Xml: introduce stub based tags - XML tag stub fully supported

GitOrigin-RevId: 47dd7b9b22f0e7a5674e011835c1e06dd749f21b
This commit is contained in:
Piotr Tomiak
2019-10-01 13:31:53 +00:00
committed by intellij-monorepo-bot
parent a8c29639f4
commit 57f9fd0d05
24 changed files with 337 additions and 116 deletions
@@ -18,7 +18,6 @@ package org.intellij.lang.xpath.xslt.util;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.xml.XmlTagImpl;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
@@ -30,14 +29,14 @@ import java.util.List;
public class NSDeclTracker implements ModificationTracker {
private static final Key<Long> MOD_COUNT = Key.create("MOD_COUNT");
private final XmlTagImpl myRootTag;
private final XmlTag myRootTag;
private final PsiFile myFile;
private final List<XmlAttribute> myNSDecls;
private long myRootCount;
private int myCount;
public NSDeclTracker(XmlTag rootTag) {
myRootTag = (XmlTagImpl)rootTag;
myRootTag = rootTag;
myFile = rootTag.getContainingFile();
myNSDecls = getNSDecls(false);
myRootCount = myFile.getModificationStamp();
@@ -23,6 +23,7 @@ import com.intellij.psi.impl.source.tree.Factory;
import com.intellij.psi.impl.source.tree.LeafElement;
import com.intellij.psi.impl.source.tree.SharedImplUtil;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.xml.IXmlTagElementType;
import com.intellij.psi.xml.XmlElementType;
import com.intellij.psi.xml.XmlText;
import com.intellij.psi.xml.XmlTokenType;
@@ -68,8 +69,7 @@ public class XmlWhiteSpaceFormattingStrategy extends WhiteSpaceFormattingStrateg
protected boolean isInsideTagBody(@NotNull ASTNode place) {
final ASTNode treeParent = place.getTreeParent();
if(treeParent.getElementType() != XmlElementType.XML_TAG
&& treeParent.getElementType() != XmlElementType.HTML_TAG) return false;
if (!(treeParent.getElementType() instanceof IXmlTagElementType)) return false;
while(place != null){
if(place.getElementType() == XmlTokenType.XML_TAG_END) return true;
place = place.getTreePrev();
@@ -20,24 +20,24 @@ import com.intellij.codeInsight.navigation.GotoTargetRendererProvider;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.xml.XmlTagImpl;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
public class GotoXmlSchemaTypeRendererProvider implements GotoTargetRendererProvider {
@Override
public PsiElementListCellRenderer getRenderer(@NotNull PsiElement element, @NotNull GotoTargetHandler.GotoData gotoData) {
if (element instanceof XmlTagImpl) {
if (SchemaDefinitionsSearch.isTypeElement((XmlTagImpl)element)) {
if (element instanceof XmlTag) {
if (SchemaDefinitionsSearch.isTypeElement((XmlTag)element)) {
return new MyRenderer("");
} else if (SchemaDefinitionsSearch.isElementWithSomeEmbeddedType((XmlTagImpl)element)) {
} else if (SchemaDefinitionsSearch.isElementWithSomeEmbeddedType((XmlTag)element)) {
return new MyRenderer("xsd:element: ");
}
}
return null;
}
private static class MyRenderer extends PsiElementListCellRenderer<XmlTagImpl> {
private static class MyRenderer extends PsiElementListCellRenderer<XmlTag> {
private final String myPrefix;
private MyRenderer(String prefix) {
@@ -45,13 +45,13 @@ public class GotoXmlSchemaTypeRendererProvider implements GotoTargetRendererProv
}
@Override
public String getElementText(XmlTagImpl element) {
public String getElementText(XmlTag element) {
final XmlAttribute attr = SchemaDefinitionsSearch.getNameAttr(element);
return myPrefix + (attr == null || attr.getValue() == null ? element.getName() : attr.getValue());
}
@Override
protected String getContainerText(XmlTagImpl element, String name) {
protected String getContainerText(XmlTag element, String name) {
final PsiFile file = element.getContainingFile();
return "(" + file.getName() + ")";
}
@@ -10,14 +10,12 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.xml.XmlTagImpl;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import java.util.HashSet;
import com.intellij.xml.index.SchemaTypeInfo;
import com.intellij.xml.index.SchemaTypeInheritanceIndex;
import com.intellij.xml.index.XmlNamespaceIndex;
@@ -30,8 +28,8 @@ import java.util.function.BiFunction;
public class SchemaDefinitionsSearch implements QueryExecutor<PsiElement, PsiElement> {
@Override
public boolean execute(@NotNull final PsiElement queryParameters, @NotNull final Processor<? super PsiElement> consumer) {
if (queryParameters instanceof XmlTagImpl) {
final XmlTagImpl xml = (XmlTagImpl) queryParameters;
if (queryParameters instanceof XmlTag) {
final XmlTag xml = (XmlTag)queryParameters;
if (ReadAction.compute(() -> isTypeElement(xml))) {
final Collection<SchemaTypeInfo> infos = ReadAction.compute(() -> gatherInheritors(xml));
@@ -70,9 +68,9 @@ public class SchemaDefinitionsSearch implements QueryExecutor<PsiElement, PsiEle
final PsiElementProcessor processor = new PsiElementProcessor() {
@Override
public boolean execute(@NotNull PsiElement element) {
if (element instanceof XmlTagImpl) {
if (isCertainTypeElement((XmlTagImpl)element, info.getTagName(), prefixByURI) ||
isElementWithEmbeddedType((XmlTagImpl)element, info.getTagName(), prefixByURI)) {
if (element instanceof XmlTag) {
if (isCertainTypeElement((XmlTag)element, info.getTagName(), prefixByURI) ||
isElementWithEmbeddedType((XmlTag)element, info.getTagName(), prefixByURI)) {
consumer.process(element);
return false;
}
@@ -91,21 +89,21 @@ public class SchemaDefinitionsSearch implements QueryExecutor<PsiElement, PsiEle
return true;
}
public static boolean isElementWithSomeEmbeddedType(XmlTagImpl xml) {
public static boolean isElementWithSomeEmbeddedType(XmlTag xml) {
final String localName = xml.getLocalName();
if (! (XmlUtil.XML_SCHEMA_URI.equals(xml.getNamespace()) && "element".equals(localName))) {
return false;
}
final XmlTag[] tags = xml.getSubTags();
for (XmlTag tag : tags) {
if (isTypeElement((XmlTagImpl)tag)) {
if (isTypeElement(tag)) {
return true;
}
}
return false;
}
public static boolean isElementWithEmbeddedType(XmlTagImpl xml, final String typeName, final String typeNsPrefix) {
public static boolean isElementWithEmbeddedType(XmlTag xml, final String typeName, final String typeNsPrefix) {
final String localName = xml.getLocalName();
if (! (XmlUtil.XML_SCHEMA_URI.equals(xml.getNamespace()) && "element".equals(localName))) {
return false;
@@ -119,14 +117,14 @@ public class SchemaDefinitionsSearch implements QueryExecutor<PsiElement, PsiEle
}
final XmlTag[] tags = xml.getSubTags();
for (XmlTag tag : tags) {
if (isTypeElement((XmlTagImpl)tag)) {
if (isTypeElement(tag)) {
return true;
}
}
return false;
}
private boolean isCertainTypeElement(XmlTagImpl xml, final String typeName, final String nsPrefix) {
private boolean isCertainTypeElement(XmlTag xml, final String typeName, final String nsPrefix) {
if (! isTypeElement(xml)) return false;
final XmlAttribute name = getNameAttr(xml);
if (name == null) return false;
@@ -136,12 +134,12 @@ public class SchemaDefinitionsSearch implements QueryExecutor<PsiElement, PsiEle
return typeName.equals(localName) && nsPrefix.equals(XmlUtil.findPrefixByQualifiedName(value));
}
public static boolean isTypeElement(XmlTagImpl xml) {
public static boolean isTypeElement(XmlTag xml) {
final String localName = xml.getLocalName();
return XmlUtil.XML_SCHEMA_URI.equals(xml.getNamespace()) && ("complexType".equals(localName) || "simpleType".equals(localName));
}
private Collection<SchemaTypeInfo> gatherInheritors(XmlTagImpl xml) {
private Collection<SchemaTypeInfo> gatherInheritors(XmlTag xml) {
XmlAttribute name = getNameAttr(xml);
if (name == null || StringUtil.isEmptyOrSpaces(name.getValue())) return null;
String localName = name.getValue();
@@ -184,7 +182,7 @@ public class SchemaDefinitionsSearch implements QueryExecutor<PsiElement, PsiEle
return result;
}
public static XmlAttribute getNameAttr(XmlTagImpl xml) {
public static XmlAttribute getNameAttr(XmlTag xml) {
XmlAttribute name = xml.getAttribute("name", XmlUtil.XML_SCHEMA_URI);
name = name == null ? xml.getAttribute("name") : name;
return name;
@@ -111,6 +111,10 @@ public interface XmlTag extends XmlElement, PsiNamedElement, PsiMetaOwner, XmlTa
@Nullable @NonNls
String getSubTagText(@NonNls String qname);
default boolean isCaseSensitive() {
return true;
}
@Nullable
default String getRealNs(@Nullable String value) {
return value;
@@ -27,7 +27,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.html.HtmlEmbeddedContentImpl;
import com.intellij.psi.impl.source.html.HtmlFileImpl;
import com.intellij.psi.impl.source.xml.stub.XmlStubBasedAttributeElementType;
import com.intellij.psi.impl.source.xml.stub.XmlStubBasedElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtilCore;
@@ -77,8 +77,9 @@ public class HTMLParserDefinition implements ParserDefinition {
@Override
@NotNull
public PsiElement createElement(ASTNode node) {
if (node.getElementType() instanceof XmlStubBasedAttributeElementType) {
return ((XmlStubBasedAttributeElementType)node.getElementType()).createPsi(node);
if (node.getElementType() instanceof XmlStubBasedElementType) {
//noinspection rawtypes
return ((XmlStubBasedElementType)node.getElementType()).createPsi(node);
}
if (node.getElementType() == XmlElementType.HTML_EMBEDDED_CONTENT) {
return new HtmlEmbeddedContentImpl(node);
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.parsing.xml.XmlParser;
import com.intellij.psi.impl.source.xml.XmlFileImpl;
import com.intellij.psi.impl.source.xml.stub.XmlStubBasedElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtilCore;
@@ -75,6 +76,10 @@ public class XMLParserDefinition implements ParserDefinition {
@Override
@NotNull
public PsiElement createElement(ASTNode node) {
if (node.getElementType() instanceof XmlStubBasedElementType) {
//noinspection rawtypes
return ((XmlStubBasedElementType)node.getElementType()).createPsi(node);
}
return PsiUtilCore.NULL_PSI_ELEMENT;
}
@@ -0,0 +1,54 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.source.html;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.psi.impl.source.xml.stub.XmlStubBasedElementType;
import com.intellij.psi.impl.source.xml.stub.XmlTagStubImpl;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.tree.ICompositeElementType;
import com.intellij.psi.xml.IXmlTagElementType;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class HtmlStubBasedTagElementType
extends XmlStubBasedElementType<XmlTagStubImpl, HtmlStubBasedTagImpl> implements ICompositeElementType, IXmlTagElementType {
public HtmlStubBasedTagElementType(@NotNull String debugName,
@NotNull Language language) {
super(debugName, language);
}
@Override
public void serialize(@NotNull XmlTagStubImpl stub, @NotNull StubOutputStream dataStream) throws IOException {
stub.serialize(dataStream);
}
@NotNull
@Override
public XmlTagStubImpl deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
return new XmlTagStubImpl(parentStub, dataStream, this);
}
@Override
@NotNull
public HtmlStubBasedTagImpl createPsi(@NotNull XmlTagStubImpl stub) {
return new HtmlStubBasedTagImpl(stub, this);
}
@Override
@NotNull
public HtmlStubBasedTagImpl createPsi(@NotNull ASTNode node) {
return new HtmlStubBasedTagImpl(node);
}
@NotNull
@Override
public XmlTagStubImpl createStub(@NotNull HtmlStubBasedTagImpl psi, StubElement parentStub) {
return new XmlTagStubImpl(psi, parentStub, this);
}
}
@@ -0,0 +1,130 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.source.html;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.html.HtmlTag;
import com.intellij.psi.impl.source.xml.XmlStubBasedTag;
import com.intellij.psi.impl.source.xml.XmlTagDelegate;
import com.intellij.psi.impl.source.xml.stub.XmlTagStubImpl;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class HtmlStubBasedTagImpl extends XmlStubBasedTag implements HtmlTag {
public HtmlStubBasedTagImpl(@NotNull XmlTagStubImpl stub,
@NotNull IStubElementType<? extends XmlTagStubImpl, ? extends HtmlStubBasedTagImpl> nodeType) {
super(stub, nodeType);
}
public HtmlStubBasedTagImpl(@NotNull ASTNode node) {
super(node);
}
@Override
@NotNull
public XmlTag[] findSubTags(@NotNull String name, String namespace) {
final XmlTag[] subTags = getSubTags();
List<XmlTag> result = null;
for (final XmlTag subTag : subTags) {
if (namespace == null) {
String tagName = subTag.getName();
tagName = StringUtil.toLowerCase(tagName);
if (name == null || name.equals(tagName)) {
if (result == null) {
result = new ArrayList<>(3);
}
result.add(subTag);
}
}
else if (namespace.equals(subTag.getNamespace()) &&
(name == null || name.equals(subTag.getLocalName()))
) {
if (result == null) {
result = new ArrayList<>(3);
}
result.add(subTag);
}
}
return result == null ? EMPTY : result.toArray(XmlTag.EMPTY);
}
@Override
public String getAttributeValue(String qname) {
qname = StringUtil.toLowerCase(qname);
return super.getAttributeValue(qname);
}
@Override
public String getAttributeValue(String name, String namespace) {
name = StringUtil.toLowerCase(name);
return super.getAttributeValue(name, namespace);
}
@Override
@NotNull
public String getNamespace() {
final String xmlNamespace = super.getNamespace();
if (!getNamespacePrefix().isEmpty()) {
return xmlNamespace;
}
if (xmlNamespace.isEmpty() || xmlNamespace.equals(XmlUtil.XHTML_URI)) {
return XmlUtil.HTML_URI;
}
// ex.: mathML and SVG namespaces can be used inside html file
return xmlNamespace;
}
@Nullable
@Override
public String getRealNs(@Nullable final String value) {
if (XmlUtil.XHTML_URI.equals(value)) return XmlUtil.HTML_URI;
return value;
}
@Override
public String toString() {
return "HtmlTag:" + getName();
}
@Override
public String getPrefixByNamespace(String namespace) {
if (XmlUtil.HTML_URI.equals(namespace)) namespace = XmlUtil.XHTML_URI;
return super.getPrefixByNamespace(namespace);
}
@Override
public XmlTag getParentTag() {
return PsiTreeUtil.getParentOfType(this, XmlTag.class);
}
@NotNull
@Override
protected XmlTagDelegate createDelegate() {
return new HtmlTagImplDelegate();
}
private class HtmlTagImplDelegate extends XmlStubBasedTagDelegate {
@Override
protected void cacheOneAttributeValue(String name, String value, final Map<String, String> attributesValueMap) {
name = StringUtil.toLowerCase(name);
super.cacheOneAttributeValue(name, value, attributesValueMap);
}
}
}
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.xml.IXmlAttributeElementType;
import com.intellij.psi.xml.IXmlTagElementType;
import com.intellij.psi.xml.XmlElementType;
import com.intellij.psi.xml.XmlTokenType;
import com.intellij.util.containers.Stack;
@@ -70,7 +71,7 @@ public class XmlBuilderDriver {
for (int i = 0; i < count; i++) {
LighterASTNode child = children[i];
final IElementType tt = child.getTokenType();
if (tt == XmlElementType.XML_TAG || tt == XmlElementType.HTML_TAG) {
if (tt instanceof IXmlTagElementType) {
processTagNode(b, structure, child, builder);
}
else if (tt == XmlElementType.XML_PROLOG) {
@@ -154,7 +155,7 @@ public class XmlBuilderDriver {
LighterASTNode node,
XmlBuilder builder) {
final IElementType nodeTT = node.getTokenType();
assert nodeTT == XmlElementType.XML_TAG || nodeTT == XmlElementType.HTML_TAG;
assert nodeTT instanceof IXmlTagElementType;
final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
final int count = structure.getChildren(node, childrenRef);
@@ -190,7 +191,7 @@ public class XmlBuilderDriver {
LighterASTNode child = children[i];
IElementType tt = child.getTokenType();
if (tt == TokenType.ERROR_ELEMENT) processErrorNode(psiBuilder, child, builder);
if (tt == XmlElementType.XML_TAG || tt == XmlElementType.HTML_TAG) processTagNode(psiBuilder, structure, child, builder);
if (tt instanceof IXmlTagElementType) processTagNode(psiBuilder, structure, child, builder);
if (processAttrs && tt instanceof IXmlAttributeElementType) processAttributeNode(child, structure, builder);
if (processTexts && tt == XmlElementType.XML_TEXT) processTextNode(structure, child, builder);
if (tt == XmlElementType.XML_ENTITY_REF) builder.entityRef(getTokenText(child), child.getStartOffset(), child.getEndOffset());
@@ -10,12 +10,16 @@ import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.util.XmlPsiUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* Simplified stub-based version of {@link XmlElementImpl}
*
@@ -41,7 +45,7 @@ abstract class XmlStubBasedElement<T extends StubElement<?>> extends StubBasedPs
@Override
public PsiElement getContext() {
final XmlElement data = getUserData(INCLUDING_ELEMENT);
if(data != null) return data;
if (data != null) return data;
return super.getContext();
}
@@ -64,9 +68,10 @@ abstract class XmlStubBasedElement<T extends StubElement<?>> extends StubBasedPs
@Override
public PsiElement getParent() {
final XmlElement data = getUserData(INCLUDING_ELEMENT);
if(data != null) return data;
if (data != null) return data;
return super.getParent();
}
@Override
@NotNull
public Language getLanguage() {
@@ -105,6 +110,20 @@ abstract class XmlStubBasedElement<T extends StubElement<?>> extends StubBasedPs
putUserData(DO_NOT_VALIDATE, null);
}
@Override
@NotNull
public PsiElement[] getChildren() {
PsiElement psiChild = getFirstChild();
if (psiChild == null) return PsiElement.EMPTY_ARRAY;
List<PsiElement> result = new ArrayList<>();
while (psiChild != null) {
result.add(psiChild);
psiChild = psiChild.getNextSibling();
}
return PsiUtilCore.toPsiElementArray(result);
}
@Override
public String toString() {
return "PsiElement" + "(" + getElementType() + ")";
@@ -65,6 +65,8 @@ public class XmlStubBasedTagBase<StubT extends XmlTagStub<?>>
public void subtreeChanged() {
super.subtreeChanged();
myImpl = null;
myValue = null;
myAttributes = null;
}
@Override
@@ -207,6 +209,7 @@ public class XmlStubBasedTagBase<StubT extends XmlTagStub<?>>
return getImpl().getAttribute(qname);
}
@Override
public boolean isCaseSensitive() {
return true;
}
@@ -374,11 +377,6 @@ public class XmlStubBasedTagBase<StubT extends XmlTagStub<?>>
super(XmlStubBasedTagBase.this);
}
@Override
protected boolean isCaseSensitive() {
return XmlStubBasedTagBase.this.isCaseSensitive();
}
@Override
protected void deleteChildInternalSuper(@NotNull ASTNode child) {
XmlStubBasedTagBase.super.deleteChildInternal(child);
@@ -73,8 +73,6 @@ public abstract class XmlTagDelegate {
myTag = tag;
}
protected abstract boolean isCaseSensitive();
protected abstract void deleteChildInternalSuper(@NotNull final ASTNode child);
protected abstract TreeElement addInternalSuper(TreeElement first, ASTNode last, @Nullable ASTNode anchor, @Nullable Boolean before);
@@ -690,7 +688,7 @@ public abstract class XmlTagDelegate {
if (qname == null) return null;
final XmlAttribute[] attributes = myTag.getAttributes();
final boolean caseSensitive = isCaseSensitive();
final boolean caseSensitive = myTag.isCaseSensitive();
for (final XmlAttribute attribute : attributes) {
final ASTNode child = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(attribute.getNode());
@@ -1075,8 +1073,8 @@ public abstract class XmlTagDelegate {
// insert child just after anchor
// insert into the position specified by index
if (subTagNum >= 0) {
final ASTNode subTag = (ASTNode)subTags[subTagNum];
if (subTag.getTreeParent() != myTag) {
final ASTNode subTag = subTags[subTagNum].getNode();
if (subTag.getTreeParent() != myTag.getNode()) {
// in entity
final XmlEntityRef entityRef = PsiTreeUtil.getParentOfType(subTags[subTagNum], XmlEntityRef.class);
throw new IncorrectOperationException(
@@ -224,10 +224,6 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc
return getImpl().getAttribute(qname);
}
public boolean isCaseSensitive() {
return true;
}
@Override
@NotNull
public String getNamespace() {
@@ -390,11 +386,6 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc
super(XmlTagImpl.this);
}
@Override
protected boolean isCaseSensitive() {
return XmlTagImpl.this.isCaseSensitive();
}
@Override
protected void deleteChildInternalSuper(@NotNull ASTNode child) {
XmlTagImpl.super.deleteChildInternal(child);
@@ -82,7 +82,7 @@ public class XmlTagValueImpl implements XmlTagValue{
@NotNull
public TextRange getTextRange() {
if(myElements.length == 0){
final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild( (ASTNode)myTag);
final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(myTag.getNode());
if(child != null)
return new TextRange(child.getStartOffset() + 1, child.getStartOffset() + 1);
return new TextRange(myTag.getTextRange().getEndOffset(), myTag.getTextRange().getEndOffset());
@@ -16,7 +16,7 @@ public class XmlAttributeStubImpl extends StubBase<XmlStubBasedAttribute> implem
@NotNull private final String name;
@Nullable private final String value;
XmlAttributeStubImpl(@Nullable StubElement<?> parent,
public XmlAttributeStubImpl(@Nullable StubElement<?> parent,
@NotNull StubInputStream dataStream,
@NotNull IStubElementType<? extends XmlAttributeStubImpl, ? extends XmlStubBasedAttribute> elementType)
throws IOException {
@@ -25,7 +25,7 @@ public class XmlAttributeStubImpl extends StubBase<XmlStubBasedAttribute> implem
value = StringRef.toString(dataStream.readName());
}
XmlAttributeStubImpl(@NotNull XmlStubBasedAttribute psi,
public XmlAttributeStubImpl(@NotNull XmlStubBasedAttribute psi,
@Nullable StubElement<?> parent,
@NotNull IStubElementType<? extends XmlAttributeStubImpl, ? extends XmlStubBasedAttribute> elementType) {
super(parent, elementType);
@@ -3,24 +3,23 @@ package com.intellij.psi.impl.source.xml.stub;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.xml.XmlStubBasedAttribute;
import com.intellij.psi.stubs.*;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.tree.ICompositeElementType;
import com.intellij.psi.xml.IXmlAttributeElementType;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Locale;
public class XmlStubBasedAttributeElementType
extends IStubElementType<XmlAttributeStubImpl, XmlStubBasedAttribute> implements ICompositeElementType {
extends XmlStubBasedElementType<XmlAttributeStubImpl, XmlStubBasedAttribute> implements ICompositeElementType, IXmlAttributeElementType {
private final @NotNull String externalId;
public XmlStubBasedAttributeElementType(@NotNull String debugName,
@NotNull Language language) {
super(language.getID().toUpperCase(Locale.ENGLISH) + ":" + debugName, language);
externalId = language.getID().toUpperCase(Locale.ENGLISH) + ":" + debugName;
super(debugName, language);
}
@Override
@@ -34,36 +33,22 @@ public class XmlStubBasedAttributeElementType
return new XmlAttributeStubImpl(parentStub, dataStream, this);
}
@Override
public void indexStub(@NotNull XmlAttributeStubImpl stub, @NotNull IndexSink sink) {
}
@Override
@NotNull
public XmlStubBasedAttribute createPsi(@NotNull XmlAttributeStubImpl stub) {
return new XmlStubBasedAttribute(stub, this);
}
@Override
@NotNull
public XmlStubBasedAttribute createPsi(@NotNull ASTNode node) {
return new XmlStubBasedAttribute(node);
}
@NotNull
@Override
public String getExternalId() {
return externalId;
}
@NotNull
@Override
public XmlAttributeStubImpl createStub(@NotNull XmlStubBasedAttribute psi, StubElement parentStub) {
return new XmlAttributeStubImpl(psi, parentStub, this);
}
@NotNull
@Override
public ASTNode createCompositeNode() {
return new CompositeElement(this);
}
}
@@ -0,0 +1,46 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.source.xml.stub;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.ICompositeElementType;
import org.jetbrains.annotations.NotNull;
import java.util.Locale;
public abstract class XmlStubBasedElementType<StubT extends StubElement<?>, PsiT extends PsiElement>
extends IStubElementType<StubT, PsiT> implements ICompositeElementType {
private final @NotNull String externalId;
public XmlStubBasedElementType(@NotNull String debugName,
@NotNull Language language) {
super((language == XMLLanguage.INSTANCE ? "" : language.getID().toUpperCase(Locale.ENGLISH) + ":") + debugName, language);
externalId = (language == XMLLanguage.INSTANCE ? "" : language.getID().toUpperCase(Locale.ENGLISH) + ":") + debugName;
}
@Override
public void indexStub(@NotNull StubT stub, @NotNull IndexSink sink) {
}
@NotNull
public abstract PsiT createPsi(@NotNull ASTNode node);
@NotNull
@Override
public String getExternalId() {
return externalId;
}
@NotNull
@Override
public ASTNode createCompositeNode() {
return new CompositeElement(this);
}
}
@@ -3,24 +3,22 @@ package com.intellij.psi.impl.source.xml.stub;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.xml.XmlStubBasedTag;
import com.intellij.psi.stubs.*;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.tree.ICompositeElementType;
import com.intellij.psi.xml.IXmlTagElementType;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Locale;
public class XmlStubBasedTagElementType
extends IStubElementType<XmlTagStubImpl, XmlStubBasedTag> implements ICompositeElementType {
private final @NotNull String externalId;
extends XmlStubBasedElementType<XmlTagStubImpl, XmlStubBasedTag> implements ICompositeElementType, IXmlTagElementType {
public XmlStubBasedTagElementType(@NotNull String debugName,
@NotNull Language language) {
super(language.getID().toUpperCase(Locale.ENGLISH) + ":" + debugName, language);
externalId = language.getID().toUpperCase(Locale.ENGLISH) + ":" + debugName;
super(debugName, language);
}
@Override
@@ -34,36 +32,22 @@ public class XmlStubBasedTagElementType
return new XmlTagStubImpl(parentStub, dataStream, this);
}
@Override
public void indexStub(@NotNull XmlTagStubImpl stub, @NotNull IndexSink sink) {
}
@Override
@NotNull
public XmlStubBasedTag createPsi(@NotNull XmlTagStubImpl stub) {
return new XmlStubBasedTag(stub, this);
}
@Override
@NotNull
public XmlStubBasedTag createPsi(@NotNull ASTNode node) {
return new XmlStubBasedTag(node);
}
@NotNull
@Override
public String getExternalId() {
return externalId;
}
@NotNull
@Override
public XmlTagStubImpl createStub(@NotNull XmlStubBasedTag psi, StubElement parentStub) {
return new XmlTagStubImpl(psi, parentStub, this);
}
@NotNull
@Override
public ASTNode createCompositeNode() {
return new CompositeElement(this);
}
}
@@ -15,7 +15,7 @@ public class XmlTagStubImpl extends StubBase<XmlStubBasedTag> implements XmlTagS
@NotNull private final String name;
XmlTagStubImpl(@Nullable StubElement<?> parent,
public XmlTagStubImpl(@Nullable StubElement<?> parent,
@NotNull StubInputStream dataStream,
@NotNull IStubElementType<? extends XmlTagStubImpl, ? extends XmlStubBasedTag> elementType)
throws IOException {
@@ -23,14 +23,14 @@ public class XmlTagStubImpl extends StubBase<XmlStubBasedTag> implements XmlTagS
name = notNull(StringRef.toString(dataStream.readName()), "");
}
XmlTagStubImpl(@NotNull XmlStubBasedTag psi,
public XmlTagStubImpl(@NotNull XmlStubBasedTag psi,
@Nullable StubElement<?> parent,
@NotNull IStubElementType<? extends XmlTagStubImpl, ? extends XmlStubBasedTag> elementType) {
super(parent, elementType);
name = psi.getName();
}
void serialize(StubOutputStream stream) throws IOException {
public void serialize(StubOutputStream stream) throws IOException {
stream.writeName(name);
}
@@ -0,0 +1,5 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.xml;
public interface IXmlTagElementType {
}
@@ -23,6 +23,7 @@ import com.intellij.lang.xhtml.XHTMLLanguage;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.parsing.xml.DtdParsing;
import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.psi.tree.*;
import com.intellij.psi.tree.xml.IXmlElementType;
import com.intellij.util.CharTable;
@@ -37,7 +38,7 @@ public interface XmlElementType extends XmlTokenType {
IElementType XML_DOCTYPE = new IXmlElementType("XML_DOCTYPE");
IElementType XML_ATTRIBUTE = new XmlAttributeElementType();
IElementType XML_COMMENT = new IXmlElementType("XML_COMMENT");
IElementType XML_TAG = new IXmlElementType("XML_TAG");
IElementType XML_TAG = new XmlTagElementType("XML_TAG");
IElementType XML_ELEMENT_DECL = new IXmlElementType("XML_ELEMENT_DECL");
IElementType XML_CONDITIONAL_SECTION = new IXmlElementType("XML_CONDITIONAL_SECTION");
@@ -55,11 +56,11 @@ public interface XmlElementType extends XmlTokenType {
//todo: move to html
IElementType HTML_DOCUMENT = new IXmlElementType("HTML_DOCUMENT");
IElementType HTML_TAG = new IXmlElementType("HTML_TAG");
IFileElementType HTML_FILE = new IStubFileElementType(HTMLLanguage.INSTANCE) {
IElementType HTML_TAG = new XmlTagElementType("HTML_TAG");
IFileElementType HTML_FILE = new IStubFileElementType<PsiFileStub<?>>(HTMLLanguage.INSTANCE) {
@Override
public int getStubVersion() {
return super.getStubVersion() + 1;
return super.getStubVersion() + 2;
}
};
IElementType HTML_EMBEDDED_CONTENT = new EmbeddedHtmlContentElementType();
@@ -72,7 +73,7 @@ public interface XmlElementType extends XmlTokenType {
IFileElementType DTD_FILE = new IFileElementType("DTD_FILE", DTDLanguage.INSTANCE);
IElementType XML_MARKUP_DECL = new CustomParsingType("XML_MARKUP_DECL", XMLLanguage.INSTANCE){
IElementType XML_MARKUP_DECL = new CustomParsingType("XML_MARKUP_DECL", XMLLanguage.INSTANCE) {
@NotNull
@Override
public ASTNode parse(@NotNull CharSequence text, @NotNull CharTable table) {
@@ -96,6 +97,10 @@ public interface XmlElementType extends XmlTokenType {
}
}
final class XmlTagElementType extends IXmlElementType implements IXmlTagElementType {
public XmlTagElementType(String debugName) {super(debugName);}
}
final class XmlAttributeElementType extends IXmlElementType implements IXmlAttributeElementType {
public XmlAttributeElementType() {super("XML_ATTRIBUTE");}
}
@@ -31,7 +31,6 @@ import com.intellij.psi.impl.source.html.HtmlDocumentImpl;
import com.intellij.psi.impl.source.parsing.xml.HtmlBuilderDriver;
import com.intellij.psi.impl.source.parsing.xml.XmlBuilder;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.xml.XmlTagImpl;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
import com.intellij.psi.util.PsiTreeUtil;
@@ -136,7 +135,7 @@ public class HtmlUtil {
public static boolean isSingleHtmlTag(@NotNull XmlTag tag, boolean lowerCase) {
final XmlExtension extension = XmlExtension.getExtensionByElement(tag);
final String name = tag.getName();
boolean result = EMPTY_TAGS_MAP.contains(!lowerCase || tag instanceof XmlTagImpl && ((XmlTagImpl)tag).isCaseSensitive()
boolean result = EMPTY_TAGS_MAP.contains(!lowerCase || tag.isCaseSensitive()
? name : StringUtil.toLowerCase(name));
return result && (extension == null || !extension.isSingleTagException(tag));
}
@@ -6,7 +6,6 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.xml.XmlTagImpl;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -67,7 +66,7 @@ public class HtmlCompatibilityData {
@Nullable
public static Map getTagData(@Nullable XmlTag tag) {
if (tag == null) return null;
String key = tag instanceof XmlTagImpl && ((XmlTagImpl)tag).isCaseSensitive() ?
String key = tag.isCaseSensitive() ?
tag.getName() :
StringUtil.toLowerCase(tag.getName());
if ("input".equals(key)) {
@@ -83,8 +82,8 @@ public class HtmlCompatibilityData {
PsiElement element = tag;
while (element != null && !(element instanceof PsiFile)) {
if (element instanceof XmlTag) {
String name = element instanceof XmlTagImpl && ((XmlTagImpl)tag).isCaseSensitive() ?
((XmlTagImpl)element).getName() :
String name = tag.isCaseSensitive() ?
((XmlTag)element).getName() :
StringUtil.toLowerCase(((XmlTag)element).getName());
if (MATH.equals(name)) {