tests fixed + duplicated error stripes removed from end of xml tags
[fedora-idea.git] / dom / impl / src / com / intellij / util / xml / highlighting / DomElementsHighlightingUtil.java
blob8d1f06ef9b5eedf49d165ace12c6098471406384
1 /*
2 * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
3 */
5 package com.intellij.util.xml.highlighting;
7 import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
8 import com.intellij.codeInspection.InspectionManager;
9 import com.intellij.codeInspection.ProblemDescriptor;
10 import com.intellij.codeInspection.ProblemHighlightType;
11 import com.intellij.lang.ASTNode;
12 import com.intellij.lang.annotation.Annotation;
13 import com.intellij.lang.annotation.HighlightSeverity;
14 import com.intellij.openapi.editor.colors.CodeInsightColors;
15 import com.intellij.openapi.util.Pair;
16 import com.intellij.openapi.util.TextRange;
17 import com.intellij.openapi.util.text.StringUtil;
18 import com.intellij.psi.PsiElement;
19 import com.intellij.psi.PsiReference;
20 import com.intellij.psi.xml.XmlAttributeValue;
21 import com.intellij.psi.xml.XmlChildRole;
22 import com.intellij.psi.xml.XmlTag;
23 import com.intellij.psi.xml.XmlText;
24 import com.intellij.util.Function;
25 import com.intellij.util.SmartList;
26 import com.intellij.util.xml.DomElement;
27 import com.intellij.util.xml.GenericAttributeValue;
28 import com.intellij.util.xml.GenericValue;
29 import org.jetbrains.annotations.Nullable;
31 import java.util.Arrays;
32 import java.util.List;
34 /**
35 * User: Sergey.Vasiliev
37 public class DomElementsHighlightingUtil {
38 private static final AnnotationHolderImpl EMPTY_ANNOTATION_HOLDER = new AnnotationHolderImpl() {
39 public boolean add(final Annotation annotation) {
40 return false;
44 public static List<ProblemDescriptor> createProblemDescriptors(final InspectionManager manager, final DomElementProblemDescriptor problemDescriptor) {
45 final ProblemHighlightType type = getProblemHighlightType(problemDescriptor);
46 return createProblemDescriptors(problemDescriptor, new Function<Pair<TextRange, PsiElement>, ProblemDescriptor>() {
47 public ProblemDescriptor fun(final Pair<TextRange, PsiElement> s) {
48 return manager.createProblemDescriptor(s.second, s.first, problemDescriptor.getDescriptionTemplate(), type, problemDescriptor.getFixes());
50 });
53 private static ProblemHighlightType getProblemHighlightType(final DomElementProblemDescriptor problemDescriptor) {
54 if (problemDescriptor instanceof DomElementResolveProblemDescriptor) {
55 final TextRange range = ((DomElementResolveProblemDescriptor)problemDescriptor).getPsiReference().getRangeInElement();
56 if (range.getStartOffset() != range.getEndOffset()) {
57 return ProblemHighlightType.LIKE_UNKNOWN_SYMBOL;
60 return ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
63 public static List<Annotation> createAnnotations(final DomElementProblemDescriptor problemDescriptor) {
65 return createProblemDescriptors(problemDescriptor, new Function<Pair<TextRange, PsiElement>, Annotation>() {
66 public Annotation fun(final Pair<TextRange, PsiElement> s) {
67 String text = problemDescriptor.getDescriptionTemplate();
68 if (StringUtil.isEmpty(text)) text = null;
69 final HighlightSeverity severity = problemDescriptor.getHighlightSeverity();
70 final AnnotationHolderImpl holder = EMPTY_ANNOTATION_HOLDER;
71 TextRange range = s.first;
72 if (text == null) range = TextRange.from(range.getStartOffset(), 0);
73 range = range.shiftRight(s.second.getTextRange().getStartOffset());
74 final Annotation annotation = createAnnotation(severity, holder, range, text);
75 if (problemDescriptor instanceof DomElementResolveProblemDescriptor) {
76 annotation.setTextAttributes(CodeInsightColors.WRONG_REFERENCES_ATTRIBUTES);
78 return annotation;
80 });
83 private static Annotation createAnnotation(final HighlightSeverity severity, final AnnotationHolderImpl holder, final TextRange range,
84 final String text) {
85 if (severity.compareTo(HighlightSeverity.ERROR) >= 0) return holder.createErrorAnnotation(range, text);
86 if (severity.compareTo(HighlightSeverity.WARNING) >= 0) return holder.createWarningAnnotation(range, text);
87 if (severity.compareTo(HighlightSeverity.INFO) >= 0) return holder.createInformationAnnotation(range, text);
88 return holder.createInfoAnnotation(range, text);
91 private static <T> List<T> createProblemDescriptors(final DomElementProblemDescriptor problemDescriptor, final Function<Pair<TextRange, PsiElement>, T> creator) {
92 final List<T> descritors = new SmartList<T>();
94 if (problemDescriptor instanceof DomElementResolveProblemDescriptor) {
95 final PsiReference reference = ((DomElementResolveProblemDescriptor)problemDescriptor).getPsiReference();
96 final PsiElement element = reference.getElement();
97 final TextRange referenceRange = reference.getRangeInElement();
98 final TextRange errorRange;
99 if (referenceRange.getStartOffset() == referenceRange.getEndOffset()) {
100 if (element instanceof XmlAttributeValue) {
101 errorRange = TextRange.from(referenceRange.getStartOffset() - 1, 2);
103 else {
104 errorRange = TextRange.from(referenceRange.getStartOffset(), 1);
106 } else {
107 errorRange = referenceRange;
109 descritors.add(creator.fun(Pair.create(errorRange, element)));
110 return descritors;
113 final DomElement domElement = problemDescriptor.getDomElement();
114 final PsiElement psiElement = getPsiElement(domElement);
115 if (psiElement != null && StringUtil.isNotEmpty(psiElement.getText())) {
116 if (psiElement instanceof XmlTag) {
117 final XmlTag tag = (XmlTag)psiElement;
118 addDescriptionsToTagEnds(tag, descritors, creator);
119 return descritors;
121 int start = 0;
122 int length = psiElement.getTextRange().getLength();
123 if (psiElement instanceof XmlAttributeValue) {
124 String value = ((XmlAttributeValue)psiElement).getValue();
125 if (StringUtil.isNotEmpty(value)) {
126 start = psiElement.getText().indexOf(value);
127 length = value.length();
130 return Arrays.asList(creator.fun(Pair.create(TextRange.from(start, length), psiElement)));
133 final XmlTag tag = getParentXmlTag(domElement);
134 if (tag != null) {
135 addDescriptionsToTagEnds(tag, descritors, creator);
137 return descritors;
140 private static <T> void addDescriptionsToTagEnds(final XmlTag tag, final List<T> descritors, Function<Pair<TextRange, PsiElement>, T> creator) {
141 final ASTNode node = tag.getNode();
142 assert node != null;
143 final ASTNode startNode = XmlChildRole.START_TAG_NAME_FINDER.findChild(node);
145 final int startOffset = tag.getTextRange().getStartOffset();
146 descritors.add(creator.fun(Pair.create(startNode.getTextRange().shiftRight(-startOffset), (PsiElement)tag)));
149 @Nullable
150 private static PsiElement getPsiElement(final DomElement domElement) {
151 if (domElement instanceof GenericAttributeValue) {
152 final GenericAttributeValue attributeValue = (GenericAttributeValue)domElement;
153 final XmlAttributeValue value = attributeValue.getXmlAttributeValue();
154 return value != null && StringUtil.isNotEmpty(value.getText()) ? value : attributeValue.getXmlElement();
156 final XmlTag tag = domElement.getXmlTag();
157 if (domElement instanceof GenericValue && tag != null) {
158 final XmlText[] textElements = tag.getValue().getTextElements();
159 if (textElements.length > 0) {
160 return textElements[0];
164 return tag;
167 @Nullable
168 private static XmlTag getParentXmlTag(final DomElement domElement) {
169 DomElement parent = domElement.getParent();
170 while (parent != null) {
171 if (parent.getXmlTag() != null) return parent.getXmlTag();
172 parent = parent.getParent();
174 return null;