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
.util
.xml
.highlighting
;
19 import com
.intellij
.codeInspection
.LocalQuickFix
;
20 import com
.intellij
.codeInspection
.ProblemHighlightType
;
21 import com
.intellij
.lang
.annotation
.Annotation
;
22 import com
.intellij
.lang
.annotation
.HighlightSeverity
;
23 import com
.intellij
.openapi
.application
.ApplicationManager
;
24 import com
.intellij
.openapi
.diagnostic
.Logger
;
25 import com
.intellij
.openapi
.util
.Pair
;
26 import com
.intellij
.openapi
.util
.TextRange
;
27 import com
.intellij
.openapi
.util
.text
.StringUtil
;
28 import com
.intellij
.psi
.PsiElement
;
29 import com
.intellij
.psi
.xml
.XmlAttributeValue
;
30 import com
.intellij
.psi
.xml
.XmlElement
;
31 import com
.intellij
.psi
.xml
.XmlTag
;
32 import com
.intellij
.psi
.xml
.XmlText
;
33 import com
.intellij
.util
.containers
.ContainerUtil
;
34 import com
.intellij
.util
.xml
.DomElement
;
35 import com
.intellij
.util
.xml
.GenericAttributeValue
;
36 import com
.intellij
.util
.xml
.GenericValue
;
37 import com
.intellij
.util
.xml
.DomFileElement
;
38 import com
.intellij
.xml
.util
.XmlTagUtil
;
39 import org
.jetbrains
.annotations
.NotNull
;
40 import org
.jetbrains
.annotations
.Nullable
;
42 import java
.util
.List
;
44 public class DomElementProblemDescriptorImpl
implements DomElementProblemDescriptor
{
45 private static final Logger LOG
= Logger
.getInstance("#com.intellij.util.xml.highlighting.DomElementProblemDescriptorImpl");
46 private final DomElement myDomElement
;
47 private final HighlightSeverity mySeverity
;
48 private final String myMessage
;
49 private final LocalQuickFix
[] myFixes
;
50 private List
<Annotation
> myAnnotations
;
51 private Pair
<TextRange
, PsiElement
> myPair
;
52 public static final Pair
<TextRange
,PsiElement
> NO_PROBLEM
= new Pair
<TextRange
, PsiElement
>(null, null);
53 private final ProblemHighlightType myHighlightType
;
55 public DomElementProblemDescriptorImpl(@NotNull final DomElement domElement
, final String message
, final HighlightSeverity type
) {
56 this(domElement
, message
, type
, LocalQuickFix
.EMPTY_ARRAY
);
59 public DomElementProblemDescriptorImpl(@NotNull final DomElement domElement
,
61 final HighlightSeverity type
,
62 @Nullable final TextRange textRange
) {
63 this(domElement
, message
, type
, textRange
, null, LocalQuickFix
.EMPTY_ARRAY
);
66 public DomElementProblemDescriptorImpl(@NotNull final DomElement domElement
,
68 final HighlightSeverity type
,
69 final LocalQuickFix
... fixes
) {
70 this(domElement
, message
, type
, null, null, fixes
);
73 public DomElementProblemDescriptorImpl(@NotNull final DomElement domElement
,
75 final HighlightSeverity type
,
76 @Nullable final TextRange textRange
,
77 ProblemHighlightType highlightType
,
78 final LocalQuickFix
... fixes
) {
79 myDomElement
= domElement
;
80 final XmlElement element
= domElement
.getXmlElement();
81 if (element
!= null && !ApplicationManager
.getApplication().isUnitTestMode()) {
82 //LOG.assertTrue(element.isPhysical(), "Problems may not be created for non-physical DOM elements");
88 if (textRange
!= null) {
89 final PsiElement psiElement
= getPsiElement();
90 LOG
.assertTrue(psiElement
!= null, "Problems with explicit text range can't be created for DOM elements without underlying XML element");
91 myPair
= new Pair
<TextRange
, PsiElement
>(textRange
, psiElement
);
93 myHighlightType
= highlightType
;
97 public DomElement
getDomElement() {
102 public HighlightSeverity
getHighlightSeverity() {
107 public String
getDescriptionTemplate() {
108 return myMessage
== null ?
"" : myMessage
;
112 public LocalQuickFix
[] getFixes() {
117 public final List
<Annotation
> getAnnotations() {
118 if (myAnnotations
== null) {
119 myAnnotations
= ContainerUtil
.createMaybeSingletonList(DomElementsHighlightingUtil
.createAnnotation(this));
121 return myAnnotations
;
124 public void highlightWholeElement() {
125 final PsiElement psiElement
= getPsiElement();
126 if (psiElement
instanceof XmlAttributeValue
) {
127 final PsiElement attr
= psiElement
.getParent();
128 myPair
= Pair
.create(new TextRange(0, attr
.getTextLength()), attr
);
130 else if (psiElement
!= null) {
131 final XmlTag tag
= (XmlTag
)(psiElement
instanceof XmlTag ? psiElement
: psiElement
.getParent());
132 myPair
= new Pair
<TextRange
, PsiElement
>(new TextRange(0, tag
.getTextLength()), tag
);
136 public Pair
<TextRange
,PsiElement
> getProblemRange() {
137 if (myPair
== null) {
138 myPair
= computeProblemRange();
144 protected Pair
<TextRange
,PsiElement
> computeProblemRange() {
145 final PsiElement element
= getPsiElement();
147 if (element
!= null) {
148 if (element
instanceof XmlTag
) {
149 return createTagNameRange((XmlTag
)element
);
152 int length
= element
.getTextRange().getLength();
153 TextRange range
= TextRange
.from(0, length
);
154 if (element
instanceof XmlAttributeValue
) {
155 final String value
= ((XmlAttributeValue
)element
).getValue();
156 if (StringUtil
.isNotEmpty(value
)) {
157 range
= TextRange
.from(element
.getText().indexOf(value
), value
.length());
160 return Pair
.create(range
, element
);
163 final XmlTag tag
= getParentXmlTag();
165 return createTagNameRange(tag
);
170 private static Pair
<TextRange
, PsiElement
> createTagNameRange(final XmlTag tag
) {
171 final PsiElement startToken
= XmlTagUtil
.getStartTagNameElement(tag
);
172 assert startToken
!= null;
173 return Pair
.create(startToken
.getTextRange().shiftRight(-tag
.getTextRange().getStartOffset()), (PsiElement
)tag
);
176 public String
toString() {
177 return myDomElement
+ "; " + myMessage
;
180 public boolean equals(final Object o
) {
181 if (this == o
) return true;
182 if (o
== null || getClass() != o
.getClass()) return false;
184 final DomElementProblemDescriptorImpl that
= (DomElementProblemDescriptorImpl
)o
;
186 if (myDomElement
!= null ?
!myDomElement
.equals(that
.myDomElement
) : that
.myDomElement
!= null) return false;
187 if (!myMessage
.equals(that
.myMessage
)) return false;
188 if (!mySeverity
.equals(that
.mySeverity
)) return false;
193 public int hashCode() {
195 result
= (myDomElement
!= null ? myDomElement
.hashCode() : 0);
196 result
= 31 * result
+ mySeverity
.hashCode();
197 result
= 31 * result
+ myMessage
.hashCode();
202 private PsiElement
getPsiElement() {
203 if (myDomElement
instanceof DomFileElement
) {
204 return ((DomFileElement
)myDomElement
).getFile();
207 if (myDomElement
instanceof GenericAttributeValue
) {
208 final GenericAttributeValue attributeValue
= (GenericAttributeValue
)myDomElement
;
209 final XmlAttributeValue value
= attributeValue
.getXmlAttributeValue();
210 return value
!= null && StringUtil
.isNotEmpty(value
.getText()) ? value
: attributeValue
.getXmlElement();
212 final XmlTag tag
= myDomElement
.getXmlTag();
213 if (myDomElement
instanceof GenericValue
&& tag
!= null) {
214 final XmlText
[] textElements
= tag
.getValue().getTextElements();
215 if (textElements
.length
> 0) {
216 return textElements
[0];
224 private XmlTag
getParentXmlTag() {
225 DomElement parent
= myDomElement
.getParent();
226 while (parent
!= null) {
227 if (parent
.getXmlTag() != null) return parent
.getXmlTag();
228 parent
= parent
.getParent();
234 public ProblemHighlightType
getHighlightType() {
235 return myHighlightType
;