mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DOM stubs for custom elements
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Boolean> myStubbed = new NotNullLazyValue<Boolean>() {
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public abstract class DomAnchorImpl<T extends DomElement> implements DomAnchor<T
|
||||
public static <T extends DomElement> DomAnchorImpl<T> createAnchor(@NotNull T t) {
|
||||
return createAnchor(t, false);
|
||||
}
|
||||
|
||||
public static <T extends DomElement> DomAnchorImpl<T> createAnchor(@NotNull T t, boolean usePsi) {
|
||||
if (usePsi) {
|
||||
final XmlElement element = t.getXmlElement();
|
||||
@@ -345,4 +346,36 @@ public abstract class DomAnchorImpl<T extends DomElement> implements DomAnchor<T
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class StubAnchor<T extends DomElement> implements DomAnchor<T> {
|
||||
|
||||
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 <T extends DomElement> DomAnchor<T> createStubAnchor(T element) {
|
||||
DomInvocationHandler handler = DomManagerImpl.getDomInvocationHandler(element);
|
||||
return handler.getStub() == null ? createAnchor(element, true) : new StubAnchor<T>(handler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +332,11 @@ public class DomFileElementImpl<T extends DomElement> implements DomFileElement<
|
||||
return checkValidity() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String checkValidity() {
|
||||
if (!myFile.isValid()) {
|
||||
|
||||
@@ -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<T extends AbstractDomChildDescription
|
||||
return getParentStrategy().getXmlElement();
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return getParentStrategy().isPhysical();
|
||||
}
|
||||
|
||||
private DomParentStrategy getParentStrategy() {
|
||||
myParentStrategy = myParentStrategy.refreshStrategy(this);
|
||||
return myParentStrategy;
|
||||
@@ -554,6 +558,12 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
|
||||
final IndexedElementInvocationHandler getFixedChild(final Pair<FixedChildDescriptionImpl, Integer> info) {
|
||||
final FixedChildDescriptionImpl description = info.first;
|
||||
final EvaluatedXmlName evaluatedXmlName = createEvaluatedXmlName(description.getXmlName());
|
||||
if (myStub != null && description.isStubbed()) {
|
||||
List<DomStub> 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<T extends AbstractDomChildDescription
|
||||
@NotNull
|
||||
final AttributeChildInvocationHandler getAttributeChild(final AttributeChildDescriptionImpl description) {
|
||||
final EvaluatedXmlName evaluatedXmlName = createEvaluatedXmlName(description.getXmlName());
|
||||
if (myStub != null && description.getAnnotation(Stubbed.class) != null) {
|
||||
if (myStub != null && description.isStubbed()) {
|
||||
AttributeStub stub = myStub.getAttributeStub(description.getXmlName());
|
||||
StubParentStrategy strategy = StubParentStrategy.createAttributeStrategy(stub, myStub);
|
||||
return new AttributeChildInvocationHandler(evaluatedXmlName, description, myManager, strategy, stub);
|
||||
@@ -758,15 +768,31 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
|
||||
}
|
||||
|
||||
public List<? extends DomElement> getCollectionChildren(final AbstractCollectionChildDescription description, final NotNullFunction<DomInvocationHandler, List<XmlTag>> tagsGetter) {
|
||||
if (myStub != null && description.getAnnotation(Stubbed.class) != null) {
|
||||
XmlName xmlName = ((DomChildDescriptionImpl)description).getXmlName();
|
||||
List<DomStub> stubs = myStub.getChildrenByName(xmlName.getLocalName());
|
||||
return ContainerUtil.map(stubs, new Function<DomStub, DomElement>() {
|
||||
@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<DomStub> stubs = myStub.getChildrenByName(xmlName.getLocalName());
|
||||
return ContainerUtil.map(stubs, new Function<DomStub, DomElement>() {
|
||||
@Override
|
||||
public DomElement fun(DomStub stub) {
|
||||
return stub.getOrCreateHandler((DomChildDescriptionImpl)description, myManager).getProxy();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (description instanceof CustomDomChildrenDescriptionImpl) {
|
||||
List<DomStub> stubs = myStub.getChildrenStubs();
|
||||
return ContainerUtil.mapNotNull(stubs, new NullableFunction<DomStub, DomElement>() {
|
||||
@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();
|
||||
|
||||
@@ -39,4 +39,6 @@ public interface DomParentStrategy {
|
||||
String checkValidity();
|
||||
|
||||
XmlFile getContainingFile(DomInvocationHandler handler);
|
||||
|
||||
boolean isPhysical();
|
||||
}
|
||||
|
||||
@@ -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<Boolean>() {
|
||||
return ourGuard.doPreventingRecursion(myInvocationHandler, false, new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
DomExtensionsRegistrarImpl registrar = runDomExtenders();
|
||||
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (element) {
|
||||
synchronized (myInvocationHandler) {
|
||||
if (!myInitialized) {
|
||||
if (registrar != null) {
|
||||
applyExtensions(registrar);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<DomStub> {
|
||||
public abstract List<DomStub> getChildrenStubs();
|
||||
|
||||
public int getChildIndex(DomStub child) {
|
||||
List<DomStub> stubs = getChildrenByName(child.getName());
|
||||
List<DomStub> stubs = getChildrenByName(XmlUtil.getLocalName(child.getName()));
|
||||
return stubs.indexOf(child);
|
||||
}
|
||||
|
||||
@@ -57,11 +55,11 @@ public abstract class DomStub extends ObjectStubBase<DomStub> {
|
||||
return myName.getString();
|
||||
}
|
||||
|
||||
public List<DomStub> getChildrenByName(final String localName) {
|
||||
public List<DomStub> getChildrenByName(final CharSequence localName) {
|
||||
return ContainerUtil.filter(getChildrenStubs(), new Condition<DomStub>() {
|
||||
@Override
|
||||
public boolean value(DomStub stub) {
|
||||
return stub.getName().equals(localName);
|
||||
return stub instanceof ElementStub && XmlUtil.getLocalName(stub.getName()).equals(localName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,9 +29,11 @@ import java.util.List;
|
||||
public class ElementStub extends DomStub {
|
||||
|
||||
private final List<DomStub> myChildren = new SmartList<DomStub>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,11 +33,12 @@ public class ElementStubSerializer implements ObjectStubSerializer<ElementStub,
|
||||
@Override
|
||||
public void serialize(ElementStub stub, StubOutputStream dataStream) throws IOException {
|
||||
dataStream.writeName(stub.getName());
|
||||
dataStream.writeBoolean(stub.isCustom());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementStub deserialize(StubInputStream dataStream, ElementStub parentStub) throws IOException {
|
||||
return new ElementStub(parentStub, dataStream.readName());
|
||||
return new ElementStub(parentStub, dataStream.readName(), dataStream.readBoolean());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,7 +32,7 @@ public class FileStub extends ElementStub {
|
||||
private final XmlFileHeader myHeader;
|
||||
|
||||
public FileStub(StringRef tagName, StringRef tagNamespace, StringRef publicId, StringRef systemId) {
|
||||
super(null, tagName);
|
||||
super(null, tagName, false);
|
||||
myHeader = new XmlFileHeader(tagName == null ? null : tagName.getString(),
|
||||
tagNamespace == null ? null : tagNamespace.getString(),
|
||||
publicId == null ? null : publicId.getString(),
|
||||
@@ -40,7 +40,7 @@ public class FileStub extends ElementStub {
|
||||
}
|
||||
|
||||
public FileStub(XmlFileHeader header) {
|
||||
super(null, StringRef.fromString(header.getRootTagLocalName()));
|
||||
super(null, StringRef.fromString(header.getRootTagLocalName()), false);
|
||||
myHeader = header;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,17 +30,7 @@ public class StubParentStrategy implements DomParentStrategy {
|
||||
|
||||
public static StubParentStrategy createAttributeStrategy(@Nullable AttributeStub stub, @NotNull final DomStub parent) {
|
||||
if (stub == null) {
|
||||
return new StubParentStrategy(parent) {
|
||||
@Override
|
||||
public DomInvocationHandler getParentHandler() {
|
||||
return parent.getHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlElement getXmlElement() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return new Empty(parent);
|
||||
}
|
||||
else {
|
||||
return new StubParentStrategy(stub) {
|
||||
@@ -59,7 +49,7 @@ public class StubParentStrategy implements DomParentStrategy {
|
||||
|
||||
protected final DomStub myStub;
|
||||
|
||||
public StubParentStrategy(DomStub stub) {
|
||||
public StubParentStrategy(@NotNull DomStub stub) {
|
||||
myStub = stub;
|
||||
}
|
||||
|
||||
@@ -112,9 +102,38 @@ public class StubParentStrategy implements DomParentStrategy {
|
||||
return getParentHandler().getFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysical() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return PhysicalDomParentStrategy.strategyEquals(this, obj);
|
||||
}
|
||||
|
||||
public static class Empty extends StubParentStrategy {
|
||||
private final DomStub myParent;
|
||||
|
||||
public Empty(DomStub parent) {
|
||||
super(parent);
|
||||
myParent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomInvocationHandler getParentHandler() {
|
||||
return myParent.getHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlElement getXmlElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysical() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class DomStubBuilder implements BinaryFileStubBuilder {
|
||||
|
||||
@Override
|
||||
public int getStubVersion() {
|
||||
int version = 3;
|
||||
int version = 6;
|
||||
DomFileDescription[] descriptions = Extensions.getExtensions(DomFileDescription.EP_NAME);
|
||||
for (DomFileDescription description : descriptions) {
|
||||
version += description.getStubVersion();
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.util.io.StringRef;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import com.intellij.util.xml.DomElementVisitor;
|
||||
import com.intellij.util.xml.DomUtil;
|
||||
import com.intellij.util.xml.reflect.CustomDomChildrenDescription;
|
||||
import com.intellij.util.xml.stubs.AttributeStub;
|
||||
import com.intellij.util.xml.stubs.ElementStub;
|
||||
import com.intellij.util.xml.stubs.FileStub;
|
||||
@@ -46,12 +47,13 @@ public class DomStubBuilderVisitor implements DomElementVisitor {
|
||||
public void visitDomElement(DomElement element) {
|
||||
|
||||
if (element.getAnnotation(Stubbed.class) != null ||
|
||||
element.getChildDescription().getAnnotation(Stubbed.class) != null) {
|
||||
element.getChildDescription().isStubbed()) {
|
||||
|
||||
XmlElement xmlElement = element.getXmlElement();
|
||||
if (xmlElement instanceof XmlTag) {
|
||||
ElementStub old = myRoot;
|
||||
myRoot = new ElementStub(myRoot, StringRef.fromString(((PsiNamedElement)xmlElement).getName()));
|
||||
boolean custom = element.getChildDescription() instanceof CustomDomChildrenDescription;
|
||||
myRoot = new ElementStub(myRoot, StringRef.fromString(((PsiNamedElement)xmlElement).getName()), custom);
|
||||
List<DomElement> children = DomUtil.getDefinedChildren(element, true, true);
|
||||
for (DomElement child : children) {
|
||||
visitDomElement(child);
|
||||
|
||||
@@ -171,6 +171,11 @@ public class DomElementXmlDescriptor extends AbstractDomChildrenDescriptor {
|
||||
public DomElement getDomDeclaration() {
|
||||
return myDomElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStubbed() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 <T extends DomElement> List<T> getChildrenOf(DomElement parent, final Class<T> type) {
|
||||
final ArrayList<T> list = new ArrayList<T>();
|
||||
List<? extends AbstractDomChildrenDescription> descriptions = parent.getGenericInfo().getChildrenDescriptions();
|
||||
for (AbstractDomChildrenDescription description : descriptions) {
|
||||
if (description.getType() instanceof Class && type.isAssignableFrom((Class<?>)description.getType())) {
|
||||
for (T value : (List<T>)description.getValues(parent)) {
|
||||
if (value.exists()) {
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,4 +56,6 @@ public interface AbstractDomChildrenDescription extends AnnotatedElement, PomTar
|
||||
|
||||
@Nullable
|
||||
DomElement getDomDeclaration();
|
||||
|
||||
boolean isStubbed();
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 <T extends DomElement> DomFileElement<T> prepare(String path, Class<T> 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<T> fileElement = DomManager.getDomManager(getProject()).getFileElement((XmlFile)file, domClass);
|
||||
assertNotNull(fileElement);
|
||||
return fileElement;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Foo> fileElement = prepare("foo.xml");
|
||||
DomFileElement<Foo> 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<Foo> element = prepare("foo.xml");
|
||||
DomFileElement<Foo> 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<Foo> element = prepare("converters.xml");
|
||||
DomFileElement<Foo> 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<Foo> element = prepare("parent.xml");
|
||||
DomFileElement<Foo> element = prepare("parent.xml", Foo.class);
|
||||
|
||||
Bar bar = element.getRootElement().getBars().get(0);
|
||||
GenericAttributeValue<Integer> notStubbed = bar.getNotStubbed();
|
||||
@@ -111,20 +106,11 @@ public class DomStubUsingTest extends DomStubTest {
|
||||
assertEquals(bar, parent);
|
||||
}
|
||||
|
||||
private DomFileElement<Foo> 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<Foo> fileElement = DomManager.getDomManager(getProject()).getFileElement((XmlFile)file, Foo.class);
|
||||
assertNotNull(fileElement);
|
||||
return fileElement;
|
||||
DomFileElement<Foo> element = prepare("foo.xml", Foo.class);
|
||||
Foo foo = element.getRootElement();
|
||||
List<Bar> bars = DomUtil.getChildrenOf(foo, Bar.class);
|
||||
assertEquals(2, bars.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LighterASTNode> structure) {
|
||||
final CharSequence name = getAttributeName(attrNode, structure);
|
||||
if (Comparing.equal(name, XMLNS)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user