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
.codeHighlighting
.HighlightDisplayLevel
;
20 import com
.intellij
.codeInspection
.InspectionManager
;
21 import com
.intellij
.codeInspection
.ProblemDescriptor
;
22 import com
.intellij
.codeInspection
.XmlSuppressableInspectionTool
;
23 import com
.intellij
.openapi
.application
.ApplicationManager
;
24 import com
.intellij
.openapi
.diagnostic
.Logger
;
25 import com
.intellij
.psi
.PsiFile
;
26 import com
.intellij
.psi
.xml
.XmlElement
;
27 import com
.intellij
.psi
.xml
.XmlFile
;
28 import com
.intellij
.psi
.xml
.XmlTag
;
29 import com
.intellij
.util
.Consumer
;
30 import com
.intellij
.util
.Function
;
31 import com
.intellij
.util
.containers
.ContainerUtil
;
32 import com
.intellij
.util
.xml
.*;
33 import com
.intellij
.util
.xml
.reflect
.AbstractDomChildrenDescription
;
34 import gnu
.trove
.THashSet
;
35 import org
.jetbrains
.annotations
.NotNull
;
36 import org
.jetbrains
.annotations
.Nullable
;
38 import java
.util
.Arrays
;
39 import java
.util
.Collection
;
40 import java
.util
.List
;
44 * @author Dmitry Avdeev
45 * @see com.intellij.util.xml.highlighting.BasicDomElementsInspection
47 public abstract class DomElementsInspection
<T
extends DomElement
> extends XmlSuppressableInspectionTool
{
48 private static final Logger LOG
= Logger
.getInstance("#com.intellij.util.xml.highlighting.DomElementsInspection");
50 private final Set
<Class
<?
extends T
>> myDomClasses
;
52 public DomElementsInspection(Class
<?
extends T
> domClass
, @NotNull Class
<?
extends T
>... additonalClasses
) {
53 myDomClasses
= new THashSet
<Class
<?
extends T
>>(Arrays
.asList(additonalClasses
));
54 myDomClasses
.add(domClass
);
58 * This method is called internally in {@link com.intellij.util.xml.highlighting.DomElementAnnotationsManager#checkFileElement(com.intellij.util.xml.DomFileElement, DomElementsInspection)},
59 * it should add some problems to the annotation holder. The default implementation performs recursive tree traversal, and calls
60 * {@link #checkDomElement(com.intellij.util.xml.DomElement, DomElementAnnotationHolder, DomHighlightingHelper)} for each element.
61 * @param domFileElement file element to check
62 * @param holder the place to store problems
64 public void checkFileElement(DomFileElement
<T
> domFileElement
, final DomElementAnnotationHolder holder
) {
65 final DomHighlightingHelper helper
=
66 DomElementAnnotationsManager
.getInstance(domFileElement
.getManager().getProject()).getHighlightingHelper();
67 final Consumer
<DomElement
> consumer
= new Consumer
<DomElement
>() {
68 public void consume(final DomElement element
) {
69 checkChildren(element
, this);
70 checkDomElement(element
, holder
, helper
);
73 consumer
.consume(domFileElement
.getRootElement());
76 @SuppressWarnings({"MethodMayBeStatic"})
77 protected void checkChildren(final DomElement element
, Consumer
<DomElement
> visitor
) {
78 final XmlElement xmlElement
= element
.getXmlElement();
79 if (xmlElement
instanceof XmlTag
) {
80 for (final DomElement child
: DomUtil
.getDefinedChildren(element
, true, true)) {
81 final XmlElement element1
= child
.getXmlElement();
82 if (element1
== null) {
83 LOG
.assertTrue(false, "child=" + child
+ "; parent=" + element
);
85 if (element1
.isPhysical()) {
86 visitor
.consume(child
);
90 for (final AbstractDomChildrenDescription description
: element
.getGenericInfo().getChildrenDescriptions()) {
91 if (description
.getAnnotation(Required
.class) != null) {
92 for (final DomElement child
: description
.getValues(element
)) {
93 if (!DomUtil
.hasXml(child
)) {
94 visitor
.consume(child
);
103 * @return the classes passed earlier to the constructor
105 public final Set
<Class
<?
extends T
>> getDomClasses() {
110 * Not intended to be overriden or called by implementors.
111 * Override {@link #checkFileElement(com.intellij.util.xml.DomFileElement, DomElementAnnotationHolder)} (which is preferred) or
112 * {@link #checkDomElement(com.intellij.util.xml.DomElement, DomElementAnnotationHolder, DomHighlightingHelper)} instead.
115 public ProblemDescriptor
[] checkFile(@NotNull PsiFile file
, @NotNull InspectionManager manager
, boolean isOnTheFly
) {
116 if (file
instanceof XmlFile
&& (file
.isPhysical() || ApplicationManager
.getApplication().isUnitTestMode())) {
117 for (Class
<?
extends T
> domClass
: myDomClasses
) {
118 final DomFileElement
<?
extends T
> fileElement
= DomManager
.getDomManager(file
.getProject()).getFileElement((XmlFile
)file
, domClass
);
119 if (fileElement
!= null) {
120 return checkDomFile((DomFileElement
<T
>)fileElement
, manager
, isOnTheFly
);
128 public HighlightDisplayLevel
getDefaultLevel() {
129 return HighlightDisplayLevel
.ERROR
;
132 public boolean isEnabledByDefault() {
137 * not intended to be overriden or called by implementors
140 protected ProblemDescriptor
[] checkDomFile(@NotNull final DomFileElement
<T
> domFileElement
,
141 @NotNull final InspectionManager manager
,
142 final boolean isOnTheFly
) {
143 final DomElementAnnotationsManager annotationsManager
= DomElementAnnotationsManager
.getInstance(manager
.getProject());
145 final List
<DomElementProblemDescriptor
> list
= annotationsManager
.checkFileElement(domFileElement
, this);
146 List
<ProblemDescriptor
> problems
=
147 ContainerUtil
.concat(list
, new Function
<DomElementProblemDescriptor
, Collection
<?
extends ProblemDescriptor
>>() {
148 public Collection
<ProblemDescriptor
> fun(final DomElementProblemDescriptor s
) {
149 return annotationsManager
.createProblemDescriptors(manager
, s
);
152 return problems
.toArray(new ProblemDescriptor
[problems
.size()]);
156 * Check particular DOM element for problems. The inspection implementor should focus on this method.
157 * The default implementation throws {@link UnsupportedOperationException}.
158 * See {@link com.intellij.util.xml.highlighting.BasicDomElementsInspection}
159 * @param element element to check
160 * @param holder a place to add problems to
161 * @param helper helper object
163 protected void checkDomElement(DomElement element
, DomElementAnnotationHolder holder
, DomHighlightingHelper helper
) {
164 throw new UnsupportedOperationException("checkDomElement() is not implemented in " + getClass().getName());