From 6c2e45f8d58341f15dd6af579596776c5cd92632 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 22 Aug 2012 14:20:09 +0400 Subject: [PATCH] DOM stubs for custom elements --- .../source/tree/LazyParseableElement.java | 11 +++++ .../impl/AbstractDomChildDescriptionImpl.java | 16 +++++++ .../intellij/util/xml/impl/DomAnchorImpl.java | 33 +++++++++++++ .../util/xml/impl/DomFileElementImpl.java | 5 ++ .../util/xml/impl/DomInvocationHandler.java | 48 ++++++++++++++----- .../util/xml/impl/DomParentStrategy.java | 2 + .../util/xml/impl/DynamicGenericInfo.java | 7 ++- .../xml/impl/PhysicalDomParentStrategy.java | 5 ++ .../util/xml/impl/RootDomParentStrategy.java | 5 ++ .../xml/impl/VirtualDomParentStrategy.java | 6 ++- .../com/intellij/util/xml/stubs/DomStub.java | 12 ++--- .../intellij/util/xml/stubs/ElementStub.java | 8 +++- .../util/xml/stubs/ElementStubSerializer.java | 3 +- .../com/intellij/util/xml/stubs/FileStub.java | 4 +- .../util/xml/stubs/StubParentStrategy.java | 43 ++++++++++++----- .../xml/stubs/builder/DomStubBuilder.java | 2 +- .../stubs/builder/DomStubBuilderVisitor.java | 6 ++- .../xml/impl/dom/DomElementXmlDescriptor.java | 5 ++ .../src/com/intellij/util/xml/DomElement.java | 17 ++++--- .../src/com/intellij/util/xml/DomUtil.java | 20 ++++++-- .../AbstractDomChildrenDescription.java | 2 + .../com/intellij/util/xml/MockDomElement.java | 5 ++ .../intellij/util/xml/MockDomFileElement.java | 5 ++ .../intellij/util/xml/stubs/DomStubTest.java | 21 ++++++++ .../util/xml/stubs/DomStubUsingTest.java | 34 ++++--------- .../source/parsing/xml/XmlBuilderDriver.java | 10 +--- .../src/com/intellij/xml/util/XmlUtil.java | 8 ++++ 27 files changed, 258 insertions(+), 85 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index d2968ebcfea5..c259563ae638 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -28,6 +28,7 @@ import com.intellij.psi.tree.ILazyParseableElementType; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.TestOnly; public class LazyParseableElement extends CompositeElement { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.LazyParseableElement"); @@ -147,6 +148,9 @@ public class LazyParseableElement extends CompositeElement { } private void ensureParsed() { + if (!ourParsingAllowed) { + LOG.error("Parsing not allowed!!!"); + } CharSequence text = myText(); if (text == null) return; @@ -220,4 +224,11 @@ public class LazyParseableElement extends CompositeElement { } return start + text.length(); } + + private static boolean ourParsingAllowed = true; + + @TestOnly + public static void setParsingAllowed(boolean allowed) { + ourParsingAllowed = allowed; + } } diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/AbstractDomChildDescriptionImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/AbstractDomChildDescriptionImpl.java index 0c43f399491b..1199ec8ccd7b 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/AbstractDomChildDescriptionImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/AbstractDomChildDescriptionImpl.java @@ -19,10 +19,12 @@ import com.intellij.ide.presentation.Presentation; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.NullableLazyValue; import com.intellij.pom.references.PomService; import com.intellij.psi.PsiElement; import com.intellij.psi.SmartPsiElementPointer; +import com.intellij.psi.stubs.Stubbed; import com.intellij.util.ReflectionUtil; import com.intellij.util.xml.*; import com.intellij.util.xml.reflect.AbstractDomChildrenDescription; @@ -62,6 +64,15 @@ public abstract class AbstractDomChildDescriptionImpl implements AbstractDomChil myCustomAnnotations.put(annotation.annotationType(), annotation); } + private NotNullLazyValue myStubbed = new NotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + return myType instanceof Class && DomReflectionUtil.findAnnotationDFS((Class)myType, Stubbed.class) != null || + getAnnotation(Stubbed.class) != null; + } + }; + @Override public boolean equals(Object o) { if (this == o) return true; @@ -188,4 +199,9 @@ public abstract class AbstractDomChildDescriptionImpl implements AbstractDomChil } return null; } + + @Override + public boolean isStubbed() { + return myStubbed.getValue(); + } } diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java index 469f7d72d429..4fa7f613fef6 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomAnchorImpl.java @@ -39,6 +39,7 @@ public abstract class DomAnchorImpl implements DomAnchor DomAnchorImpl createAnchor(@NotNull T t) { return createAnchor(t, false); } + public static DomAnchorImpl createAnchor(@NotNull T t, boolean usePsi) { if (usePsi) { final XmlElement element = t.getXmlElement(); @@ -345,4 +346,36 @@ public abstract class DomAnchorImpl implements DomAnchor implements DomAnchor { + + private final DomInvocationHandler myHandler; + + private StubAnchor(DomInvocationHandler handler) { + myHandler = handler; + } + + @Nullable + @Override + public T retrieveDomElement() { + return (T)myHandler.getProxy(); + } + + @NotNull + @Override + public XmlFile getContainingFile() { + return myHandler.getFile(); + } + + @Nullable + @Override + public PsiElement getPsiElement() { + return myHandler.getXmlElement(); + } + } + + public static DomAnchor createStubAnchor(T element) { + DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(element); + return handler.getStub() == null ? createAnchor(element, true) : new StubAnchor(handler); + } } diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomFileElementImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomFileElementImpl.java index e6dc26567e48..305e706f6311 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomFileElementImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomFileElementImpl.java @@ -332,6 +332,11 @@ public class DomFileElementImpl implements DomFileElement< return checkValidity() == null; } + @Override + public boolean exists() { + return true; + } + @Nullable public String checkValidity() { if (!myFile.isValid()) { diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java index 5330b2ec61c8..090080e2a739 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java @@ -13,7 +13,6 @@ import com.intellij.psi.SmartPointerManager; import com.intellij.psi.SmartPsiElementPointer; import com.intellij.psi.XmlElementFactory; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.stubs.Stubbed; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; @@ -27,6 +26,7 @@ import com.intellij.util.xml.events.DomEvent; import com.intellij.util.xml.reflect.*; import com.intellij.util.xml.stubs.AttributeStub; import com.intellij.util.xml.stubs.DomStub; +import com.intellij.util.xml.stubs.ElementStub; import com.intellij.util.xml.stubs.StubParentStrategy; import net.sf.cglib.proxy.AdvancedProxy; import net.sf.cglib.proxy.InvocationHandler; @@ -257,6 +257,10 @@ public abstract class DomInvocationHandler info) { final FixedChildDescriptionImpl description = info.first; final EvaluatedXmlName evaluatedXmlName = createEvaluatedXmlName(description.getXmlName()); + if (myStub != null && description.isStubbed()) { + List stubs = myStub.getChildrenByName(description.getXmlName().getLocalName()); + DomStub stub = stubs.isEmpty() ? null : stubs.get(0); + DomParentStrategy strategy = stub == null ? new StubParentStrategy.Empty(myStub) : new StubParentStrategy(stub); + return new IndexedElementInvocationHandler(evaluatedXmlName, description, 0, strategy, myManager, (ElementStub)stub); + } final XmlTag tag = getXmlTag(); final int index = info.second; if (tag != null) { @@ -586,7 +596,7 @@ public abstract class DomInvocationHandler getCollectionChildren(final AbstractCollectionChildDescription description, final NotNullFunction> tagsGetter) { - if (myStub != null && description.getAnnotation(Stubbed.class) != null) { - XmlName xmlName = ((DomChildDescriptionImpl)description).getXmlName(); - List stubs = myStub.getChildrenByName(xmlName.getLocalName()); - return ContainerUtil.map(stubs, new Function() { - @Override - public DomElement fun(DomStub stub) { - return stub.getOrCreateHandler((DomChildDescriptionImpl)description, myManager).getProxy(); - } - }); + if (myStub != null && description.isStubbed()) { + if (description instanceof DomChildDescriptionImpl) { + XmlName xmlName = ((DomChildDescriptionImpl)description).getXmlName(); + List stubs = myStub.getChildrenByName(xmlName.getLocalName()); + return ContainerUtil.map(stubs, new Function() { + @Override + public DomElement fun(DomStub stub) { + return stub.getOrCreateHandler((DomChildDescriptionImpl)description, myManager).getProxy(); + } + }); + } + else if (description instanceof CustomDomChildrenDescriptionImpl) { + List stubs = myStub.getChildrenStubs(); + return ContainerUtil.mapNotNull(stubs, new NullableFunction() { + @Nullable + @Override + public DomElement fun(DomStub stub) { + if (stub instanceof ElementStub && ((ElementStub)stub).isCustom()) { + EvaluatedXmlName name = new DummyEvaluatedXmlName(stub.getName(), null); + return new CollectionElementInvocationHandler(name, (CustomDomChildrenDescriptionImpl)description, myManager, (ElementStub)stub).getProxy(); + } + return null; + } + }); + } } XmlTag tag = getXmlTag(); if (tag == null) return Collections.emptyList(); diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomParentStrategy.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomParentStrategy.java index c5f3f4ce5885..96d373a60761 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomParentStrategy.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomParentStrategy.java @@ -39,4 +39,6 @@ public interface DomParentStrategy { String checkValidity(); XmlFile getContainingFile(DomInvocationHandler handler); + + boolean isPhysical(); } diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java index 7ed28403a095..a95cbe56330a 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java @@ -73,16 +73,15 @@ public class DynamicGenericInfo extends DomGenericInfoEx { if (myInitialized) return true; myStaticGenericInfo.buildMethodMaps(); - final XmlElement element = myInvocationHandler.getXmlElement(); - if (element == null) return true; + if (!myInvocationHandler.exists()) return true; - return ourGuard.doPreventingRecursion(element, false, new Computable() { + return ourGuard.doPreventingRecursion(myInvocationHandler, false, new Computable() { @Override public Boolean compute() { DomExtensionsRegistrarImpl registrar = runDomExtenders(); //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (element) { + synchronized (myInvocationHandler) { if (!myInitialized) { if (registrar != null) { applyExtensions(registrar); diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/PhysicalDomParentStrategy.java b/xml/dom-impl/src/com/intellij/util/xml/impl/PhysicalDomParentStrategy.java index 3ad337ac54f6..f83280c85c98 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/PhysicalDomParentStrategy.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/PhysicalDomParentStrategy.java @@ -92,6 +92,11 @@ public class PhysicalDomParentStrategy implements DomParentStrategy { return DomImplUtil.getFile(handler); } + @Override + public boolean isPhysical() { + return true; + } + @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") public boolean equals(final Object o) { return strategyEquals(this, o); diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/RootDomParentStrategy.java b/xml/dom-impl/src/com/intellij/util/xml/impl/RootDomParentStrategy.java index f89412d95e98..10861c0d781c 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/RootDomParentStrategy.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/RootDomParentStrategy.java @@ -64,6 +64,11 @@ public class RootDomParentStrategy implements DomParentStrategy { return myFileElement.getFile(); } + @Override + public boolean isPhysical() { + return true; + } + public boolean equals(final Object o) { if (this == o) return true; if (!(o instanceof RootDomParentStrategy)) return false; diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/VirtualDomParentStrategy.java b/xml/dom-impl/src/com/intellij/util/xml/impl/VirtualDomParentStrategy.java index dfca9174bf8b..73da7d6197c3 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/VirtualDomParentStrategy.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/VirtualDomParentStrategy.java @@ -18,7 +18,6 @@ package com.intellij.util.xml.impl; import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; -import com.intellij.util.xml.DomUtil; import org.jetbrains.annotations.NotNull; /** @@ -87,6 +86,11 @@ public class VirtualDomParentStrategy implements DomParentStrategy { return DomImplUtil.getFile(handler); } + @Override + public boolean isPhysical() { + return false; + } + public boolean equals(final Object o) { if (this == o) return true; if (!(o instanceof VirtualDomParentStrategy)) return false; diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/DomStub.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/DomStub.java index df0cca02abf2..6277ee99e185 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/stubs/DomStub.java +++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/DomStub.java @@ -21,10 +21,8 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.StringRef; import com.intellij.util.xml.EvaluatedXmlNameImpl; import com.intellij.util.xml.XmlName; -import com.intellij.util.xml.impl.CollectionElementInvocationHandler; -import com.intellij.util.xml.impl.DomChildDescriptionImpl; -import com.intellij.util.xml.impl.DomInvocationHandler; -import com.intellij.util.xml.impl.DomManagerImpl; +import com.intellij.util.xml.impl.*; +import com.intellij.xml.util.XmlUtil; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -49,7 +47,7 @@ public abstract class DomStub extends ObjectStubBase { public abstract List getChildrenStubs(); public int getChildIndex(DomStub child) { - List stubs = getChildrenByName(child.getName()); + List stubs = getChildrenByName(XmlUtil.getLocalName(child.getName())); return stubs.indexOf(child); } @@ -57,11 +55,11 @@ public abstract class DomStub extends ObjectStubBase { return myName.getString(); } - public List getChildrenByName(final String localName) { + public List getChildrenByName(final CharSequence localName) { return ContainerUtil.filter(getChildrenStubs(), new Condition() { @Override public boolean value(DomStub stub) { - return stub.getName().equals(localName); + return stub instanceof ElementStub && XmlUtil.getLocalName(stub.getName()).equals(localName); } }); } diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStub.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStub.java index 0e7076b21cb4..b5e5bd33e1cc 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStub.java +++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStub.java @@ -29,9 +29,11 @@ import java.util.List; public class ElementStub extends DomStub { private final List myChildren = new SmartList(); + private final boolean myCustom; - public ElementStub(@Nullable ElementStub parent, StringRef name) { + public ElementStub(@Nullable ElementStub parent, StringRef name, boolean custom) { super(parent, name); + myCustom = custom; } void addChild(DomStub child) { @@ -58,4 +60,8 @@ public class ElementStub extends DomStub { if (obj == this) return true; return obj instanceof ElementStub && id == ((ElementStub)obj).id && myName.equals(((ElementStub)obj).myName); } + + public boolean isCustom() { + return myCustom; + } } diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStubSerializer.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStubSerializer.java index 0724dce4745c..1d6aceb63262 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStubSerializer.java +++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/ElementStubSerializer.java @@ -33,11 +33,12 @@ public class ElementStubSerializer implements ObjectStubSerializer children = DomUtil.getDefinedChildren(element, true, true); for (DomElement child : children) { visitDomElement(child); diff --git a/xml/dom-impl/src/com/intellij/xml/impl/dom/DomElementXmlDescriptor.java b/xml/dom-impl/src/com/intellij/xml/impl/dom/DomElementXmlDescriptor.java index c812d68807e7..018de44b522d 100644 --- a/xml/dom-impl/src/com/intellij/xml/impl/dom/DomElementXmlDescriptor.java +++ b/xml/dom-impl/src/com/intellij/xml/impl/dom/DomElementXmlDescriptor.java @@ -171,6 +171,11 @@ public class DomElementXmlDescriptor extends AbstractDomChildrenDescriptor { public DomElement getDomDeclaration() { return myDomElement; } + + @Override + public boolean isStubbed() { + return false; + } } } diff --git a/xml/dom-openapi/src/com/intellij/util/xml/DomElement.java b/xml/dom-openapi/src/com/intellij/util/xml/DomElement.java index 23229dffca9f..4e86444facb6 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/DomElement.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/DomElement.java @@ -15,16 +15,16 @@ */ package com.intellij.util.xml; -import com.intellij.psi.xml.XmlElement; -import com.intellij.psi.xml.XmlTag; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.xml.reflect.DomGenericInfo; -import com.intellij.util.xml.reflect.AbstractDomChildrenDescription; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.UserDataHolder; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.xml.XmlElement; +import com.intellij.psi.xml.XmlTag; +import com.intellij.util.xml.reflect.AbstractDomChildrenDescription; +import com.intellij.util.xml.reflect.DomGenericInfo; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.NonNls; import java.lang.reflect.Type; @@ -59,6 +59,11 @@ public interface DomElement extends AnnotatedElement, UserDataHolder { boolean isValid(); + /** + * @return true if corresponding XML element exists + */ + boolean exists(); + @NotNull DomGenericInfo getGenericInfo(); diff --git a/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.java b/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.java index 045e59b1f815..d536836f9387 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.java @@ -18,10 +18,7 @@ import com.intellij.util.ReflectionUtil; import com.intellij.util.SmartList; import com.intellij.util.containers.ConcurrentFactoryMap; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.xml.reflect.DomAttributeChildDescription; -import com.intellij.util.xml.reflect.DomCollectionChildDescription; -import com.intellij.util.xml.reflect.DomFixedChildDescription; -import com.intellij.util.xml.reflect.DomGenericInfo; +import com.intellij.util.xml.reflect.*; import com.intellij.xml.util.XmlTagUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -455,4 +452,19 @@ public class DomUtil { return Pair.create(startToken.getTextRange().shiftRight(-tag.getTextRange().getStartOffset()), (PsiElement)tag); } + + public static List getChildrenOf(DomElement parent, final Class type) { + final ArrayList list = new ArrayList(); + List descriptions = parent.getGenericInfo().getChildrenDescriptions(); + for (AbstractDomChildrenDescription description : descriptions) { + if (description.getType() instanceof Class && type.isAssignableFrom((Class)description.getType())) { + for (T value : (List)description.getValues(parent)) { + if (value.exists()) { + list.add(value); + } + } + } + } + return list; + } } diff --git a/xml/dom-openapi/src/com/intellij/util/xml/reflect/AbstractDomChildrenDescription.java b/xml/dom-openapi/src/com/intellij/util/xml/reflect/AbstractDomChildrenDescription.java index 3017480d30ae..cd68639bed7f 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/reflect/AbstractDomChildrenDescription.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/reflect/AbstractDomChildrenDescription.java @@ -56,4 +56,6 @@ public interface AbstractDomChildrenDescription extends AnnotatedElement, PomTar @Nullable DomElement getDomDeclaration(); + + boolean isStubbed(); } diff --git a/xml/dom-tests/tests/com/intellij/util/xml/MockDomElement.java b/xml/dom-tests/tests/com/intellij/util/xml/MockDomElement.java index 1c51ea0e4ed7..d861ead47908 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/MockDomElement.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/MockDomElement.java @@ -64,6 +64,11 @@ public class MockDomElement extends UserDataHolderBase implements DomElement{ throw new UnsupportedOperationException("Method isValid is not yet implemented in " + getClass().getName()); } + @Override + public boolean exists() { + throw new UnsupportedOperationException("Method exists is not yet implemented in " + getClass().getName()); + } + @Override @NotNull public DomGenericInfo getGenericInfo() { diff --git a/xml/dom-tests/tests/com/intellij/util/xml/MockDomFileElement.java b/xml/dom-tests/tests/com/intellij/util/xml/MockDomFileElement.java index c1319727a8e1..b2bbb5f30577 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/MockDomFileElement.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/MockDomFileElement.java @@ -106,6 +106,11 @@ public class MockDomFileElement extends UserDataHolderBase implements DomFileEle throw new UnsupportedOperationException("Method isValid is not yet implemented in " + getClass().getName()); } + @Override + public boolean exists() { + throw new UnsupportedOperationException("Method exists is not yet implemented in " + getClass().getName()); + } + @Override @NotNull public DomGenericInfo getGenericInfo() { diff --git a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.java b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.java index 3679a534520c..650d93bf6f45 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.java @@ -18,10 +18,14 @@ package com.intellij.util.xml.stubs; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.stubs.ObjectStubTree; import com.intellij.psi.stubs.StubTreeLoader; +import com.intellij.psi.xml.XmlFile; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomFileDescription; +import com.intellij.util.xml.DomFileElement; import com.intellij.util.xml.DomManager; import com.intellij.util.xml.impl.DomManagerImpl; import com.intellij.util.xml.stubs.model.Foo; @@ -67,4 +71,21 @@ public abstract class DomStubTest extends LightCodeInsightFixtureTestCase { ElementStub stub = getRootStub(file); assertEquals(stubText, DebugUtil.stubTreeToString(stub)); } + + protected DomFileElement prepare(String path, Class domClass) { + PsiFile file = myFixture.configureByFile(path); + assertFalse(file.getNode().isParsed()); + VirtualFile virtualFile = file.getVirtualFile(); + ObjectStubTree tree = StubTreeLoader.getInstance().readOrBuild(getProject(), virtualFile, file); + assertNotNull(tree); + + ((PsiManagerImpl)getPsiManager()).cleanupForNextTest(); + + file = getPsiManager().findFile(virtualFile); + assertFalse(file.getNode().isParsed()); + + DomFileElement fileElement = DomManager.getDomManager(getProject()).getFileElement((XmlFile)file, domClass); + assertNotNull(fileElement); + return fileElement; + } } diff --git a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java index 9b4f32c6bac4..21695bb6bf7c 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java @@ -15,18 +15,13 @@ */ package com.intellij.util.xml.stubs; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.PsiManagerImpl; -import com.intellij.psi.stubs.ObjectStubTree; -import com.intellij.psi.stubs.StubTreeLoader; import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomFileElement; -import com.intellij.util.xml.DomManager; +import com.intellij.util.xml.DomUtil; import com.intellij.util.xml.GenericAttributeValue; import com.intellij.util.xml.stubs.model.Bar; import com.intellij.util.xml.stubs.model.Foo; @@ -42,7 +37,7 @@ public class DomStubUsingTest extends DomStubTest { public void testFoo() throws Exception { - DomFileElement fileElement = prepare("foo.xml"); + DomFileElement fileElement = prepare("foo.xml", Foo.class); PsiFile file = fileElement.getFile(); assertFalse(file.getNode().isParsed()); @@ -71,7 +66,7 @@ public class DomStubUsingTest extends DomStubTest { } public void testAccessingPsi() throws Exception { - DomFileElement element = prepare("foo.xml"); + DomFileElement element = prepare("foo.xml", Foo.class); assertNotNull(element.getXmlElement()); XmlTag tag = element.getRootTag(); @@ -88,7 +83,7 @@ public class DomStubUsingTest extends DomStubTest { } public void testConverters() throws Exception { - DomFileElement element = prepare("converters.xml"); + DomFileElement element = prepare("converters.xml", Foo.class); Bar bar = element.getRootElement().getBars().get(0); PsiClass value = bar.getClazz().getValue(); assertNotNull(value); @@ -97,7 +92,7 @@ public class DomStubUsingTest extends DomStubTest { } public void testParent() throws Exception { - DomFileElement element = prepare("parent.xml"); + DomFileElement element = prepare("parent.xml", Foo.class); Bar bar = element.getRootElement().getBars().get(0); GenericAttributeValue notStubbed = bar.getNotStubbed(); @@ -111,20 +106,11 @@ public class DomStubUsingTest extends DomStubTest { assertEquals(bar, parent); } - private DomFileElement prepare(String path) { - PsiFile file = myFixture.configureByFile(path); - assertFalse(file.getNode().isParsed()); - VirtualFile virtualFile = file.getVirtualFile(); - ObjectStubTree tree = StubTreeLoader.getInstance().readOrBuild(getProject(), virtualFile, file); - assertNotNull(tree); + public void testChildrenOfType() throws Exception { - ((PsiManagerImpl)getPsiManager()).cleanupForNextTest(); - - file = getPsiManager().findFile(virtualFile); - assertFalse(file.getNode().isParsed()); - - DomFileElement fileElement = DomManager.getDomManager(getProject()).getFileElement((XmlFile)file, Foo.class); - assertNotNull(fileElement); - return fileElement; + DomFileElement element = prepare("foo.xml", Foo.class); + Foo foo = element.getRootElement(); + List bars = DomUtil.getChildrenOf(foo, Bar.class); + assertEquals(2, bars.size()); } } diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilderDriver.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilderDriver.java index f1db1be33cbd..0518f9d80929 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilderDriver.java +++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/XmlBuilderDriver.java @@ -178,7 +178,7 @@ public class XmlBuilderDriver { } } - CharSequence localName = getLocalName(tagName); + CharSequence localName = XmlUtil.getLocalName(tagName); String namespace = getNamespace(tagName); XmlBuilder.ProcessingOrder order = builder.startTag(localName, namespace, node.getStartOffset(), node.getEndOffset(), headerEndOffset); @@ -263,14 +263,6 @@ public class XmlBuilderDriver { return ""; } - private static CharSequence getLocalName(final CharSequence tagName) { - int pos = StringUtil.indexOf(tagName, ':'); - if (pos == -1) { - return tagName; - } - return tagName.subSequence(pos + 1, tagName.length()); - } - private void checkForXmlns(LighterASTNode attrNode, FlyweightCapableTreeStructure structure) { final CharSequence name = getAttributeName(attrNode, structure); if (Comparing.equal(name, XMLNS)) { diff --git a/xml/impl/src/com/intellij/xml/util/XmlUtil.java b/xml/impl/src/com/intellij/xml/util/XmlUtil.java index da1dc8b5fd32..e683f22d7a38 100644 --- a/xml/impl/src/com/intellij/xml/util/XmlUtil.java +++ b/xml/impl/src/com/intellij/xml/util/XmlUtil.java @@ -596,6 +596,14 @@ public class XmlUtil { : doctype; } + public static CharSequence getLocalName(final CharSequence tagName) { + int pos = StringUtil.indexOf(tagName, ':'); + if (pos == -1) { + return tagName; + } + return tagName.subSequence(pos + 1, tagName.length()); + } + private static class XmlElementProcessor { private final PsiElementProcessor processor; private final PsiFile targetFile;