mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DOM stubs: accessing attribute values
This commit is contained in:
@@ -129,6 +129,9 @@ public class AttributeChildInvocationHandler extends DomInvocationHandler<Attrib
|
||||
|
||||
@Nullable
|
||||
protected String getValue() {
|
||||
if (myStub != null) {
|
||||
return myStub.getValue();
|
||||
}
|
||||
final XmlAttribute attribute = (XmlAttribute)getXmlElement();
|
||||
if (attribute != null) {
|
||||
final XmlAttributeValue value = attribute.getValueElement();
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
@@ -21,10 +22,13 @@ import com.intellij.semantic.SemElement;
|
||||
import com.intellij.semantic.SemKey;
|
||||
import com.intellij.semantic.SemService;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xml.*;
|
||||
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.StubParentStrategy;
|
||||
import net.sf.cglib.proxy.AdvancedProxy;
|
||||
import net.sf.cglib.proxy.InvocationHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -62,10 +66,10 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
|
||||
private final InvocationCache myInvocationCache;
|
||||
private volatile Converter myScalarConverter = null;
|
||||
private volatile SmartFMap<Method, Invocation> myAccessorInvocations = SmartFMap.emptyMap();
|
||||
@Nullable private final Stub myStub;
|
||||
@Nullable protected final Stub myStub;
|
||||
|
||||
protected DomInvocationHandler(Type type, DomParentStrategy parentStrategy,
|
||||
final EvaluatedXmlName tagName,
|
||||
@NotNull final EvaluatedXmlName tagName,
|
||||
final T childDescription,
|
||||
final DomManagerImpl manager,
|
||||
boolean dynamic,
|
||||
@@ -576,6 +580,12 @@ 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) {
|
||||
AttributeStub stub = myStub.getAttributeStub(description.getXmlName());
|
||||
if (stub != null) {
|
||||
return new AttributeChildInvocationHandler(evaluatedXmlName, description, myManager, new StubParentStrategy(stub), stub);
|
||||
}
|
||||
}
|
||||
final XmlTag tag = getXmlTag();
|
||||
|
||||
if (tag != null) {
|
||||
@@ -743,6 +753,16 @@ 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);
|
||||
return ContainerUtil.map(stubs, new Function<DomStub, DomElement>() {
|
||||
@Override
|
||||
public DomElement fun(DomStub stub) {
|
||||
return stub.getOrCreateHandler((DomChildDescriptionImpl)description, myManager).getProxy();
|
||||
}
|
||||
});
|
||||
}
|
||||
XmlTag tag = getXmlTag();
|
||||
if (tag == null) return Collections.emptyList();
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ public class DomRootInvocationHandler extends DomInvocationHandler<AbstractDomCh
|
||||
}
|
||||
}, fileElement.getManager(), true, stub);
|
||||
myParent = fileElement;
|
||||
if (stub != null) {
|
||||
stub.setHandler(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void undefineInternal() {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.util.xml.stubs;
|
||||
|
||||
import com.intellij.psi.stubs.ObjectStubSerializer;
|
||||
import com.intellij.psi.stubs.Stub;
|
||||
import com.intellij.util.io.StringRef;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -40,7 +39,7 @@ public class AttributeStub extends DomStub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Stub> getChildrenStubs() {
|
||||
public List<DomStub> getChildrenStubs() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,19 @@
|
||||
*/
|
||||
package com.intellij.util.xml.stubs;
|
||||
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.stubs.ObjectStubBase;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
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.DomChildDescriptionImpl;
|
||||
import com.intellij.util.xml.impl.DomInvocationHandler;
|
||||
import com.intellij.util.xml.impl.DomManagerImpl;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
@@ -25,6 +36,7 @@ import com.intellij.util.io.StringRef;
|
||||
public abstract class DomStub extends ObjectStubBase<DomStub> {
|
||||
|
||||
protected final StringRef myName;
|
||||
private DomInvocationHandler myHandler;
|
||||
|
||||
public DomStub(DomStub parent, StringRef name) {
|
||||
super(parent);
|
||||
@@ -34,7 +46,54 @@ public abstract class DomStub extends ObjectStubBase<DomStub> {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
public abstract List<DomStub> getChildrenStubs();
|
||||
|
||||
public String getName() {
|
||||
return myName.getString();
|
||||
}
|
||||
|
||||
public List<DomStub> getChildrenByName(final XmlName name) {
|
||||
return ContainerUtil.filter(getChildrenStubs(), new Condition<DomStub>() {
|
||||
@Override
|
||||
public boolean value(DomStub stub) {
|
||||
return stub.getName().equals(name.getLocalName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AttributeStub getAttributeStub(final XmlName name) {
|
||||
return (AttributeStub)ContainerUtil.find(getChildrenStubs(), new Condition<DomStub>() {
|
||||
@Override
|
||||
public boolean value(DomStub o) {
|
||||
return o instanceof AttributeStub && o.getName().equals(name.getLocalName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized DomInvocationHandler getOrCreateHandler(DomChildDescriptionImpl description, DomManagerImpl manager) {
|
||||
if (myHandler == null) {
|
||||
XmlName name = description.getXmlName();
|
||||
EvaluatedXmlNameImpl evaluatedXmlName = EvaluatedXmlNameImpl.createEvaluatedXmlName(name, name.getNamespaceKey(), true);
|
||||
myHandler = new DomInvocationHandler(description.getType(), new StubParentStrategy(this), evaluatedXmlName, description, manager, false, this) {
|
||||
@Override
|
||||
protected void undefineInternal() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XmlTag setEmptyXmlTag() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
return myHandler;
|
||||
}
|
||||
|
||||
public DomInvocationHandler getHandler() {
|
||||
return myHandler;
|
||||
}
|
||||
|
||||
public void setHandler(DomInvocationHandler handler) {
|
||||
myHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.util.xml.stubs;
|
||||
|
||||
import com.intellij.psi.stubs.ObjectStubSerializer;
|
||||
import com.intellij.psi.stubs.Stub;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -40,7 +39,7 @@ public class ElementStub extends DomStub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Stub> getChildrenStubs() {
|
||||
public List<DomStub> getChildrenStubs() {
|
||||
return myChildren;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.xml.stubs;
|
||||
|
||||
import com.intellij.psi.xml.XmlElement;
|
||||
import com.intellij.util.xml.impl.DomInvocationHandler;
|
||||
import com.intellij.util.xml.impl.DomParentStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 8/9/12
|
||||
*/
|
||||
public class StubParentStrategy implements DomParentStrategy {
|
||||
|
||||
private final DomStub myStub;
|
||||
|
||||
public StubParentStrategy(DomStub stub) {
|
||||
myStub = stub;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomInvocationHandler getParentHandler() {
|
||||
DomStub parentStub = myStub.getParentStub();
|
||||
return parentStub == null ? null : parentStub.getHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlElement getXmlElement() {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DomParentStrategy refreshStrategy(DomInvocationHandler handler) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DomParentStrategy setXmlElement(@NotNull XmlElement element) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DomParentStrategy clearXmlElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String checkValidity() {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
@@ -81,14 +81,14 @@ public class EvaluatedXmlNameImpl implements EvaluatedXmlName {
|
||||
|
||||
if (myEqualToParent != that.myEqualToParent) return false;
|
||||
if (myNamespaceKey != null ? !myNamespaceKey.equals(that.myNamespaceKey) : that.myNamespaceKey != null) return false;
|
||||
if (myXmlName != null ? !myXmlName.equals(that.myXmlName) : that.myXmlName != null) return false;
|
||||
if (!myXmlName.equals(that.myXmlName)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myXmlName != null ? myXmlName.hashCode() : 0;
|
||||
int result = myXmlName.hashCode();
|
||||
result = 31 * result + (myNamespaceKey != null ? myNamespaceKey.hashCode() : 0);
|
||||
result = 31 * result + (myEqualToParent ? 1 : 0);
|
||||
return result;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<foo>
|
||||
<bar attribute="xxx"></bar>
|
||||
<bar string="xxx" int="666"></bar>
|
||||
<bar></bar>
|
||||
</foo>
|
||||
@@ -26,5 +26,8 @@ import com.intellij.util.xml.GenericAttributeValue;
|
||||
public interface Bar extends DomElement {
|
||||
|
||||
@Stubbed
|
||||
GenericAttributeValue getAttribute();
|
||||
GenericAttributeValue<String> getString();
|
||||
|
||||
@Stubbed
|
||||
GenericAttributeValue<Integer> getInt();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ public class DomStubBuilderTest extends DomStubTest {
|
||||
doTest("foo.xml", "File:foo\n" +
|
||||
" Element:foo\n" +
|
||||
" Element:bar\n" +
|
||||
" Attribute:attribute:xxx\n" +
|
||||
" Attribute:int:666\n" +
|
||||
" Attribute:string:xxx\n" +
|
||||
" Element:bar\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,17 @@
|
||||
*/
|
||||
package com.intellij.util.xml.stubs;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
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.XmlFile;
|
||||
import com.intellij.util.xml.DomFileElement;
|
||||
import com.intellij.util.xml.DomManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 8/8/12
|
||||
@@ -27,9 +33,44 @@ import com.intellij.util.xml.DomManager;
|
||||
public class DomStubUsingTest extends DomStubTest {
|
||||
|
||||
public void testFoo() throws Exception {
|
||||
PsiFile file = myFixture.configureByFile("foo.xml");
|
||||
|
||||
DomFileElement<Foo> fileElement = prepare("foo.xml");
|
||||
PsiFile file;
|
||||
|
||||
file = fileElement.getFile();
|
||||
assertFalse(file.getNode().isParsed());
|
||||
|
||||
Foo foo = fileElement.getRootElement();
|
||||
List<Bar> bars = foo.getBars();
|
||||
assertFalse(file.getNode().isParsed());
|
||||
|
||||
assertEquals(2, bars.size());
|
||||
Bar bar = bars.get(0);
|
||||
String value = bar.getString().getStringValue();
|
||||
assertEquals("xxx", value);
|
||||
|
||||
Object o = bar.getString().getValue();
|
||||
assertEquals("xxx", o);
|
||||
|
||||
Integer integer = bar.getInt().getValue();
|
||||
assertEquals(666, integer.intValue());
|
||||
|
||||
assertFalse(file.getNode().isParsed());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
((PsiManagerImpl)getPsiManager()).cleanupForNextTest();
|
||||
file = getPsiManager().findFile(virtualFile);
|
||||
assertFalse(file.getNode().isParsed());
|
||||
|
||||
DomFileElement<Foo> fileElement = DomManager.getDomManager(getProject()).getFileElement((XmlFile)file, Foo.class);
|
||||
assertNotNull(fileElement);
|
||||
Foo foo = fileElement.getRootElement();
|
||||
return fileElement;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user