diff options
Diffstat (limited to 'xml/xml-psi-impl/src/com/intellij/xml')
4 files changed, 313 insertions, 347 deletions
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java b/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java index 4ece939ffac0..e54a93394242 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java @@ -3,6 +3,7 @@ package com.intellij.xml; import com.intellij.ide.highlighter.HtmlFileType; import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlDocument; +import com.intellij.xml.util.HtmlUtil; import org.jetbrains.annotations.Nullable; /** @@ -19,6 +20,16 @@ public class HtmlXmlExtension extends DefaultXmlExtension { @Nullable @Override public String[][] getNamespacesFromDocument(XmlDocument parent, boolean declarationsExist) { - return super.getNamespacesFromDocument(parent, false); + String[][] namespaces = super.getNamespacesFromDocument(parent, false); + if (namespaces == null || !HtmlUtil.isHtml5Document(parent)) return namespaces; + + for (String[] namespace : namespaces) { + if ("xlink".equals(namespace[0])) return namespaces; + } + + String[][] newNamespaces = new String[namespaces.length + 1][2]; + System.arraycopy(namespaces, 0, newNamespaces, 0, namespaces.length); + newNamespaces[namespaces.length] = new String[] {"xlink", "http://www.w3.org/1999/xlink"}; + return newNamespaces; } } diff --git a/xml/xml-psi-impl/src/com/intellij/xml/XmlCoreEnvironment.java b/xml/xml-psi-impl/src/com/intellij/xml/XmlCoreEnvironment.java index b7704fb3b981..4610c2fa97e0 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/XmlCoreEnvironment.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/XmlCoreEnvironment.java @@ -119,7 +119,7 @@ public class XmlCoreEnvironment { appEnvironment.addExtension(StandardResourceProvider.EP_NAME, new InternalResourceProvider()); appEnvironment.registerApplicationComponent(PathMacros.class, new PathMacrosImpl()); - appEnvironment.registerApplicationService(ExternalResourceManager.class, new ExternalResourceManagerExImpl(PathMacrosImpl.getInstanceEx())); + appEnvironment.registerApplicationService(ExternalResourceManager.class, new ExternalResourceManagerExImpl()); appEnvironment.registerApplicationService(XmlFoldingSettings.class, new XmlFoldingSettings()); Language[] myLanguages = new Language[]{XMLLanguage.INSTANCE, HTMLLanguage.INSTANCE, XHTMLLanguage.INSTANCE, DTDLanguage.INSTANCE}; for (Language myLanguage : myLanguages) { @@ -137,8 +137,7 @@ public class XmlCoreEnvironment { public static class ProjectEnvironment { public ProjectEnvironment(CoreProjectEnvironment projectEnvironment) { projectEnvironment.getProject().registerService(XmlElementFactory.class, new XmlElementFactoryImpl(projectEnvironment.getProject())); - projectEnvironment.getProject().registerService(ExternalResourceManagerExImpl.class, - new ProjectResources(PathMacrosImpl.getInstanceEx())); + projectEnvironment.getProject().registerService(ExternalResourceManagerExImpl.class, new ProjectResources()); } } } 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 192c272a5f23..17c6f1ab37ae 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 @@ -30,7 +30,6 @@ import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlDocument; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; @@ -56,35 +55,35 @@ import java.util.*; */ @SuppressWarnings({"HardCodedStringLiteral"}) public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocument>, DumbAware, XmlNSTypeDescriptorProvider { - private static final Logger LOG = Logger.getInstance("#com.intellij.xml.impl.schema.XmlNSDescriptorImpl"); - @NonNls private static final Set<String> STD_TYPES = new HashSet<String>(); - private static final Set<String> UNDECLARED_STD_TYPES = new HashSet<String>(); - private XmlFile myFile; - private XmlTag myTag; - private String myTargetNamespace; @NonNls public static final String XSD_PREFIX = "xsd"; - + @NonNls public static final String SCHEMA_TAG_NAME = "schema"; + @NonNls public static final String IMPORT_TAG_NAME = "import"; @NonNls static final String ELEMENT_TAG_NAME = "element"; @NonNls static final String ATTRIBUTE_TAG_NAME = "attribute"; @NonNls static final String COMPLEX_TYPE_TAG_NAME = "complexType"; @NonNls static final String SEQUENCE_TAG_NAME = "sequence"; - @NonNls public static final String SCHEMA_TAG_NAME = "schema"; + private static final Logger LOG = Logger.getInstance("#com.intellij.xml.impl.schema.XmlNSDescriptorImpl"); + @NonNls private static final Set<String> STD_TYPES = new HashSet<String>(); + private static final Set<String> UNDECLARED_STD_TYPES = new HashSet<String>(); @NonNls private static final String INCLUDE_TAG_NAME = "include"; - @NonNls public static final String IMPORT_TAG_NAME = "import"; @NonNls private static final String REDEFINE_TAG_NAME = "redefine"; + private static final ThreadLocal<Set<PsiFile>> myRedefinedDescriptorsInProcessing = new ThreadLocal<Set<PsiFile>>(); + private final Map<QNameKey, CachedValue<XmlElementDescriptor>> myDescriptorsMap = Collections.synchronizedMap(new HashMap<QNameKey, CachedValue<XmlElementDescriptor>>()); + private final Map<Pair<QNameKey, XmlTag>, CachedValue<TypeDescriptor>> myTypesMap = Collections.synchronizedMap(new HashMap<Pair<QNameKey,XmlTag>, CachedValue<TypeDescriptor>>()); + private XmlFile myFile; + private XmlTag myTag; + private String myTargetNamespace; + private volatile Object[] dependencies; + private MultiMap<String,XmlTag> mySubstitutions; public XmlNSDescriptorImpl(XmlFile file) { init(file.getDocument()); } - + public XmlNSDescriptorImpl() { } - private volatile Object[] dependencies; - - private static final ThreadLocal<Set<PsiFile>> myRedefinedDescriptorsInProcessing = new ThreadLocal<Set<PsiFile>>(); - private static void collectDependencies(@Nullable XmlTag myTag, @NotNull XmlFile myFile, @NotNull Set<PsiFile> visited) { if (visited.contains(myFile)) return; visited.add( myFile ); @@ -121,7 +120,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum if(tokenizer.hasMoreTokens()){ PsiFile resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(tokenizer.nextToken(), myFile, null); - if (resourceLocation == null && uri != null) resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(uri, myFile, null); + if (resourceLocation == null) resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(uri, myFile, null); if (resourceLocation instanceof XmlFile) addDependency((XmlFile)resourceLocation, visited); } @@ -136,6 +135,211 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum } } + private static boolean checkSchemaNamespace(String name, XmlTag context){ + final String namespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(name)); + if(namespace.length() > 0){ + return checkSchemaNamespace(namespace); + } + return XSD_PREFIX.equals(XmlUtil.findPrefixByQualifiedName(name)); + } + + public static boolean checkSchemaNamespace(String namespace) { + return XmlUtil.XML_SCHEMA_URI.equals(namespace) || + XmlUtil.XML_SCHEMA_URI2.equals(namespace) || + XmlUtil.XML_SCHEMA_URI3.equals(namespace); + } + + public static boolean checkSchemaNamespace(XmlTag context) { + LOG.assertTrue(context.isValid()); + final String namespace = context.getNamespace(); + if (namespace.length() > 0) { + return checkSchemaNamespace(namespace); + } + return StringUtil.startsWithConcatenation(context.getName(), XSD_PREFIX, ":"); + } + + static @NotNull XmlNSDescriptorImpl getNSDescriptorToSearchIn(XmlTag rootTag, final String name, XmlNSDescriptorImpl defaultNSDescriptor) { + if (name == null) return defaultNSDescriptor; + final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name); + + if (namespacePrefix.length() > 0) { + final String namespace = rootTag.getNamespaceByPrefix(namespacePrefix); + final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(namespace, true); + + if (nsDescriptor instanceof XmlNSDescriptorImpl) { + return (XmlNSDescriptorImpl)nsDescriptor; + } + } + + return defaultNSDescriptor; + } + + @Nullable + private static XmlElementDescriptor getDescriptorFromParent(final XmlTag tag, XmlElementDescriptor elementDescriptor) { + final PsiElement parent = tag.getParent(); + if (parent instanceof XmlTag) { + final XmlElementDescriptor descriptor = ((XmlTag)parent).getDescriptor(); + if (descriptor != null) elementDescriptor = descriptor.getElementDescriptor(tag, (XmlTag)parent); + } + return elementDescriptor; + } + + public static boolean processTagsInNamespace(@NotNull final XmlTag rootTag, String[] tagNames, PsiElementProcessor<XmlTag> processor) { + return processTagsInNamespaceInner(rootTag, tagNames, processor, null); + } + + private static boolean processTagsInNamespaceInner(@NotNull final XmlTag rootTag, final String[] tagNames, + final PsiElementProcessor<XmlTag> processor, Set<XmlTag> visitedTags) { + if (visitedTags == null) visitedTags = new HashSet<XmlTag>(3); + else if (visitedTags.contains(rootTag)) return true; + + visitedTags.add(rootTag); + XmlTag[] tags = rootTag.getSubTags(); + + NextTag: + for (XmlTag tag : tags) { + for(String tagName:tagNames) { + if (equalsToSchemaName(tag, tagName)) { + final String name = tag.getAttributeValue("name"); + + if (name != null) { + if (!processor.execute(tag)) { + return false; + } + } + + continue NextTag; + } + } + + if (equalsToSchemaName(tag, INCLUDE_TAG_NAME)) { + final String schemaLocation = tag.getAttributeValue("schemaLocation"); + + if (schemaLocation != null) { + final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation); + + if (xmlFile != null) { + final XmlDocument includedDocument = xmlFile.getDocument(); + + if (includedDocument != null) { + if (!processTagsInNamespaceInner(includedDocument.getRootTag(), tagNames, processor, visitedTags)) return false; + } + } + } + } + } + + return true; + } + + public static boolean equalsToSchemaName(@NotNull XmlTag tag, @NonNls String schemaName) { + return schemaName.equals(tag.getLocalName()) && checkSchemaNamespace(tag); + } + + private static @Nullable XmlTag findSpecialTag(@NonNls String name, @NonNls String specialName, XmlTag rootTag, XmlNSDescriptorImpl descriptor, + HashSet<XmlTag> visited) { + XmlNSDescriptorImpl nsDescriptor = getNSDescriptorToSearchIn(rootTag, name, descriptor); + + if (nsDescriptor != descriptor) { + final XmlDocument document = nsDescriptor.getDescriptorFile() != null ? nsDescriptor.getDescriptorFile().getDocument():null; + if (document == null) return null; + + return findSpecialTag( + XmlUtil.findLocalNameByQualifiedName(name), + specialName, + document.getRootTag(), + nsDescriptor, + visited + ); + } + + if (visited == null) visited = new HashSet<XmlTag>(1); + else if (visited.contains(rootTag)) return null; + visited.add(rootTag); + + XmlTag[] tags = rootTag.getSubTags(); + + return findSpecialTagIn(tags, specialName, name, rootTag, descriptor, visited); + } + + private static XmlTag findSpecialTagIn(final XmlTag[] tags, + final String specialName, + final String name, + final XmlTag rootTag, + final XmlNSDescriptorImpl descriptor, final HashSet<XmlTag> visited) { + for (XmlTag tag : tags) { + if (equalsToSchemaName(tag, specialName)) { + String attribute = tag.getAttributeValue("name"); + + if (name.equals(attribute) + || name.contains(":") && name.substring(name.indexOf(":") + 1).equals(attribute)) { + return tag; + } + } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) || + ( equalsToSchemaName(tag, IMPORT_TAG_NAME) && + rootTag.getNamespaceByPrefix( + XmlUtil.findPrefixByQualifiedName(name) + ).equals(tag.getAttributeValue("namespace")) + ) + ) { + final String schemaLocation = tag.getAttributeValue("schemaLocation"); + + if (schemaLocation != null) { + final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation); + + if (xmlFile != null) { + final XmlDocument document = xmlFile.getDocument(); + if (document != null) { + final XmlTag rTag = findSpecialTag(name, specialName, document.getRootTag(), descriptor, visited); + + if (rTag != null) return rTag; + } + } + } + } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) { + XmlTag rTag = findSpecialTagIn(tag.getSubTags(), specialName, name, rootTag, descriptor, visited); + if (rTag != null) return rTag; + + final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag); + if (nsDescriptor != null) { + final XmlTag redefinedRootTag = ((XmlDocument)nsDescriptor.getDeclaration()).getRootTag(); + + rTag = findSpecialTagIn(redefinedRootTag.getSubTags(), specialName, name, redefinedRootTag, nsDescriptor, visited); + if (rTag != null) return rTag; + } + } + } + + return null; + } + + public static XmlNSDescriptorImpl getRedefinedElementDescriptor(final XmlTag parentTag) { + XmlFile file = getRedefinedElementDescriptorFile(parentTag); + if (file != null) { + final XmlDocument document = file.getDocument(); + final PsiMetaData metaData = document != null ? document.getMetaData():null; + if (metaData instanceof XmlNSDescriptorImpl) return (XmlNSDescriptorImpl)metaData; + } + return null; + } + + public static XmlFile getRedefinedElementDescriptorFile(final XmlTag parentTag) { + final String schemaL = parentTag.getAttributeValue(XmlUtil.SCHEMA_LOCATION_ATT); + + if (schemaL != null) { + final PsiReference[] references = parentTag.getAttribute(XmlUtil.SCHEMA_LOCATION_ATT, null).getValueElement().getReferences(); + + if (references.length > 0) { + final PsiElement psiElement = references[references.length - 1].resolve(); + + if (psiElement instanceof XmlFile) { + return ((XmlFile)psiElement); + } + } + } + return null; + } + @Override public XmlFile getDescriptorFile() { return myFile; @@ -150,18 +354,10 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum return myTargetNamespace != null ? myTargetNamespace : ""; } - static class QNameKey extends Pair<String, String>{ - QNameKey(String name, String namespace) { - super(name, namespace); - } - } - private final Map<QNameKey, CachedValue<XmlElementDescriptor>> myDescriptorsMap = Collections.synchronizedMap(new HashMap<QNameKey, CachedValue<XmlElementDescriptor>>()); - private final Map<Pair<QNameKey, XmlTag>, CachedValue<TypeDescriptor>> myTypesMap = Collections.synchronizedMap(new HashMap<Pair<QNameKey,XmlTag>, CachedValue<TypeDescriptor>>()); - @Override @Nullable public XmlElementDescriptor getElementDescriptor(String localName, String namespace) { - return getElementDescriptor(localName, namespace, new HashSet<XmlNSDescriptorImpl>(),false); + return getElementDescriptor(localName, namespace, new HashSet<XmlNSDescriptorImpl>(), false); } @Nullable @@ -213,9 +409,9 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum ) ) ) { - final XmlAttribute schemaLocation = tag.getAttribute("schemaLocation"); + final String schemaLocation = tag.getAttributeValue("schemaLocation"); if (schemaLocation != null) { - final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation.getValue()); + final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation); if (xmlFile != null) { final XmlDocument includedDocument = xmlFile.getDocument(); if (includedDocument != null) { @@ -266,8 +462,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum return true; } else { - final boolean b = myTargetNamespace.equals(namespace); - if (b) return b; + if (myTargetNamespace.equals(namespace)) return true; return context.getNSDescriptor(namespace, true) == this; // schema's targetNamespace could be different from file systemId } return false; @@ -311,10 +506,10 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum namespace.equals(tag.getAttributeValue("namespace")) ) ) { - final XmlAttribute schemaLocation = tag.getAttribute("schemaLocation"); + final String schemaLocation = tag.getAttributeValue("schemaLocation"); if (schemaLocation != null) { - final XmlFile xmlFile = XmlUtil.findNamespace(myTag.getContainingFile(), schemaLocation.getValue()); + final XmlFile xmlFile = XmlUtil.findNamespace(myTag.getContainingFile(), schemaLocation); if (xmlFile != null) { @@ -370,7 +565,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum public TypeDescriptor getTypeDescriptor(final String name, XmlTag context) { if(checkSchemaNamespace(name, context)){ final String localNameByQualifiedName = XmlUtil.findLocalNameByQualifiedName(name); - + if (STD_TYPES.contains(localNameByQualifiedName) && ( name.length() == localNameByQualifiedName.length() || UNDECLARED_STD_TYPES.contains(localNameByQualifiedName) @@ -390,45 +585,6 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum return new XmlElementDescriptorByType(instanceTag, (ComplexTypeDescriptor)typeDescriptor); } - private static boolean checkSchemaNamespace(String name, XmlTag context){ - final String namespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(name)); - if(namespace.length() > 0){ - return checkSchemaNamespace(namespace); - } - return XSD_PREFIX.equals(XmlUtil.findPrefixByQualifiedName(name)); - } - - public static boolean checkSchemaNamespace(String namespace) { - return XmlUtil.XML_SCHEMA_URI.equals(namespace) || - XmlUtil.XML_SCHEMA_URI2.equals(namespace) || - XmlUtil.XML_SCHEMA_URI3.equals(namespace); - } - - public static boolean checkSchemaNamespace(XmlTag context) { - LOG.assertTrue(context.isValid()); - final String namespace = context.getNamespace(); - if (namespace.length() > 0) { - return checkSchemaNamespace(namespace); - } - return StringUtil.startsWithConcatenation(context.getName(), XSD_PREFIX, ":"); - } - - static @NotNull XmlNSDescriptorImpl getNSDescriptorToSearchIn(XmlTag rootTag, final String name, XmlNSDescriptorImpl defaultNSDescriptor) { - if (name == null) return defaultNSDescriptor; - final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name); - - if (namespacePrefix != null && namespacePrefix.length() > 0) { - final String namespace = rootTag.getNamespaceByPrefix(namespacePrefix); - final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(namespace, true); - - if (nsDescriptor instanceof XmlNSDescriptorImpl) { - return (XmlNSDescriptorImpl)nsDescriptor; - } - } - - return defaultNSDescriptor; - } - @Nullable protected TypeDescriptor findTypeDescriptor(final String qname) { return findTypeDescriptor(qname, myTag); @@ -587,7 +743,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum private boolean isSameName(@NotNull String name, String namespace, String nameAttribute) { return nameAttribute != null && - (nameAttribute.equals(name) || (name.indexOf(":") >= 0 && nameAttribute.equals(name.substring(name.indexOf(":") + 1)))) && + (nameAttribute.equals(name) || (name.contains(":") && nameAttribute.equals(name.substring(name.indexOf(":") + 1)))) && (namespace == null || namespace.length() == 0 || namespace.equals(getDefaultNamespace())) ; } @@ -619,23 +775,24 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum } private CachedValue<TypeDescriptor> createAndPutTypesCachedValue(final XmlTag tag, final Pair<QNameKey, XmlTag> pair) { - final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<TypeDescriptor>() { - @Override - public CachedValueProvider.Result<TypeDescriptor> compute() { - final String name = tag.getAttributeValue("name"); - - if (name != null && - pair.first != null && - pair.first.first != null && - !name.equals(XmlUtil.findLocalNameByQualifiedName(pair.first.first)) - ) { - myTypesMap.remove(pair); - return new Result<TypeDescriptor>(null, PsiModificationTracker.MODIFICATION_COUNT); + final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue( + new CachedValueProvider<TypeDescriptor>() { + @Override + public CachedValueProvider.Result<TypeDescriptor> compute() { + final String name = tag.getAttributeValue("name"); + + if (name != null && + pair.first != null && + pair.first.first != null && + !name.equals(XmlUtil.findLocalNameByQualifiedName(pair.first.first)) + ) { + myTypesMap.remove(pair); + return new Result<TypeDescriptor>(null, PsiModificationTracker.MODIFICATION_COUNT); + } + final ComplexTypeDescriptor complexTypeDescriptor = new ComplexTypeDescriptor(XmlNSDescriptorImpl.this, tag); + return new Result<TypeDescriptor>(complexTypeDescriptor, tag); } - final ComplexTypeDescriptor complexTypeDescriptor = new ComplexTypeDescriptor(XmlNSDescriptorImpl.this, tag); - return new Result<TypeDescriptor>(complexTypeDescriptor, tag); - } - }, false); + }, false); myTypesMap.put(pair, value); return value; } @@ -668,7 +825,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum } else { XmlElementDescriptor elementDescriptor = getElementDescriptor(tag.getLocalName(), tag.getNamespace()); - + if (elementDescriptor == null) { elementDescriptor = getDescriptorFromParent(tag, elementDescriptor); } @@ -677,29 +834,19 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum } } - @Nullable - private static XmlElementDescriptor getDescriptorFromParent(final XmlTag tag, XmlElementDescriptor elementDescriptor) { - final PsiElement parent = tag.getParent(); - if (parent instanceof XmlTag) { - final XmlElementDescriptor descriptor = ((XmlTag)parent).getDescriptor(); - if (descriptor != null) elementDescriptor = descriptor.getElementDescriptor(tag, (XmlTag)parent); - } - return elementDescriptor; - } - @Override @NotNull public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument doc) { class CollectElementsProcessor implements PsiElementProcessor<XmlTag> { final List<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>(); - + @Override public boolean execute(@NotNull final XmlTag element) { ContainerUtil.addIfNotNull(result, getElementDescriptor(element.getAttributeValue("name"), getDefaultNamespace())); return true; } } - + CollectElementsProcessor processor = new CollectElementsProcessor() { @Override public boolean execute(@NotNull final XmlTag element) { @@ -729,135 +876,6 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum return processor.result.toArray(new XmlAttributeDescriptor[processor.result.size()]); } - public static boolean processTagsInNamespace(@NotNull final XmlTag rootTag, String[] tagNames, PsiElementProcessor<XmlTag> processor) { - return processTagsInNamespaceInner(rootTag, tagNames, processor, null); - } - - private static boolean processTagsInNamespaceInner(@NotNull final XmlTag rootTag, final String[] tagNames, - final PsiElementProcessor<XmlTag> processor, Set<XmlTag> visitedTags) { - if (visitedTags == null) visitedTags = new HashSet<XmlTag>(3); - else if (visitedTags.contains(rootTag)) return true; - - visitedTags.add(rootTag); - XmlTag[] tags = rootTag.getSubTags(); - - NextTag: - for (XmlTag tag : tags) { - for(String tagName:tagNames) { - if (equalsToSchemaName(tag, tagName)) { - final String name = tag.getAttributeValue("name"); - - if (name != null) { - if (!processor.execute(tag)) { - return false; - } - } - - continue NextTag; - } - } - - if (equalsToSchemaName(tag, INCLUDE_TAG_NAME)) { - final String schemaLocation = tag.getAttributeValue("schemaLocation"); - - if (schemaLocation != null) { - final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation); - - if (xmlFile != null) { - final XmlDocument includedDocument = xmlFile.getDocument(); - - if (includedDocument != null) { - if (!processTagsInNamespaceInner(includedDocument.getRootTag(), tagNames, processor, visitedTags)) return false; - } - } - } - } - } - - return true; - } - - public static boolean equalsToSchemaName(@NotNull XmlTag tag, @NonNls String schemaName) { - return schemaName.equals(tag.getLocalName()) && checkSchemaNamespace(tag); - } - - private static @Nullable XmlTag findSpecialTag(@NonNls String name, @NonNls String specialName, XmlTag rootTag, XmlNSDescriptorImpl descriptor, - HashSet<XmlTag> visited) { - XmlNSDescriptorImpl nsDescriptor = getNSDescriptorToSearchIn(rootTag, name, descriptor); - - if (nsDescriptor != descriptor) { - final XmlDocument document = nsDescriptor.getDescriptorFile() != null ? nsDescriptor.getDescriptorFile().getDocument():null; - if (document == null) return null; - - return findSpecialTag( - XmlUtil.findLocalNameByQualifiedName(name), - specialName, - document.getRootTag(), - nsDescriptor, - visited - ); - } - - if (visited == null) visited = new HashSet<XmlTag>(1); - else if (visited.contains(rootTag)) return null; - visited.add(rootTag); - - XmlTag[] tags = rootTag.getSubTags(); - - return findSpecialTagIn(tags, specialName, name, rootTag, descriptor, visited); - } - - private static XmlTag findSpecialTagIn(final XmlTag[] tags, - final String specialName, - final String name, - final XmlTag rootTag, - final XmlNSDescriptorImpl descriptor, final HashSet<XmlTag> visited) { - for (XmlTag tag : tags) { - if (equalsToSchemaName(tag, specialName)) { - String attribute = tag.getAttributeValue("name"); - - if (name.equals(attribute) - || name.indexOf(":") >= 0 && name.substring(name.indexOf(":") + 1).equals(attribute)) { - return tag; - } - } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) || - ( equalsToSchemaName(tag, IMPORT_TAG_NAME) && - rootTag.getNamespaceByPrefix( - XmlUtil.findPrefixByQualifiedName(name) - ).equals(tag.getAttributeValue("namespace")) - ) - ) { - final String schemaLocation = tag.getAttributeValue("schemaLocation"); - - if (schemaLocation != null) { - final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation); - - if (xmlFile != null) { - final XmlDocument document = xmlFile.getDocument(); - if (document != null) { - final XmlTag rTag = findSpecialTag(name, specialName, document.getRootTag(), descriptor, visited); - - if (rTag != null) return rTag; - } - } - } - } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) { - XmlTag rTag = findSpecialTagIn(tag.getSubTags(), specialName, name, rootTag, descriptor, visited); - if (rTag != null) return rTag; - - final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag); - if (nsDescriptor != null) { - final XmlTag redefinedRootTag = ((XmlDocument)nsDescriptor.getDeclaration()).getRootTag(); - - rTag = findSpecialTagIn(redefinedRootTag.getSubTags(), specialName, name, redefinedRootTag, nsDescriptor, visited); - if (rTag != null) return rTag; - } - } - } - - return null; - } - @Nullable public XmlTag findGroup(String name) { return findSpecialTag(name,"group",myTag, this, null); @@ -865,11 +883,9 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum @Nullable public XmlTag findAttributeGroup(String name) { - return findSpecialTag(name,"attributeGroup",myTag,this, null); + return findSpecialTag(name, "attributeGroup", myTag, this, null); } - private MultiMap<String,XmlTag> mySubstitutions; - public XmlElementDescriptor[] getSubstitutes(String localName, String namespace) { if (!initSubstitutes()) { return XmlElementDescriptor.EMPTY_ARRAY; @@ -926,7 +942,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum @Override public void init(PsiElement element){ myFile = (XmlFile) element.getContainingFile(); - + if (element instanceof XmlTag) { myTag = (XmlTag)element; } else { @@ -955,7 +971,6 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum if (dependencies == null) dependencies = myFile == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : new Object[] {myFile}; // init was not called return dependencies; } - static { STD_TYPES.add("string"); STD_TYPES.add("normalizedString"); @@ -1002,7 +1017,7 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum STD_TYPES.add("NMTOKEN"); STD_TYPES.add("NMTOKENS"); STD_TYPES.add("anySimpleType"); - + UNDECLARED_STD_TYPES.add("anySimpleType"); } @@ -1015,33 +1030,6 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum return myTag; } - public static XmlNSDescriptorImpl getRedefinedElementDescriptor(final XmlTag parentTag) { - XmlFile file = getRedefinedElementDescriptorFile(parentTag); - if (file != null) { - final XmlDocument document = file.getDocument(); - final PsiMetaData metaData = document != null ? document.getMetaData():null; - if (metaData instanceof XmlNSDescriptorImpl) return (XmlNSDescriptorImpl)metaData; - } - return null; - } - - public static XmlFile getRedefinedElementDescriptorFile(final XmlTag parentTag) { - final String schemaL = parentTag.getAttributeValue(XmlUtil.SCHEMA_LOCATION_ATT); - - if (schemaL != null) { - final PsiReference[] references = parentTag.getAttribute(XmlUtil.SCHEMA_LOCATION_ATT, null).getValueElement().getReferences(); - - if (references.length > 0) { - final PsiElement psiElement = references[references.length - 1].resolve(); - - if (psiElement instanceof XmlFile) { - return ((XmlFile)psiElement); - } - } - } - return null; - } - public boolean hasSubstitutions() { initSubstitutes(); return mySubstitutions != null && mySubstitutions.size() > 0; @@ -1050,4 +1038,10 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocum public boolean isValid() { return myFile != null && getDeclaration().isValid(); } + + static class QNameKey extends Pair<String, String>{ + QNameKey(String name, String namespace) { + super(name, namespace); + } + } } 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 a513db49b121..9de6d6e7e1d6 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 @@ -82,19 +82,14 @@ import java.util.*; * @author Mike */ public class XmlUtil { - private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.XmlUtil"); - @NonNls public static final String TAGLIB_1_2_URI = "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"; - @NonNls public static final String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema"; @NonNls public static final String XML_SCHEMA_URI2 = "http://www.w3.org/1999/XMLSchema"; @NonNls public static final String XML_SCHEMA_URI3 = "http://www.w3.org/2000/10/XMLSchema"; public static final String[] SCHEMA_URIS = {XML_SCHEMA_URI, XML_SCHEMA_URI2, XML_SCHEMA_URI3}; @NonNls public static final String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance"; - @NonNls public static final String XSLT_URI = "http://www.w3.org/1999/XSL/Transform"; @NonNls public static final String XINCLUDE_URI = XmlPsiUtil.XINCLUDE_URI; - @NonNls public static final String ANT_URI = "http://ant.apache.org/schema.xsd"; @NonNls public static final String XHTML_URI = "http://www.w3.org/1999/xhtml"; @NonNls public static final String HTML_URI = "http://www.w3.org/1999/html"; @@ -102,31 +97,21 @@ public class XmlUtil { @NonNls public static final Key<String> TEST_PATH = Key.create("TEST PATH"); @NonNls public static final String JSP_URI = "http://java.sun.com/JSP/Page"; @NonNls public static final String ANY_URI = "http://www.intellij.net/ns/any"; - @NonNls public static final String JSTL_CORE_URI = "http://java.sun.com/jsp/jstl/core"; @NonNls public static final String JSTL_CORE_URI2 = "http://java.sun.com/jstl/core"; @NonNls public static final String JSTL_CORE_URI3 = "http://java.sun.com/jstl/core_rt"; @NonNls public static final String JSTL_CORE_URI_JAVAEE_7 = "http://xmlns.jcp.org/jsp/jstl/core"; - @NonNls public static final String[] JSTL_CORE_URIS = {JSTL_CORE_URI, JSTL_CORE_URI2, JSTL_CORE_URI3, JSTL_CORE_URI_JAVAEE_7}; - - @NonNls public static final String JSF_HTML_URI = "http://java.sun.com/jsf/html"; @NonNls public static final String JSF_HTML_URI_JAVAEE_7 = "http://xmlns.jcp.org/jsf/html"; @NonNls public static final String[] JSF_HTML_URIS = {JSF_HTML_URI, JSF_HTML_URI_JAVAEE_7}; - @NonNls public static final String JSF_CORE_URI = "http://java.sun.com/jsf/core"; @NonNls public static final String JSF_CORE_URI_JAVAEE_7 = "http://xmlns.jcp.org/jsf/core"; @NonNls public static final String[] JSF_CORE_URIS = {JSF_CORE_URI, JSF_CORE_URI_JAVAEE_7}; - @NonNls public static final String JSF_PASS_THROUGH_ATTR_URI_JAVAEE7 = "http://xmlns.jcp.org/jsf"; @NonNls public static final String JSF_PASSTHROUGH_URI = "http://xmlns.jcp.org/jsf/passthrough"; - @NonNls public static final String JSTL_FORMAT_URI = "http://java.sun.com/jsp/jstl/fmt"; @NonNls public static final String JSTL_FORMAT_URI2 = "http://java.sun.com/jstl/fmt"; - @NonNls private static final String JSTL_FORMAT_URI3 = "http://java.sun.com/jstl/fmt_rt"; - @NonNls public static final String[] JSTL_FORMAT_URIS = {JSTL_FORMAT_URI, JSTL_FORMAT_URI2, JSTL_FORMAT_URI3}; - @NonNls public static final String SPRING_URI = "http://www.springframework.org/tags"; @NonNls public static final String SPRING_FORMS_URI = "http://www.springframework.org/tags/form"; @NonNls public static final String STRUTS_BEAN_URI = "http://struts.apache.org/tags-bean"; @@ -135,26 +120,21 @@ public class XmlUtil { @NonNls public static final String STRUTS_LOGIC_URI = "http://struts.apache.org/tags-logic"; @NonNls public static final String STRUTS_HTML_URI = "http://struts.apache.org/tags-html"; @NonNls public static final String STRUTS_HTML_URI2 = "http://jakarta.apache.org/struts/tags-html"; - @NonNls public static final String APACHE_TRINIDAD_URI = "http://myfaces.apache.org/trinidad"; @NonNls public static final String APACHE_TRINIDAD_HTML_URI = "http://myfaces.apache.org/trinidad/html"; - @NonNls public static final String XSD_SIMPLE_CONTENT_TAG = "simpleContent"; @NonNls public static final String NO_NAMESPACE_SCHEMA_LOCATION_ATT = "noNamespaceSchemaLocation"; @NonNls public static final String SCHEMA_LOCATION_ATT = "schemaLocation"; @NonNls public static final String[] WEB_XML_URIS = {"http://java.sun.com/xml/ns/j2ee", "http://java.sun.com/xml/ns/javaee", "http://xmlns.jcp.org/xml/ns/javaee", "http://java.sun.com/dtd/web-app_2_3.dtd", "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"}; - @NonNls public static final String FACELETS_URI = "http://java.sun.com/jsf/facelets"; @NonNls public static final String FACELETS_URI_JAVAEE_7 = "http://xmlns.jcp.org/jsf/facelets"; @NonNls public static final String[] FACELETS_URIS = {FACELETS_URI, FACELETS_URI_JAVAEE_7}; - @NonNls public static final String JSTL_FUNCTIONS_URI = "http://java.sun.com/jsp/jstl/functions"; @NonNls public static final String JSTL_FUNCTIONS_URI2 = "http://java.sun.com/jstl/functions"; @NonNls public static final String JSTL_FUNCTIONS_JAVAEE_7 = "http://xmlns.jcp.org/jsp/jstl/functions"; @NonNls public static final String[] JSTL_FUNCTIONS_URIS = {JSTL_FUNCTIONS_URI, JSTL_FUNCTIONS_URI2}; - @NonNls public static final String JSTL_FN_FACELET_URI = "com.sun.facelets.tag.jstl.fn.JstlFnLibrary"; @NonNls public static final String JSTL_CORE_FACELET_URI = "com.sun.facelets.tag.jstl.core.JstlCoreLibrary"; @NonNls public static final String TARGET_NAMESPACE_ATTR_NAME = "targetNamespace"; @@ -166,7 +146,6 @@ public class XmlUtil { @NonNls public static final String ENUMERATION_TAG_NAME = "enumeration"; @NonNls public static final String HTML4_LOOSE_URI = "http://www.w3.org/TR/html4/loose.dtd"; @NonNls public static final String WSDL_SCHEMA_URI = "http://schemas.xmlsoap.org/wsdl/"; - public static final String XHTML4_SCHEMA_LOCATION; public final static ThreadLocal<Boolean> BUILDING_DOM_STUBS = new ThreadLocal<Boolean>() { @Override @@ -174,52 +153,38 @@ public class XmlUtil { return Boolean.FALSE; } }; + private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.XmlUtil"); + @NonNls private static final String JSTL_FORMAT_URI3 = "http://java.sun.com/jstl/fmt_rt"; + @NonNls public static final String[] JSTL_FORMAT_URIS = {JSTL_FORMAT_URI, JSTL_FORMAT_URI2, JSTL_FORMAT_URI3}; @NonNls private static final String FILE = "file:"; @NonNls private static final String CLASSPATH = "classpath:/"; @NonNls private static final String URN = "urn:"; + private final static Set<String> doNotVisitTags = new HashSet<String>(Arrays.asList("annotation", "element", "attribute")); private XmlUtil() { } - static { final URL xhtml4SchemaLocationUrl = XmlUtil.class.getResource(ExternalResourceManagerEx.STANDARD_SCHEMAS + "xhtml1-transitional.xsd"); XHTML4_SCHEMA_LOCATION = VfsUtilCore.urlToPath(VfsUtilCore.toIdeaUrl(FileUtil.unquote(xhtml4SchemaLocationUrl.toExternalForm()), false)); } - @Nullable - public static String getSchemaLocation(XmlTag tag, String namespace) { - final String uri = ExternalResourceManagerEx.getInstanceEx().getResourceLocation(namespace, tag.getProject()); - if (uri != null && !uri.equals(namespace)) return uri; - - while (true) { - if (namespace.isEmpty()) { - final String attributeValue = tag.getAttributeValue("noNamespaceSchemaLocation", XML_SCHEMA_INSTANCE_URI); - if (attributeValue != null) return attributeValue; - } - else { - String schemaLocation = tag.getAttributeValue("schemaLocation", XML_SCHEMA_INSTANCE_URI); - if (schemaLocation != null) { - int start = schemaLocation.indexOf(namespace); - if (start >= 0) { - start += namespace.length(); - final StringTokenizer tokenizer = new StringTokenizer(schemaLocation.substring(start + 1)); - if (tokenizer.hasMoreTokens()) { - return tokenizer.nextToken(); - } - else { - return null; - } + public static String getSchemaLocation(XmlTag tag, final String namespace) { + while (tag != null) { + String schemaLocation = tag.getAttributeValue(SCHEMA_LOCATION_ATT, XML_SCHEMA_INSTANCE_URI); + if (schemaLocation != null) { + StringTokenizer tokenizer = new StringTokenizer(schemaLocation); + int i = 0; + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (i % 2 == 0 && namespace.equals(token) && tokenizer.hasMoreTokens()) { + return tokenizer.nextToken(); } + i++; } } - if (tag.getParent() instanceof XmlTag) { - tag = (XmlTag)tag.getParent(); - } - else { - break; - } + tag = tag.getParentTag(); } - return null; + return namespace; } @Nullable @@ -965,8 +930,6 @@ public class XmlUtil { }); } - private final static Set<String> doNotVisitTags = new HashSet<String>(Arrays.asList("annotation", "element", "attribute")); - /** * @return true if enumeration is exhaustive */ @@ -1189,31 +1152,6 @@ public class XmlUtil { return ExternalResourceManager.getInstance().getResourceLocation(s, project) != s; } - private static class MyAttributeInfo implements Comparable { - boolean myRequired = true; - String myName = null; - - MyAttributeInfo(String name) { - myName = name; - } - - MyAttributeInfo(String name, boolean flag) { - myName = name; - myRequired = flag; - } - - @Override - public int compareTo(Object o) { - if (o instanceof MyAttributeInfo) { - return myName.compareTo(((MyAttributeInfo)o).myName); - } - else if (o instanceof XmlAttribute) { - return myName.compareTo(((XmlAttribute)o).getName()); - } - return -1; - } - } - public static String generateDocumentDTD(XmlDocument doc, boolean full) { final Map<String, List<String>> tags = new LinkedHashMap<String, List<String>>(); final Map<String, List<MyAttributeInfo>> attributes = new LinkedHashMap<String, List<MyAttributeInfo>>(); @@ -1303,7 +1241,6 @@ public class XmlUtil { return name == null ? null : name.substring(name.indexOf(':') + 1); } - public static XmlFile getContainingFile(PsiElement element) { while (!(element instanceof XmlFile) && element != null) { final PsiElement context = element.getContext(); @@ -1482,4 +1419,29 @@ public class XmlUtil { @NotNull PsiElement getNodeForMessage(@NotNull T t); } + + private static class MyAttributeInfo implements Comparable { + boolean myRequired = true; + String myName = null; + + MyAttributeInfo(String name) { + myName = name; + } + + MyAttributeInfo(String name, boolean flag) { + myName = name; + myRequired = flag; + } + + @Override + public int compareTo(Object o) { + if (o instanceof MyAttributeInfo) { + return myName.compareTo(((MyAttributeInfo)o).myName); + } + else if (o instanceof XmlAttribute) { + return myName.compareTo(((XmlAttribute)o).getName()); + } + return -1; + } + } } |