2 * Copyright 2005 Sascha Weinreuter
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.
16 package org
.intellij
.lang
.xpath
.validation
.inspections
;
18 import com
.intellij
.codeInspection
.InspectionManager
;
19 import com
.intellij
.codeInspection
.LocalQuickFix
;
20 import com
.intellij
.codeInspection
.ProblemHighlightType
;
21 import com
.intellij
.psi
.xml
.XmlElement
;
22 import org
.intellij
.lang
.xpath
.context
.ContextProvider
;
23 import org
.intellij
.lang
.xpath
.context
.NamespaceContext
;
24 import org
.intellij
.lang
.xpath
.psi
.PrefixedName
;
25 import org
.intellij
.lang
.xpath
.psi
.XPathNodeTest
;
26 import org
.jetbrains
.annotations
.NonNls
;
27 import org
.jetbrains
.annotations
.NotNull
;
28 import org
.jetbrains
.annotations
.Nullable
;
30 import javax
.xml
.namespace
.QName
;
31 import java
.text
.MessageFormat
;
34 public class CheckNodeTest
extends XPathInspection
{
36 private static final String SHORT_NAME
= "CheckNodeTest";
38 protected Visitor
createVisitor(InspectionManager manager
, boolean isOnTheFly
) {
39 return new MyVisitor(manager
, isOnTheFly
);
43 public String
getDisplayName() {
44 return "Check Node Test";
49 public String
getShortName() {
53 public boolean isEnabledByDefault() {
57 final static class MyVisitor
extends Visitor
{
58 MyVisitor(InspectionManager manager
, boolean isOnTheFly
) {
59 super(manager
, isOnTheFly
);
62 protected void checkNodeTest(XPathNodeTest nodeTest
) {
63 final ContextProvider contextProvider
= ContextProvider
.getContextProvider(nodeTest
.getContainingFile());
64 final XmlElement contextNode
= contextProvider
.getContextElement();
65 final NamespaceContext namespaceContext
= contextProvider
.getNamespaceContext();
66 if (namespaceContext
== null) return;
68 if (nodeTest
.isNameTest() && contextNode
!= null) {
69 final PrefixedName prefixedName
= nodeTest
.getQName();
70 assert prefixedName
!= null;
71 if (!"*".equals(prefixedName
.getLocalName())) {
74 if (nodeTest
.getPrincipalType() == XPathNodeTest
.PrincipalType
.ELEMENT
) {
75 final Set
<QName
> elementNames
= contextProvider
.getElements(true);
76 if (elementNames
!= null) {
78 for (javax
.xml
.namespace
.QName pair
: elementNames
) {
79 if (matches(nodeTest
.getQName(), pair
, namespaceContext
, contextNode
)) {
85 registerProblem(contextProvider
, prefixedName
, nodeTest
, "element");
88 } else if (nodeTest
.getPrincipalType() == XPathNodeTest
.PrincipalType
.ATTRIBUTE
) {
89 final Set
<javax
.xml
.namespace
.QName
> attributeNames
= contextProvider
.getAttributes(true);
90 if (attributeNames
!= null) {
92 for (javax
.xml
.namespace
.QName pair
: attributeNames
) {
93 if (matches(nodeTest
.getQName(), pair
, namespaceContext
, contextNode
)) {
99 registerProblem(contextProvider
, prefixedName
, nodeTest
, "attribute");
107 private void registerProblem(ContextProvider contextProvider
, PrefixedName prefixedName
, XPathNodeTest nodeTest
, String type
) {
108 final QName qName
= contextProvider
.getQName(prefixedName
, nodeTest
);
111 final String pattern
;
112 if (!"".equals(qName
.getNamespaceURI())) {
113 pattern
= "''<b>{0}</b>'' (<i>{1}</i>)";
115 pattern
= "''<b>{0}</b>''";
117 name
= MessageFormat
.format(pattern
, qName
.getLocalPart(), qName
.getNamespaceURI());
119 name
= MessageFormat
.format("''<b>{0}</b>''", prefixedName
.getLocalName());
122 final LocalQuickFix
[] fixes
= contextProvider
.getQuickFixFactory().createUnknownNodeTestFixes(nodeTest
);
123 addProblem(myManager
.createProblemDescriptor(nodeTest
, "<html>Unknown " + type
+ " name " + name
+ "</html>",
124 fixes
, ProblemHighlightType
.GENERIC_ERROR_OR_WARNING
, myOnTheFly
));
127 private static boolean matches(@Nullable PrefixedName prefixedName
, QName element
, NamespaceContext namespaceContext
, XmlElement context
) {
128 if (prefixedName
== null) return false;
129 boolean b
= prefixedName
.getLocalName().equals(element
.getLocalPart()) || "*".equals(element
.getLocalPart());
130 if (prefixedName
.getPrefix() != null) {
131 b
= b
&& element
.getNamespaceURI().equals(namespaceContext
.getNamespaceURI(prefixedName
.getPrefix(), context
));
133 b
= b
&& element
.getNamespaceURI().equals("");