Inspections - pass onTheFly into ProblemDescriptors & use it to create LAZY refs...
[fedora-idea.git] / platform / lang-impl / src / com / intellij / codeInspection / ex / ProblemDescriptorImpl.java
blob6a04b2ebb44d44969e5e6d11b6f3c981b52bda95
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.codeInspection.ex;
19 import com.intellij.codeInspection.*;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.editor.Document;
23 import com.intellij.openapi.editor.colors.TextAttributesKey;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.util.TextRange;
26 import com.intellij.pom.Navigatable;
27 import com.intellij.psi.*;
28 import com.intellij.psi.util.PsiTreeUtil;
29 import com.intellij.psi.util.PsiUtilBase;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
33 /**
34 * @author max
36 public class ProblemDescriptorImpl extends CommonProblemDescriptorImpl implements ProblemDescriptor {
37 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.ProblemDescriptorImpl");
39 @NotNull private final SmartPsiElementPointer myStartSmartPointer;
40 @Nullable private final SmartPsiElementPointer myEndSmartPointer;
43 private final ProblemHighlightType myHighlightType;
44 private Navigatable myNavigatable;
45 private final boolean myAfterEndOfLine;
46 private final TextRange myTextRangeInElement;
47 private final boolean myShowTooltip;
48 private final HintAction myHintAction;
49 private TextAttributesKey myEnforcedTextAttributes;
51 public ProblemDescriptorImpl(@NotNull PsiElement startElement, @NotNull PsiElement endElement, String descriptionTemplate, LocalQuickFix[] fixes,
52 ProblemHighlightType highlightType,
53 boolean isAfterEndOfLine,
54 final TextRange rangeInElement,
55 boolean onTheFly) {
56 this(startElement, endElement, descriptionTemplate, fixes, highlightType, isAfterEndOfLine, rangeInElement, null, onTheFly);
59 public ProblemDescriptorImpl(@NotNull PsiElement startElement, @NotNull PsiElement endElement, String descriptionTemplate, LocalQuickFix[] fixes,
60 ProblemHighlightType highlightType,
61 boolean isAfterEndOfLine,
62 final TextRange rangeInElement,
63 @Nullable HintAction hintAction,
64 boolean onTheFly) {
65 this(startElement, endElement, descriptionTemplate, fixes, highlightType, isAfterEndOfLine, rangeInElement, true, hintAction, onTheFly);
68 public ProblemDescriptorImpl(@NotNull PsiElement startElement, @NotNull PsiElement endElement, String descriptionTemplate, LocalQuickFix[] fixes,
69 ProblemHighlightType highlightType,
70 boolean isAfterEndOfLine,
71 final TextRange rangeInElement,
72 final boolean tooltip,
73 @Nullable HintAction hintAction,
74 boolean onTheFly) {
76 super(fixes, descriptionTemplate);
77 myShowTooltip = tooltip;
78 myHintAction = hintAction;
79 LOG.assertTrue(startElement.isValid(), startElement);
80 LOG.assertTrue(startElement == endElement || endElement.isValid(), endElement);
81 assertPhysical(startElement);
82 if (startElement != endElement) assertPhysical(endElement);
84 if (startElement.getTextRange().getStartOffset() >= endElement.getTextRange().getEndOffset()) {
85 if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) {
86 LOG.error("Empty PSI elements should not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement);
90 myHighlightType = highlightType;
91 final Project project = startElement.getProject();
92 final boolean useLazy = !onTheFly || ApplicationManager.getApplication().isHeadlessEnvironment();
93 final SmartPointerManager manager = SmartPointerManager.getInstance(project);
94 myStartSmartPointer = useLazy? manager.createLazyPointer(startElement) : manager.createSmartPsiElementPointer(startElement);
95 myEndSmartPointer = startElement == endElement ? null : useLazy ? manager.createLazyPointer(endElement) : manager.createSmartPsiElementPointer(endElement);
97 myAfterEndOfLine = isAfterEndOfLine;
98 myTextRangeInElement = rangeInElement;
101 protected void assertPhysical(final PsiElement element) {
102 if (!element.isPhysical()) {
103 LOG.error("Non-physical PsiElement. Physical element is required to be able to anchor the problem in the source tree: " +
104 element + "; file: " + element.getContainingFile());
108 public PsiElement getPsiElement() {
109 PsiElement startElement = getStartElement();
110 if (myEndSmartPointer == null) {
111 return startElement;
113 PsiElement endElement = getEndElement();
114 if (startElement == endElement) {
115 return startElement;
117 if (startElement == null || endElement == null) return null;
118 return PsiTreeUtil.findCommonParent(startElement, endElement);
121 public PsiElement getStartElement() {
122 return myStartSmartPointer.getElement();
125 public PsiElement getEndElement() {
126 return myEndSmartPointer == null ? getStartElement() : myEndSmartPointer.getElement();
129 public int getLineNumber() {
130 PsiElement psiElement = getPsiElement();
131 if (psiElement == null) return -1;
132 if (!psiElement.isValid()) return -1;
133 LOG.assertTrue(psiElement.isPhysical());
134 PsiFile containingFile = psiElement.getContainingFile();
135 PsiElement containingFileContext = containingFile.getContext();
136 if (containingFileContext != null) {
137 containingFile = containingFileContext.getContainingFile();
139 Document document = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(containingFile);
140 if (document == null) return -1;
141 TextRange textRange = getTextRange();
142 if (textRange == null) return -1;
143 if (containingFileContext != null) {
144 textRange = textRange.shiftRight(PsiUtilBase.findInjectedElementOffsetInRealDocument(psiElement));
146 return document.getLineNumber(textRange.getStartOffset()) + 1;
149 public ProblemHighlightType getHighlightType() {
150 return myHighlightType;
153 public boolean isAfterEndOfLine() {
154 return myAfterEndOfLine;
157 public void setTextAttributes(TextAttributesKey key) {
158 myEnforcedTextAttributes = key;
161 public TextAttributesKey getEnforcedTextAttributes() {
162 return myEnforcedTextAttributes;
165 public TextRange getTextRangeForNavigation() {
166 TextRange textRange = getTextRange();
167 if (textRange == null) return null;
168 return textRange.shiftRight(PsiUtilBase.findInjectedElementOffsetInRealDocument(getPsiElement()));
171 public TextRange getTextRange() {
172 PsiElement startElement = getStartElement();
173 PsiElement endElement = myEndSmartPointer == null ? startElement : getEndElement();
174 if (startElement == null || endElement == null) {
175 return null;
178 TextRange textRange = startElement.getTextRange();
179 if (startElement == endElement) {
180 if (isAfterEndOfLine()) return new TextRange(textRange.getEndOffset(), textRange.getEndOffset());
181 if (myTextRangeInElement != null) {
182 return new TextRange(textRange.getStartOffset() + myTextRangeInElement.getStartOffset(),
183 textRange.getStartOffset() + myTextRangeInElement.getEndOffset());
185 return textRange;
187 return new TextRange(textRange.getStartOffset(), endElement.getTextRange().getEndOffset());
190 public Navigatable getNavigatable() {
191 return myNavigatable;
194 public void setNavigatable(final Navigatable navigatable) {
195 myNavigatable = navigatable;
198 public HintAction getHintAction() {
199 return myHintAction;
202 public boolean showTooltip() {
203 return myShowTooltip;