| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.lang.annotation; |
| |
| import com.intellij.codeInsight.daemon.HighlightDisplayKey; |
| import com.intellij.codeInsight.intention.IntentionAction; |
| import com.intellij.codeInspection.*; |
| import com.intellij.openapi.editor.HighlighterColors; |
| import com.intellij.openapi.editor.colors.CodeInsightColors; |
| import com.intellij.openapi.editor.colors.TextAttributesKey; |
| import com.intellij.openapi.editor.markup.GutterIconRenderer; |
| import com.intellij.openapi.editor.markup.TextAttributes; |
| import com.intellij.openapi.util.Segment; |
| import com.intellij.openapi.util.TextRange; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Defines an annotation, which is displayed as a gutter bar mark or an extra highlight in the editor. |
| * |
| * @author max |
| * @see Annotator |
| * @see AnnotationHolder |
| * @see com.intellij.openapi.editor.markup.RangeHighlighter |
| */ |
| public final class Annotation implements Segment { |
| private final int myStartOffset; |
| private final int myEndOffset; |
| private final HighlightSeverity mySeverity; |
| private final String myMessage; |
| |
| private ProblemHighlightType myHighlightType = ProblemHighlightType.GENERIC_ERROR_OR_WARNING; |
| private TextAttributesKey myEnforcedAttributesKey; |
| private TextAttributes myEnforcedAttributes; |
| |
| private List<QuickFixInfo> myQuickFixes = null; |
| private Boolean myNeedsUpdateOnTyping = null; |
| private String myTooltip; |
| private boolean myAfterEndOfLine = false; |
| private boolean myIsFileLevelAnnotation = false; |
| private GutterIconRenderer myGutterIconRenderer; |
| @Nullable |
| private ProblemGroup myProblemGroup; |
| private List<QuickFixInfo> myBatchFixes; |
| |
| public static class QuickFixInfo { |
| @NotNull |
| public final IntentionAction quickFix; |
| @NotNull |
| public final TextRange textRange; |
| public final HighlightDisplayKey key; |
| |
| public QuickFixInfo(@NotNull IntentionAction fix, @NotNull TextRange range, @Nullable final HighlightDisplayKey key) { |
| this.key = key; |
| quickFix = fix; |
| textRange = range; |
| } |
| |
| @Override |
| public String toString() { |
| return quickFix.toString(); |
| } |
| } |
| |
| /** |
| * Creates an instance of the annotation. |
| * |
| * @param startOffset the start offset of the text range covered by the annotation. |
| * @param endOffset the end offset of the text range covered by the annotation. |
| * @param severity the severity of the problem indicated by the annotation (highlight, warning or error). |
| * @param message the description of the annotation (shown in the status bar or by "View | Error Description" action) |
| * @param tooltip the tooltip for the annotation (shown when hovering the mouse in the gutter bar) |
| * @see AnnotationHolder#createErrorAnnotation |
| * @see AnnotationHolder#createWarningAnnotation |
| * @see AnnotationHolder#createInfoAnnotation |
| */ |
| public Annotation(final int startOffset, final int endOffset, @NotNull HighlightSeverity severity, final String message, String tooltip) { |
| assert startOffset <= endOffset : startOffset + ":" + endOffset; |
| assert startOffset >= 0 : "Start offset must not be negative: " +startOffset; |
| myStartOffset = startOffset; |
| myEndOffset = endOffset; |
| myMessage = message; |
| myTooltip = tooltip; |
| mySeverity = severity; |
| } |
| |
| /** |
| * Registers a quick fix for the annotation. |
| * |
| * @param fix the quick fix implementation. |
| */ |
| public void registerFix(@NotNull IntentionAction fix) { |
| registerFix(fix, null); |
| } |
| |
| public void registerFix(@NotNull IntentionAction fix, TextRange range) { |
| registerFix(fix,range, null); |
| } |
| |
| public void registerFix(@NotNull LocalQuickFix fix, @Nullable TextRange range, @Nullable HighlightDisplayKey key, |
| @NotNull ProblemDescriptor problemDescriptor) { |
| if (range == null) { |
| range = new TextRange(myStartOffset, myEndOffset); |
| } |
| if (myQuickFixes == null) { |
| myQuickFixes = new ArrayList<QuickFixInfo>(); |
| } |
| myQuickFixes.add(new QuickFixInfo(new LocalQuickFixAsIntentionAdapter(fix, problemDescriptor), range, key)); |
| } |
| |
| /** |
| * Registers a quick fix for the annotation which is only available on a particular range of text |
| * within the annotation. |
| * |
| * @param fix the quick fix implementation. |
| * @param range the text range (relative to the document) where the quick fix is available. |
| */ |
| public void registerFix(@NotNull IntentionAction fix, @Nullable TextRange range, @Nullable final HighlightDisplayKey key) { |
| if (range == null) { |
| range = new TextRange(myStartOffset, myEndOffset); |
| } |
| if (myQuickFixes == null) { |
| myQuickFixes = new ArrayList<QuickFixInfo>(); |
| } |
| myQuickFixes.add(new QuickFixInfo(fix, range, key)); |
| } |
| |
| /** |
| * Registers a quickfix which would be available during batch mode only, |
| * in particular during com.intellij.codeInspection.DefaultHighlightVisitorBasedInspection run |
| */ |
| public <T extends IntentionAction & LocalQuickFix> void registerBatchFix(@NotNull T fix, @Nullable TextRange range, @Nullable final HighlightDisplayKey key) { |
| if (range == null) { |
| range = new TextRange(myStartOffset, myEndOffset); |
| } |
| |
| if (myBatchFixes == null) { |
| myBatchFixes = new ArrayList<QuickFixInfo>(); |
| } |
| myBatchFixes.add(new QuickFixInfo(fix, range, key)); |
| } |
| |
| /** |
| * Register a quickfix which would be available onTheFly and in the batch mode. Should implement both IntentionAction and LocalQuickFix. |
| */ |
| public <T extends IntentionAction & LocalQuickFix> void registerUniversalFix(@NotNull T fix, @Nullable TextRange range, @Nullable final HighlightDisplayKey key) { |
| registerBatchFix(fix, range, key); |
| registerFix(fix, range, key); |
| } |
| /** |
| * Sets a flag indicating what happens with the annotation when the user starts typing. |
| * If the parameter is true, the annotation is removed as soon as the user starts typing |
| * and is possibly restored by a later run of the annotator. If false, the annotation remains |
| * in place while the user is typing. |
| * |
| * @param b whether the annotation needs to be removed on typing. |
| * @see #needsUpdateOnTyping() |
| */ |
| public void setNeedsUpdateOnTyping(boolean b) { |
| myNeedsUpdateOnTyping = Boolean.valueOf(b); |
| } |
| |
| /** |
| * Gets a flag indicating what happens with the annotation when the user starts typing. |
| * |
| * @return true if the annotation is removed on typing, false otherwise. |
| * @see #setNeedsUpdateOnTyping(boolean) |
| */ |
| public boolean needsUpdateOnTyping() { |
| if (myNeedsUpdateOnTyping == null) { |
| return mySeverity != HighlightSeverity.INFORMATION; |
| } |
| |
| return myNeedsUpdateOnTyping.booleanValue(); |
| } |
| |
| /** |
| * Returns the start offset of the text range covered by the annotation. |
| * |
| * @return the annotation start offset. |
| */ |
| @Override |
| public int getStartOffset() { |
| return myStartOffset; |
| } |
| |
| /** |
| * Returns the end offset of the text range covered by the annotation. |
| * |
| * @return the annotation end offset. |
| */ |
| @Override |
| public int getEndOffset() { |
| return myEndOffset; |
| } |
| |
| /** |
| * Returns the severity of the problem indicated by the annotation (highlight, warning or error). |
| * |
| * @return the annotation severity. |
| */ |
| @NotNull |
| public HighlightSeverity getSeverity() { |
| return mySeverity; |
| } |
| |
| /** |
| * If the annotation matches one of commonly encountered problem types, returns the ID of that |
| * problem type so that an appropriate color can be used for highlighting the annotation. |
| * |
| * @return the common problem type. |
| */ |
| public ProblemHighlightType getHighlightType() { |
| return myHighlightType; |
| } |
| |
| /** |
| * Returns the text attribute key used for highlighting the annotation. If not specified |
| * explicitly, the key is determined automatically based on the problem highlight type and |
| * the annotation severity. |
| * |
| * @return the text attribute key used for highlighting |
| */ |
| @NotNull |
| public TextAttributesKey getTextAttributes() { |
| if (myEnforcedAttributesKey != null) return myEnforcedAttributesKey; |
| |
| if (myHighlightType == ProblemHighlightType.GENERIC_ERROR_OR_WARNING) { |
| if (mySeverity == HighlightSeverity.ERROR) return CodeInsightColors.ERRORS_ATTRIBUTES; |
| if (mySeverity == HighlightSeverity.WARNING) return CodeInsightColors.WARNINGS_ATTRIBUTES; |
| if (mySeverity == HighlightSeverity.WEAK_WARNING) return CodeInsightColors.WEAK_WARNING_ATTRIBUTES; |
| } |
| |
| if (myHighlightType == ProblemHighlightType.GENERIC_ERROR) { |
| return CodeInsightColors.ERRORS_ATTRIBUTES; |
| } |
| |
| if (myHighlightType == ProblemHighlightType.LIKE_DEPRECATED) { |
| return CodeInsightColors.DEPRECATED_ATTRIBUTES; |
| } |
| if (myHighlightType == ProblemHighlightType.LIKE_UNUSED_SYMBOL) { |
| return CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES; |
| } |
| if (myHighlightType == ProblemHighlightType.LIKE_UNKNOWN_SYMBOL || myHighlightType == ProblemHighlightType.ERROR) { |
| return CodeInsightColors.WRONG_REFERENCES_ATTRIBUTES; |
| } |
| return HighlighterColors.TEXT; |
| } |
| |
| public TextAttributes getEnforcedTextAttributes() { |
| return myEnforcedAttributes; |
| } |
| |
| /** |
| * Sets the text attributes used for highlighting the annotation. |
| * |
| * @param enforcedAttributes the text attributes for highlighting, |
| */ |
| public void setEnforcedTextAttributes(final TextAttributes enforcedAttributes) { |
| myEnforcedAttributes = enforcedAttributes; |
| } |
| |
| /** |
| * Returns the list of quick fixes registered for the annotation. |
| * |
| * @return the list of quick fixes, or null if none have been registered. |
| */ |
| |
| @Nullable |
| public List<QuickFixInfo> getQuickFixes() { |
| return myQuickFixes; |
| } |
| |
| @Nullable |
| public List<QuickFixInfo> getBatchFixes() { |
| return myBatchFixes; |
| } |
| |
| /** |
| * Returns the description of the annotation (shown in the status bar or by "View | Error Description" action). |
| * |
| * @return the description of the annotation. |
| */ |
| public String getMessage() { |
| return myMessage; |
| } |
| |
| /** |
| * Returns the tooltip for the annotation (shown when hovering the mouse in the gutter bar). |
| * |
| * @return the tooltip for the annotation. |
| */ |
| public String getTooltip() { |
| return myTooltip; |
| } |
| |
| /** |
| * Sets the tooltip for the annotation (shown when hovering the mouse in the gutter bar). |
| * |
| * @param tooltip the tooltip text. |
| */ |
| public void setTooltip(final String tooltip) { |
| myTooltip = tooltip; |
| } |
| |
| /** |
| * If the annotation matches one of commonly encountered problem types, sets the ID of that |
| * problem type so that an appropriate color can be used for highlighting the annotation. |
| * |
| * @param highlightType the ID of the problem type. |
| */ |
| public void setHighlightType(final ProblemHighlightType highlightType) { |
| myHighlightType = highlightType; |
| } |
| |
| /** |
| * Sets the text attributes key used for highlighting the annotation. |
| * |
| * @param enforcedAttributes the text attributes key for highlighting, |
| */ |
| public void setTextAttributes(final TextAttributesKey enforcedAttributes) { |
| myEnforcedAttributesKey = enforcedAttributes; |
| } |
| |
| /** |
| * Returns the flag indicating whether the annotation is shown after the end of line containing it. |
| * |
| * @return true if the annotation is shown after the end of line, false otherwise. |
| */ |
| public boolean isAfterEndOfLine() { |
| return myAfterEndOfLine; |
| } |
| |
| /** |
| * Sets the flag indicating whether the annotation is shown after the end of line containing it. |
| * This can be used for errors like "unclosed string literal", "missing semicolon" and so on. |
| * |
| * @param afterEndOfLine true if the annotation should be shown after the end of line, false otherwise. |
| */ |
| public void setAfterEndOfLine(final boolean afterEndOfLine) { |
| myAfterEndOfLine = afterEndOfLine; |
| } |
| |
| /** |
| * File level annotations are visualized differently than lesser range annotations by showing a title bar on top of the |
| * editor rather than applying text attributes to the text range. |
| * @return <code>true</code> if this particular annotation have been defined as file level. |
| */ |
| public boolean isFileLevelAnnotation() { |
| return myIsFileLevelAnnotation; |
| } |
| |
| /** |
| * File level annotations are visualized differently than lesser range annotations by showing a title bar on top of the |
| * editor rather than applying text attributes to the text range. |
| * @param isFileLevelAnnotation <code>true</code> if this particular annotation should be visualized at file level. |
| */ |
| public void setFileLevelAnnotation(final boolean isFileLevelAnnotation) { |
| myIsFileLevelAnnotation = isFileLevelAnnotation; |
| } |
| |
| /** |
| * Gets the renderer used to draw the gutter icon in the region covered by the annotation. |
| * |
| * @return the gutter icon renderer instance. |
| */ |
| @Nullable |
| public GutterIconRenderer getGutterIconRenderer() { |
| return myGutterIconRenderer; |
| } |
| |
| /** |
| * Sets the renderer used to draw the gutter icon in the region covered by the annotation. |
| * |
| * @param gutterIconRenderer the gutter icon renderer instance. |
| */ |
| public void setGutterIconRenderer(@Nullable final GutterIconRenderer gutterIconRenderer) { |
| myGutterIconRenderer = gutterIconRenderer; |
| } |
| |
| /** |
| * Gets the unique object, which is the same for all of the problems of this group |
| * |
| * @return the problem group |
| */ |
| @Nullable |
| public ProblemGroup getProblemGroup() { |
| return myProblemGroup; |
| } |
| |
| /** |
| * Sets the unique object, which is the same for all of the problems of this group |
| * |
| * @param problemGroup the problem group |
| */ |
| public void setProblemGroup(@Nullable ProblemGroup problemGroup) { |
| myProblemGroup = problemGroup; |
| } |
| |
| @NonNls |
| public String toString() { |
| return "Annotation(" + |
| "message='" + myMessage + "'" + |
| ", severity='" + mySeverity + "'" + |
| ", toolTip='" + myTooltip + "'" + |
| ")"; |
| } |
| } |