summaryrefslogtreecommitdiff
path: root/xml/xml-psi-impl/src/com/intellij
diff options
context:
space:
mode:
Diffstat (limited to 'xml/xml-psi-impl/src/com/intellij')
-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
7 files changed, 208 insertions, 88 deletions
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;