summaryrefslogtreecommitdiff
path: root/xml
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-08-21 11:17:55 -0700
committerTor Norbye <tnorbye@google.com>2013-08-21 11:17:55 -0700
commitd34b4c8d74407f5b2be1a344e41f2ecdeb25f4fe (patch)
tree1263896cdf5d3e25697287c40cf3a1d35de8e95d /xml
parent4db7dfd37df60de478b5d99be0554bc0e06dfdba (diff)
downloadidea-d34b4c8d74407f5b2be1a344e41f2ecdeb25f4fe.tar.gz
Snapshot 32d31e4915ef17b3ec6ec4e87923f017e8e41bce from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: Idb2188c1f4e63d654aa3e3b832b9121d0be2dbe9
Diffstat (limited to 'xml')
-rw-r--r--xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java5
-rw-r--r--xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java8
-rw-r--r--xml/dom-openapi/src/com/intellij/util/xml/NonExhaustiveEnum.java23
-rw-r--r--xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java13
-rw-r--r--xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java2
-rw-r--r--xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java2
-rw-r--r--xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java2
-rw-r--r--xml/impl/src/com/intellij/xml/util/XmlAttributeValueReferenceProvider.java61
-rw-r--r--xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java1
-rw-r--r--xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java26
-rw-r--r--xml/relaxng/testData/highlighting/attribute-choice-3.xml2
-rw-r--r--xml/relaxng/testData/highlighting/fixed-attribute_2.xml2
-rw-r--r--xml/relaxng/testData/highlighting/value-choice-2.xml2
-rw-r--r--xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml2
-rw-r--r--xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties3
-rw-r--r--xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java9
-rw-r--r--xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java52
-rw-r--r--xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java121
-rw-r--r--xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java2
-rw-r--r--xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java13
-rw-r--r--xml/xml-psi-impl/src/com/intellij/xml/util/XmlAttributeValueReference.java75
-rw-r--r--xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java24
22 files changed, 348 insertions, 102 deletions
diff --git a/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java b/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
index 8dc15edb48e2..0d86645a37fc 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
@@ -3,6 +3,7 @@ package com.intellij.util.xml;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ReflectionCache;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NotNull;
@@ -60,4 +61,8 @@ public class EnumConverter<T extends Enum> extends ResolvingConverter<T>{
}
return Arrays.asList(myType.getEnumConstants());
}
+
+ public boolean isExhaustive() {
+ return !ReflectionCache.isAssignable(NonExhaustiveEnum.class, myType);
+ }
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java b/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
index b457c9d6b10a..c36c2bfa2454 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
@@ -24,6 +24,7 @@ import com.intellij.psi.xml.*;
import com.intellij.util.ProcessingContext;
import com.intellij.util.ReflectionCache;
import com.intellij.util.xml.*;
+import com.intellij.xml.util.XmlAttributeValueReferenceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -86,6 +87,13 @@ public class GenericValueReferenceProvider extends PsiReferenceProvider {
}
}
}
+ if (references.length > 0) {
+ if (converter instanceof EnumConverter && !((EnumConverter)converter).isExhaustive()) {
+ // will be handled by core XML
+ return PsiReference.EMPTY_ARRAY;
+ }
+ context.put(XmlAttributeValueReferenceProvider.SUPPRESS, Boolean.TRUE);
+ }
return references;
}
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/NonExhaustiveEnum.java b/xml/dom-openapi/src/com/intellij/util/xml/NonExhaustiveEnum.java
new file mode 100644
index 000000000000..95b522ecb32d
--- /dev/null
+++ b/xml/dom-openapi/src/com/intellij/util/xml/NonExhaustiveEnum.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.util.xml;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 21.08.13
+ */
+public interface NonExhaustiveEnum {
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
index 00d6c1e18650..bf87f35c9411 100644
--- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
@@ -71,11 +71,14 @@ public class XmlCompletionData extends CompletionData {
}
{
- final CompletionVariant variant = new CompletionVariant(createAttributeValueCompletionFilter());
- variant.includeScopeClass(XmlAttributeValue.class);
- variant.addCompletion(getAttributeValueGetter(), TailType.NONE);
- variant.addCompletionFilter(TrueFilter.INSTANCE, TailType.NONE);
- registerVariant(variant);
+ XmlAttributeValueGetter getter = getAttributeValueGetter();
+ if (getter != null) {
+ final CompletionVariant variant = new CompletionVariant(createAttributeValueCompletionFilter());
+ variant.includeScopeClass(XmlAttributeValue.class);
+ variant.addCompletion(getter, TailType.NONE);
+ variant.addCompletionFilter(TrueFilter.INSTANCE, TailType.NONE);
+ registerVariant(variant);
+ }
}
final ElementFilter entityCompletionFilter = createXmlEntityCompletionFilter();
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java
index 0fb6ef242977..142e7df51f21 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/DependentNSReferenceQuickFixProvider.java
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
*/
public class DependentNSReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<DependentNSReference> {
@Override
- public void registerFixes(DependentNSReference ref, QuickFixActionRegistrar registrar) {
+ public void registerFixes(@NotNull DependentNSReference ref, @NotNull QuickFixActionRegistrar registrar) {
registrar.register(new FetchExtResourceAction(ref.isForceFetchResultValid()));
registrar.register(new ManuallySetupExtResourceAction());
registrar.register(new IgnoreExtResourceAction());
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java
index 6b8bebde5652..eb3d558b6e18 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferenceQuickFixProvider.java
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.PropertyKey;
*/
public class SchemaReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<SchemaReferencesProvider.TypeOrElementOrAttributeReference> {
@Override
- public void registerFixes(SchemaReferencesProvider.TypeOrElementOrAttributeReference ref, QuickFixActionRegistrar registrar) {
+ public void registerFixes(@NotNull SchemaReferencesProvider.TypeOrElementOrAttributeReference ref, @NotNull QuickFixActionRegistrar registrar) {
if (ref.getType() == SchemaReferencesProvider.TypeOrElementOrAttributeReference.ReferenceType.TypeReference) {
registrar.register(
new CreateXmlElementIntentionAction("xml.schema.create.complex.type.intention.name", SchemaReferencesProvider.COMPLEX_TYPE_TAG_NAME, ref)
diff --git a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java
index 1c63a9737aef..13bae7ba826f 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/URLReferenceQuickFixProvider.java
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
*/
public class URLReferenceQuickFixProvider extends UnresolvedReferenceQuickFixProvider<URLReference> {
@Override
- public void registerFixes(URLReference ref, QuickFixActionRegistrar registrar) {
+ public void registerFixes(@NotNull URLReference ref, @NotNull QuickFixActionRegistrar registrar) {
registrar.register(new FetchExtResourceAction());
registrar.register(new ManuallySetupExtResourceAction());
registrar.register(new IgnoreExtResourceAction());
diff --git a/xml/impl/src/com/intellij/xml/util/XmlAttributeValueReferenceProvider.java b/xml/impl/src/com/intellij/xml/util/XmlAttributeValueReferenceProvider.java
new file mode 100644
index 000000000000..33d72010189d
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/XmlAttributeValueReferenceProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import com.intellij.xml.impl.schema.XmlSchemaTagsProcessor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 15.08.13
+ */
+public class XmlAttributeValueReferenceProvider extends PsiReferenceProvider {
+
+ public final static Key<Boolean> SUPPRESS = Key.create("suppress attribute value references");
+
+ @NotNull
+ @Override
+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
+
+ if (XmlSchemaTagsProcessor.PROCESSING_FLAG.get() != null || context.get(SUPPRESS) != null) {
+ return PsiReference.EMPTY_ARRAY;
+ }
+ XmlAttributeValue value = (XmlAttributeValue)element;
+ String unquotedValue = value.getValue();
+ if (unquotedValue == null || XmlHighlightVisitor.skipValidation(value) || !XmlUtil.isSimpleXmlAttributeValue(unquotedValue, value)) {
+ return PsiReference.EMPTY_ARRAY;
+ }
+ PsiElement parent = value.getParent();
+ if (parent instanceof XmlAttribute) {
+ final XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
+ if (descriptor instanceof BasicXmlAttributeDescriptor &&
+ (descriptor.isFixed() || descriptor.isEnumerated() || unquotedValue.equals(descriptor.getDefaultValue()))) { // todo case insensitive
+ return ((BasicXmlAttributeDescriptor)descriptor).getValueReferences(value);
+ }
+ }
+ return PsiReference.EMPTY_ARRAY;
+ }
+}
diff --git a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
index 21d6abcca803..6fcd606e18fa 100644
--- a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
+++ b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java
@@ -89,5 +89,6 @@ public class XmlReferenceContributor extends PsiReferenceContributor {
new XmlEncodingReferenceProvider());
registrar.registerReferenceProvider(xmlAttributeValue(), new XmlPrefixReferenceProvider());
+ registrar.registerReferenceProvider(xmlAttributeValue(), new XmlAttributeValueReferenceProvider(), PsiReferenceRegistrar.LOWER_PRIORITY);
}
}
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java
index 36760ce1016a..db3d85e44600 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngXmlAttributeDescriptor.java
@@ -17,14 +17,20 @@
package org.intellij.plugins.relaxNG.model.descriptors;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.DelimitedListProcessor;
+import com.intellij.psi.ElementManipulators;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.XmlAttributeValueReference;
import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
@@ -201,4 +207,24 @@ public class RngXmlAttributeDescriptor extends BasicXmlAttributeDescriptor {
private static String normalizeSpace(String value) {
return value.replaceAll("\\s+", " ").trim();
}
+
+ @Override
+ public PsiReference[] getValueReferences(final XmlAttributeValue value) {
+ String text = value.getValue();
+ if (text == null) return PsiReference.EMPTY_ARRAY;
+ final int offset = ElementManipulators.getValueTextRange(value).getStartOffset();
+ final List<PsiReference> list = new ArrayList<PsiReference>();
+ new DelimitedListProcessor("") {
+ @Override
+ protected boolean isDelimiter(char ch) {
+ return Character.isWhitespace(ch);
+ }
+
+ @Override
+ protected void processToken(int start, int end, boolean delimitersOnly) {
+ list.add(new XmlAttributeValueReference(value, TextRange.create(offset + start, offset + end), RngXmlAttributeDescriptor.this));
+ }
+ }.processText(text);
+ return list.toArray(new PsiReference[list.size()]);
+ }
} \ No newline at end of file
diff --git a/xml/relaxng/testData/highlighting/attribute-choice-3.xml b/xml/relaxng/testData/highlighting/attribute-choice-3.xml
index c095d96e136f..312c85d7e8cd 100644
--- a/xml/relaxng/testData/highlighting/attribute-choice-3.xml
+++ b/xml/relaxng/testData/highlighting/attribute-choice-3.xml
@@ -1,2 +1,2 @@
-<attribute-choice xmlns="urn:test:simple.rng" type=<error>"c"</error>>
+<attribute-choice xmlns="urn:test:simple.rng" type="<error descr="Wrong attribute value">c</error>">
</attribute-choice> \ No newline at end of file
diff --git a/xml/relaxng/testData/highlighting/fixed-attribute_2.xml b/xml/relaxng/testData/highlighting/fixed-attribute_2.xml
index a7a4b233198b..cf6c47a396b7 100644
--- a/xml/relaxng/testData/highlighting/fixed-attribute_2.xml
+++ b/xml/relaxng/testData/highlighting/fixed-attribute_2.xml
@@ -1,2 +1,2 @@
-<fixed-attribute xmlns="urn:test:simple.rng" x=<error>"2.0"</error>>
+<fixed-attribute xmlns="urn:test:simple.rng" x="<error descr="Attribute should have fixed value 1.0">2.0</error>">
</fixed-attribute> \ No newline at end of file
diff --git a/xml/relaxng/testData/highlighting/value-choice-2.xml b/xml/relaxng/testData/highlighting/value-choice-2.xml
index 8b026fed37e5..fba9ef5c72ae 100644
--- a/xml/relaxng/testData/highlighting/value-choice-2.xml
+++ b/xml/relaxng/testData/highlighting/value-choice-2.xml
@@ -1,2 +1,2 @@
-<value-choice xmlns="urn:test:simple.rng" x=<error>"c"</error>>
+<value-choice xmlns="urn:test:simple.rng" x="<error descr="Wrong attribute value">c</error>">
</value-choice> \ No newline at end of file
diff --git a/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml b/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml
index c9f2474359d5..0ffab3101ea5 100644
--- a/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml
+++ b/xml/tests/testData/xml/HighlightWhenNoNsSchemaLocation.xml
@@ -1,4 +1,4 @@
<build number="1" xsi:noNamespaceSchemaLocation="HighlightWhenNoNsSchemaLocation.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<statusInfo status="SUCCESS"/>
-<statusInfo status=<error>"SUCCESS2"</error>/>
+<statusInfo status="<error descr="Wrong attribute value">SUCCESS2</error>"/>
</build> \ No newline at end of file
diff --git a/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties b/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
index 2f90357d2e09..8ab43e2f5311 100644
--- a/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
+++ b/xml/xml-psi-impl/resources/messages/XmlErrorMessages.properties
@@ -20,8 +20,7 @@ duplicate.id.reference=Duplicate id reference
invalid.id.reference=Invalid id reference
uri.is.not.registered=URI is not registered (Settings | Project Settings | Schemas and DTDs)
registered.resource.is.not.recognized=Resource registered by this uri is not recognized (Settings | Project Settings | Schemas and DTDs)
-# 0 - attr name, 1 - expected default value
-attribute.should.have.fixed.value=Attribute {0} should have fixed value {1}
+attribute.should.have.fixed.value=Attribute should have fixed value {0}
#quickfixes
insert.required.attribute.quickfix.text=Insert Required Attribute {0}
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
index 445a5503a855..d6bbd3ba3722 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlAttributeDescriptorImpl.java
@@ -16,14 +16,16 @@
package com.intellij.psi.impl.source.html.dtd;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlElement;
import com.intellij.util.ArrayUtil;
import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
/**
* @author Maxim.Mossienko
*/
-public class HtmlAttributeDescriptorImpl implements XmlAttributeDescriptor {
+public class HtmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor {
private final XmlAttributeDescriptor delegate;
private final boolean myCaseSensitive;
@@ -90,4 +92,9 @@ public class HtmlAttributeDescriptorImpl implements XmlAttributeDescriptor {
public String toString() {
return delegate.toString();
}
+
+ @Override
+ protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, String value) {
+ return super.getEnumeratedValueDeclaration(attributeValue, myCaseSensitive ? value : value.toLowerCase());
+ }
}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
index 1aa72c3f7ffc..83cf70f5ff37 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/BasicXmlAttributeDescriptor.java
@@ -24,40 +24,18 @@
*/
package com.intellij.xml.impl;
-import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.openapi.util.Comparing;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlElement;
+import com.intellij.util.ArrayUtilRt;
+import com.intellij.xml.util.XmlAttributeValueReference;
import com.intellij.xml.XmlAttributeDescriptor;
-import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.Nullable;
public abstract class BasicXmlAttributeDescriptor implements XmlAttributeDescriptor {
public String validateValue(XmlElement context, String value) {
- if (isFixed()) {
- String defaultValue = getDefaultValue();
-
- if (defaultValue != null && !defaultValue.equals(value)) {
- return XmlErrorMessages.message("attribute.should.have.fixed.value", getName(), defaultValue);
- }
- }
-
- if (isEnumerated(context) && XmlUtil.isSimpleXmlAttributeValue(value, (XmlAttributeValue)context)) {
- String[] values = getEnumeratedValues(context);
- boolean valueWasFound = false;
-
- for (String enumValue : values) {
- if (enumValue.equals(value)) {
- valueWasFound = true;
- break;
- }
- }
-
- if (!valueWasFound) {
- return XmlErrorMessages.message("wrong.attribute.value");
- }
- }
-
return null;
}
@@ -78,4 +56,26 @@ public abstract class BasicXmlAttributeDescriptor implements XmlAttributeDescrip
public String toString() {
return getName();
}
+
+ public PsiElement getValueDeclaration(XmlAttributeValue attributeValue, String value) {
+ String defaultValue = getDefaultValue();
+ if (Comparing.equal(defaultValue, value)) {
+ return getDefaultValueDeclaration();
+ }
+ return isFixed() ? null : getEnumeratedValueDeclaration(attributeValue, value);
+ }
+
+ protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, String value) {
+ String[] values = getEnumeratedValues();
+ if (values == null || values.length == 0) return getDeclaration();
+ return ArrayUtilRt.find(values, value) != -1 ? getDeclaration() : null;
+ }
+
+ protected PsiElement getDefaultValueDeclaration() {
+ return getDeclaration();
+ }
+
+ public PsiReference[] getValueReferences(XmlAttributeValue value) {
+ return new PsiReference[] { new XmlAttributeValueReference(value, this)};
+ }
}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
index 195449b9ef02..2248f003ab98 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
@@ -15,22 +15,19 @@
*/
package com.intellij.xml.impl.schema;
+import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.meta.PsiWritableMetaData;
-import com.intellij.psi.xml.XmlElement;
-import com.intellij.psi.xml.XmlFile;
-import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.*;
+import com.intellij.util.*;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.HashSet;
+import java.util.List;
/**
* @author Mike
@@ -38,6 +35,8 @@ import java.util.HashSet;
public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor implements PsiWritableMetaData {
private XmlTag myTag;
String myUse;
+ private boolean myExhaustiveEnum;
+
@NonNls
public static final String REQUIRED_ATTR_VALUE = "required";
@NonNls
@@ -115,18 +114,7 @@ public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor impl
}
public boolean isEnumerated(@Nullable XmlElement context) {
- final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
- myTag,
- context != null ?PsiTreeUtil.getContextOfType(context, XmlTag.class, true):null
- );
-
- if (elementDescriptor != null &&
- elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
- final EnumerationData data = getEnumeratedValuesImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration());
- return data != null && data.exaustive;
- }
-
- return false;
+ return processEnumeration(context, PairProcessor.TRUE);
}
public boolean isEnumerated() {
@@ -138,19 +126,27 @@ public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor impl
}
public String[] getEnumeratedValues(XmlElement context) {
- final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(
- myTag,
- context != null ?PsiTreeUtil.getContextOfType(context, XmlTag.class, true):null
- );
+ final List<String> list = new SmartList<String>();
+ processEnumeration(context, new PairProcessor<PsiElement, String>() {
+ @Override
+ public boolean process(PsiElement element, String s) {
+ list.add(s);
+ return true;
+ }
+ });
+ String defaultValue = getDefaultValue();
+ if (defaultValue != null) {
+ list.add(defaultValue);
+ }
+ return ArrayUtil.toStringArray(list);
+ }
- if (elementDescriptor!=null && elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
- final EnumerationData data = getEnumeratedValuesImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration());
- final String s = getDefaultValue();
+ private boolean processEnumeration(XmlElement context, PairProcessor<PsiElement, String> processor) {
+ XmlTag contextTag = context != null ? PsiTreeUtil.getContextOfType(context, XmlTag.class, true) : null;
+ final XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)XmlUtil.findXmlDescriptorByType(myTag, contextTag);
- if (s != null && s.length() > 0 && data == null) {
- return new String[] {s};
- }
- return data != null? data.enumeratedValues:ArrayUtil.EMPTY_STRING_ARRAY;
+ if (elementDescriptor!=null && elementDescriptor.getType() instanceof ComplexTypeDescriptor) {
+ return processEnumerationImpl(((ComplexTypeDescriptor)elementDescriptor.getType()).getDeclaration(), processor);
}
final String namespacePrefix = myTag.getNamespacePrefix();
@@ -159,35 +155,42 @@ public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor impl
);
if (type != null) {
- final EnumerationData data = getEnumeratedValuesImpl(type);
- return data != null? data.enumeratedValues:ArrayUtil.EMPTY_STRING_ARRAY;
+ return processEnumerationImpl(type, processor);
}
- return ArrayUtil.EMPTY_STRING_ARRAY;
- }
-
- static class EnumerationData {
- final String[] enumeratedValues;
- final boolean exaustive;
-
- EnumerationData(@NotNull String[] _values, boolean _exaustive) {
- enumeratedValues = _values;
- exaustive = _exaustive;
- }
+ return false;
}
- private static EnumerationData getEnumeratedValuesImpl(final XmlTag declaration) {
+ private boolean processEnumerationImpl(final XmlTag declaration, final PairProcessor<PsiElement, String> pairProcessor) {
if ("boolean".equals(declaration.getAttributeValue("name"))) {
- return new EnumerationData(new String[] {"true", "false"}, true);
+ XmlAttributeValue valueElement = declaration.getAttribute("name").getValueElement();
+ pairProcessor.process(valueElement, "true");
+ pairProcessor.process(valueElement, "false");
+ myExhaustiveEnum = true;
+ return true;
}
- final HashSet<String> variants = new HashSet<String>();
- final boolean exaustive = XmlUtil.collectEnumerationValues(declaration, variants);
+ else {
+ final Ref<Boolean> found = new Ref<Boolean>(Boolean.FALSE);
+ myExhaustiveEnum = XmlUtil.processEnumerationValues(declaration, new Processor<XmlTag>() {
+ @Override
+ public boolean process(XmlTag tag) {
+ found.set(Boolean.TRUE);
+ XmlAttribute name = tag.getAttribute("value");
+ return name == null || pairProcessor.process(name.getValueElement(), name.getValue());
+ }
+ });
+ return found.get();
+ }
+ }
- if (variants.size() > 0) {
- return new EnumerationData(ArrayUtil.toStringArray(variants), exaustive);
+ @Override
+ public PsiElement getValueDeclaration(XmlAttributeValue attributeValue, String value) {
+ PsiElement declaration = super.getValueDeclaration(attributeValue, value);
+ if (declaration == null && !myExhaustiveEnum) {
+ return getDeclaration();
}
- return null;
+ return declaration;
}
public String getName(PsiElement context) {
@@ -243,4 +246,20 @@ public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor impl
public void setName(String name) throws IncorrectOperationException {
NamedObjectDescriptor.setName(myTag, name);
}
+
+ @Override
+ protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, final String value) {
+ final Ref<PsiElement> result = new Ref<PsiElement>();
+ processEnumeration(myTag, new PairProcessor<PsiElement, String>() {
+ @Override
+ public boolean process(PsiElement element, String s) {
+ if (value.equals(s)) {
+ result.set(element);
+ return false;
+ }
+ return true;
+ }
+ });
+ return result.get();
+ }
}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
index 8b4c20a76c2c..4e5e37eaf0d4 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
@@ -757,7 +757,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum
return true;
}
- protected static boolean equalsToSchemaName(XmlTag tag, @NonNls String schemaName) {
+ protected static boolean equalsToSchemaName(@NotNull XmlTag tag, @NonNls String schemaName) {
return schemaName.equals(tag.getLocalName()) && checkSchemaNamespace(tag);
}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
index b884ced15bf6..98cb0b4923d6 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlSchemaTagsProcessor.java
@@ -31,6 +31,8 @@ import java.util.Set;
*/
public abstract class XmlSchemaTagsProcessor {
+ public final static ThreadLocal<Boolean> PROCESSING_FLAG = new ThreadLocal<Boolean>();
+
private final Set<XmlTag> myVisited = new HashSet<XmlTag>();
protected final XmlNSDescriptorImpl myNsDescriptor;
private final String[] myTagsToIgnore;
@@ -41,10 +43,16 @@ public abstract class XmlSchemaTagsProcessor {
}
public final void startProcessing(XmlTag tag) {
- processTag(tag, null);
+ try {
+ PROCESSING_FLAG.set(Boolean.TRUE);
+ processTag(tag, null);
+ }
+ finally {
+ PROCESSING_FLAG.set(null);
+ }
}
- public void processTag(XmlTag tag, @Nullable XmlTag context) {
+ private void processTag(XmlTag tag, @Nullable XmlTag context) {
if (myVisited.contains(tag)) return;
myVisited.add(tag);
@@ -80,6 +88,7 @@ public abstract class XmlSchemaTagsProcessor {
if (ref == null) return;
XmlTag group;
XmlTag parentTag = tag.getParentTag();
+ assert parentTag != null;
if (XmlNSDescriptorImpl.equalsToSchemaName(parentTag, "attributeGroup") &&
ref.equals(parentTag.getAttributeValue("name"))) {
group = resolveTagReference(tag.getAttribute("ref"));
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlAttributeValueReference.java b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlAttributeValueReference.java
new file mode 100644
index 000000000000..75a604b520c8
--- /dev/null
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlAttributeValueReference.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xml.util;
+
+import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
+import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReferenceBase;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ArrayUtil;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.impl.BasicXmlAttributeDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author Dmitry Avdeev
+* Date: 16.08.13
+*/
+public class XmlAttributeValueReference extends PsiReferenceBase<XmlAttributeValue> implements EmptyResolveMessageProvider {
+ private final XmlAttributeDescriptor myDescriptor;
+
+ public XmlAttributeValueReference(XmlAttributeValue value, XmlAttributeDescriptor descriptor) {
+ super(value);
+ myDescriptor = descriptor;
+ }
+
+ public XmlAttributeValueReference(XmlAttributeValue element,
+ TextRange range,
+ XmlAttributeDescriptor descriptor) {
+ super(element, range);
+ myDescriptor = descriptor;
+ }
+
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+ return ((BasicXmlAttributeDescriptor)myDescriptor).getValueDeclaration(getElement(), getValue());
+ }
+
+ @NotNull
+ @Override
+ public Object[] getVariants() {
+ if (myDescriptor.isFixed()) {
+ String defaultValue = myDescriptor.getDefaultValue();
+ return defaultValue == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : new Object[] {defaultValue};
+ }
+ else {
+ String[] values = myDescriptor.getEnumeratedValues();
+ return values == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : values;
+ }
+ }
+
+ @NotNull
+ @Override
+ public String getUnresolvedMessagePattern() {
+ return myDescriptor.isFixed()
+ ? XmlErrorMessages.message("attribute.should.have.fixed.value", myDescriptor.getDefaultValue())
+ : XmlErrorMessages.message("wrong.attribute.value");
+ }
+}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
index ee38a7e63518..e8bb8f4c6f41 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
@@ -933,26 +933,33 @@ public class XmlUtil {
});
}
+ /**
+ * @return true if enumeration is exhaustive
+ */
public static boolean processEnumerationValues(final XmlTag element, final Processor<XmlTag> tagProcessor) {
- boolean exaustiveEnum = true;
+ boolean exhaustiveEnum = true;
for (final XmlTag tag : element.getSubTags()) {
@NonNls final String localName = tag.getLocalName();
if (localName.equals(ENUMERATION_TAG_NAME)) {
final String attributeValue = tag.getAttributeValue(VALUE_ATTR_NAME);
- if (attributeValue != null) tagProcessor.process(tag);
+ if (attributeValue != null) {
+ if (!tagProcessor.process(tag)) {
+ return exhaustiveEnum;
+ }
+ }
}
else if (localName.equals("union")) {
- exaustiveEnum = false;
+ exhaustiveEnum = false;
processEnumerationValues(tag, tagProcessor);
}
else if (!localName.equals("annotation")) {
// don't go into annotation
- exaustiveEnum &= processEnumerationValues(tag, tagProcessor);
+ exhaustiveEnum &= processEnumerationValues(tag, tagProcessor);
}
}
- return exaustiveEnum;
+ return exhaustiveEnum;
}
/**
@@ -1063,12 +1070,15 @@ public class XmlUtil {
return new Pair<XmlTagChild, XmlTagChild>(first, last);
}
- public static boolean isSimpleXmlAttributeValue(final String unquotedValue, final XmlAttributeValue context) {
+ public static boolean isSimpleXmlAttributeValue(@NotNull final String unquotedValue, final XmlAttributeValue context) {
for (int i = 0; i < unquotedValue.length(); ++i) {
final char ch = unquotedValue.charAt(i);
if (!Character.isJavaIdentifierPart(ch) && ch != ':' && ch != '-') {
final XmlFile file = PsiTreeUtil.getParentOfType(context, XmlFile.class);
- return file != null && !tagFromTemplateFramework(file.getRootTag());
+ if (file != null) {
+ XmlTag tag = file.getRootTag();
+ return tag != null && !tagFromTemplateFramework(tag);
+ }
}
}
return true;