dom-tests moved to community

This commit is contained in:
Dmitry Avdeev
2012-08-06 17:14:55 +04:00
parent 98e3b5c30a
commit b9b616eb90
34 changed files with 6678 additions and 0 deletions
+1
View File
@@ -36,6 +36,7 @@
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/jps-plugin/devkit-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/devkit/jps-plugin/devkit-jps-plugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" filepath="$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" group="xml" />
<module fileurl="file://$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" filepath="$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" group="xml" />
<module fileurl="file://$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" filepath="$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" group="xml" />
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/eclipse.iml" filepath="$PROJECT_DIR$/plugins/eclipse/eclipse.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/java/execution/impl/execution-impl.iml" filepath="$PROJECT_DIR$/java/execution/impl/execution-impl.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/execution/openapi/execution-openapi.iml" filepath="$PROJECT_DIR$/java/execution/openapi/execution-openapi.iml" group="java" />
+1
View File
@@ -91,6 +91,7 @@
<orderEntry type="module" module-name="gradle" />
<orderEntry type="module" module-name="rearranger" />
<orderEntry type="module" module-name="xml-tests" scope="TEST" />
<orderEntry type="module" module-name="dom-tests" />
</component>
</module>
+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="dom-impl" />
<orderEntry type="library" name="CGLIB" level="project" />
<orderEntry type="module" module-name="xml" />
<orderEntry type="module" module-name="testFramework-java" />
<orderEntry type="module" module-name="java-psi-impl" />
<orderEntry type="module" module-name="java-impl" scope="TEST" />
</component>
<component name="copyright">
<Base>
<setting name="state" value="1" />
</Base>
</component>
</module>
+1
View File
@@ -0,0 +1 @@
<foo/>
@@ -0,0 +1,29 @@
package com.intellij.util.xml;
import com.intellij.util.xml.converters.DelimitedListProcessor;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Dmitry Avdeev
*/
public class DelimitedListProcessorTest extends TestCase {
public void testProcessor() {
doTest("a; ; ", Arrays.asList("a", " ", " "));
}
private void doTest(final String text, final List<String> expected) {
final ArrayList<String> tokens = new ArrayList<String>();
new DelimitedListProcessor(";") {
@Override
protected void processToken(final int start, final int end, final boolean delimitersOnly) {
tokens.add(text.substring(start, end));
}
}.processText(text);
assertEquals(expected, tokens);
}
}
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.highlighting.*;
import java.util.Arrays;
/**
* @author peter
*/
public class DomAnnotationsTest extends DomTestCase{
@Override
protected <T extends DomElement> T createElement(final String xml, final Class<T> aClass) {
final String name = "a.xml";
final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText(name, StdFileTypes.XML, xml, 0,
true);
final XmlTag tag = file.getDocument().getRootTag();
final String rootTagName = tag != null ? tag.getName() : "root";
final T element = getDomManager().getFileElement(file, aClass, rootTagName).getRootElement();
assertNotNull(element);
assertSame(tag, element.getXmlTag());
return element;
}
public void testResolveProblemsAreReportedOnlyOnce() throws Throwable {
final MyElement myElement = createElement("<a><my-class>abc</my-class></a>", MyElement.class);
new MockDomInspection(MyElement.class).checkFile(DomUtil.getFile(myElement), InspectionManager.getInstance(getProject()), true);
final DomElementsProblemsHolder holder = DomElementAnnotationsManager.getInstance(getProject()).getProblemHolder(myElement);
final DomElement element = myElement.getMyClass();
assertEquals(0, holder.getProblems(myElement).size());
assertEquals(0, holder.getProblems(myElement).size());
assertEquals(1, holder.getProblems(element).size());
assertEquals(1, holder.getProblems(element).size());
assertEquals(1, holder.getProblems(myElement, true, true).size());
assertEquals(1, holder.getProblems(myElement, true, true).size());
}
public void testMinSeverity() throws Throwable {
final MyElement element = createElement("<a/>", MyElement.class);
final DomElementsProblemsHolderImpl holder = new DomElementsProblemsHolderImpl(DomUtil.getFileElement(element));
final DomElementProblemDescriptorImpl error = new DomElementProblemDescriptorImpl(element, "abc", HighlightSeverity.ERROR);
final DomElementProblemDescriptorImpl warning = new DomElementProblemDescriptorImpl(element, "abc", HighlightSeverity.WARNING);
holder.addProblem(error, MockDomInspection.class);
holder.addProblem(warning, MockDomInspection.class);
assertEquals(Arrays.asList(error), holder.getProblems(element, true, true, HighlightSeverity.ERROR));
assertEquals(Arrays.asList(error, warning), holder.getProblems(element, true, true, HighlightSeverity.WARNING));
}
public interface MyElement extends DomElement{
GenericDomValue<PsiClass> getMyClass();
}
}
@@ -0,0 +1,606 @@
package com.intellij.util.xml;
import com.intellij.mock.MockModule;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.events.DomEvent;
import com.intellij.util.xml.impl.*;
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 java.lang.reflect.ParameterizedType;
import java.util.*;
/**
* @author peter
*/
public class DomBasicsTest extends DomTestCase {
@Override
protected void invokeTestRunnable(final Runnable runnable) throws Exception {
new WriteCommandAction.Simple(null) {
@Override
protected void run() throws Throwable {
runnable.run();
}
}.execute().throwException();
}
public void testFileElementCaching() throws Throwable {
final XmlFile file = createXmlFile("<a/>");
final DomManagerImpl manager = getDomManager();
final DomFileElementImpl<DomElement> fileElement = manager.getFileElement(file, DomElement.class, "a");
assertEquals(fileElement, manager.getFileElement(file, DomElement.class, "a"));
assertCached(fileElement, file);
assertEquals(fileElement.getRootElement(), fileElement.getRootElement());
}
public void testElementCaching() throws Throwable {
final MyElement element = createElement("<a><child/></a>");
assertSame(element.getChild(), element.getChild());
assertSame(element.getXmlTag().getSubTags()[0], element.getChild().getXmlTag());
assertCached(element.getChild(), element.getChild().getXmlTag());
}
public void testGetParentAndRoot() throws Throwable {
final XmlFile file = createXmlFile("<a><foo/><child-element/><child-element/></a>");
final DomFileElementImpl<MyElement> fileElement = getDomManager().getFileElement(file, MyElement.class, "a");
assertNull(fileElement.getParent());
assertSame(fileElement, DomUtil.getFileElement(fileElement));
final MyElement rootElement = fileElement.getRootElement();
assertSame(fileElement, rootElement.getParent());
assertSame(fileElement, DomUtil.getFileElement(rootElement));
assertParent(rootElement.getFoo(), rootElement);
assertParent(rootElement.getChildElements().get(0), rootElement);
assertParent(rootElement.getChildElements().get(1), rootElement);
}
private static void assertParent(final DomElement element, final DomElement parent) {
assertEquals(parent, element.getParent());
}
public void testEnsureTagExists() throws Throwable {
final MyElement element = createElement("<a/>");
myCallRegistry.clear();
final MyElement child = element.getChild();
assertNull(child.getXmlTag());
child.ensureTagExists();
final XmlTag[] subTags = element.getXmlTag().getSubTags();
assertEquals(1, subTags.length);
final XmlTag childTag = subTags[0];
assertEquals("child", childTag.getName());
assertCached(child, childTag);
assertSame(child.getXmlTag(), childTag);
final DomElement element1 = child;
myCallRegistry.putExpected(new DomEvent(element1, true));
myCallRegistry.assertResultsAndClear();
final MyElement childElement = element.addChildElement();
final XmlTag childElementTag = childElement.getXmlTag();
assertSame(childElementTag, childElement.ensureTagExists());
}
public void testEnsureRootTagExists() throws Throwable {
final MyElement rootElement = createEmptyElement();
myCallRegistry.clear();
assertNull(rootElement.getXmlTag());
rootElement.ensureTagExists();
final DomElement element = rootElement;
myCallRegistry.putExpected(new DomEvent(element, true));
assertCached(rootElement, assertRootTag(rootElement));
myCallRegistry.assertResultsAndClear();
}
private XmlTag assertRootTag(final DomElement rootElement) {
return assertRootTag(DomUtil.getFile(rootElement));
}
private static XmlTag assertRootTag(final XmlFile file) {
final XmlTag rootTag = file.getDocument().getRootTag();
assertNotNull(rootTag);
assertEquals("root", rootTag.getName());
return rootTag;
}
protected MyElement createEmptyElement() throws IncorrectOperationException {
final XmlFile file = createXmlFile("");
return getDomManager().getFileElement(file, MyElement.class, "root").getRootElement();
}
public void testFile() throws Throwable {
final XmlFile file = createXmlFile("<a>foo</a>");
DomFileElementImpl<MyElement> fileElement = getDomManager().getFileElement(file, MyElement.class, "a");
final MyElement rootElement = fileElement.getRootElement();
assertNotNull(rootElement);
assertEquals("foo", rootElement.getValue());
}
public void testAcceptChidren() throws Throwable {
final MyElement element = createElement("<a><child-element/><child/><child-element/></a>");
final Set<DomElement> visited = new HashSet<DomElement>();
element.acceptChildren(new DomElementVisitor() {
@Override
public void visitDomElement(DomElement element) {
visited.add(element);
}
});
final MyElement foo = element.getFoo();
final MyElement child = element.getChild();
final MyElement child1 = element.getChildElements().get(0);
final MyElement child2 = element.getChildElements().get(1);
final GenericDomValue<Boolean> genericValue = element.getGenericValue();
assertSameElements(visited, foo, child, child1, child2, genericValue, element.getAttr());
}
public void testChildrenReflection() throws Throwable {
final MyElement element =
createElement("<a><child/><child-element/><child-element/></a>");
final DomGenericInfo info = element.getGenericInfo();
final DomFixedChildDescription foo = info.getFixedChildDescription("foo");
assertFixedChildDescription(foo, element.getFoo(), "foo");
final DomFixedChildDescription child = info.getFixedChildDescription("child");
assertFixedChildDescription(child, element.getChild(), "child");
final DomFixedChildDescription genericChild = info.getFixedChildDescription("generic-value");
assertGenericChildDescription(genericChild, element.getGenericValue(), "generic-value");
final DomCollectionChildDescription collectionChild = info.getCollectionChildDescription("child-element");
assertEquals(element.getChildElements(), collectionChild.getValues(element));
assertEquals("child-element", collectionChild.getXmlElementName());
assertEquals(MyElement.class, collectionChild.getType());
assertEquals(MyElement.class.getMethod("getChildElements"), collectionChild.getGetterMethod().getMethod());
assertEquals(new HashSet(Arrays.asList(foo, child, collectionChild, genericChild,
info.getAttributeChildrenDescriptions().get(0))),
new HashSet(info.getChildrenDescriptions()));
}
private void assertFixedChildDescription(final DomFixedChildDescription description,
final DomElement child,
final String tagName) throws NoSuchMethodException {
assertEquals(1, description.getCount());
assertEquals(Arrays.asList(child), description.getValues(child.getParent()));
assertEquals(tagName, description.getXmlElementName());
assertEquals(MyElement.class, description.getType());
assertEquals(JavaMethod.getMethod(MyElement.class, new JavaMethodSignature("get" + StringUtil.capitalize(tagName))), description.getGetterMethod(0));
}
private static void assertGenericChildDescription(final DomFixedChildDescription description,
final DomElement child,
final String tagName) throws NoSuchMethodException {
assertEquals(1, description.getCount());
assertEquals(Arrays.asList(child), description.getValues(child.getParent()));
assertEquals(tagName, description.getXmlElementName());
assertEquals(GenericDomValue.class, ((ParameterizedType)description.getType()).getRawType());
assertEquals(JavaMethod.getMethod(MyElement.class, new JavaMethodSignature("getGenericValue")), description.getGetterMethod(0));
}
public void testGetDomElementType() throws Throwable {
final MyElement element = createElement("<a/>");
assertEquals(MyElement.class.getMethod("getGenericValue").getGenericReturnType(), element.getGenericValue().getDomElementType());
}
public void testAddChildrenByReflection() throws Throwable {
final MyElement element =
createElement("<a><child-element/></a>");
final DomGenericInfo info = element.getGenericInfo();
final DomCollectionChildDescription collectionChild = info.getCollectionChildDescription("child-element");
final List<? extends DomElement> values = collectionChild.getValues(element);
MyElement newChild = (MyElement) collectionChild.addValue(element);
List<DomElement> newChildren = Arrays.asList(values.get(0), newChild);
assertEquals(newChildren, element.getChildElements());
assertEquals(newChildren, collectionChild.getValues(element));
MyElement lastChild = (MyElement) collectionChild.addValue(element, 0);
newChildren = Arrays.asList(lastChild, values.get(0), newChild);
assertEquals(newChildren, element.getChildElements());
assertEquals(newChildren, collectionChild.getValues(element));
}
public void testGetPresentableName() throws Throwable {
assertCollectionPresentableName("Aaas", "aaa", DomNameStrategy.HYPHEN_STRATEGY);
assertCollectionPresentableName("Aaa Bbbs", "aaa-bbb", DomNameStrategy.HYPHEN_STRATEGY);
assertCollectionPresentableName("Aaas", "aaa", DomNameStrategy.JAVA_STRATEGY);
assertCollectionPresentableName("Aaa Children", "aaaChild", DomNameStrategy.JAVA_STRATEGY);
assertFixedPresentableName("Aaa Bbbs", "aaa-bbbs", DomNameStrategy.HYPHEN_STRATEGY);
assertFixedPresentableName("Aaa Child", "aaaChild", DomNameStrategy.JAVA_STRATEGY);
}
private void assertCollectionPresentableName(final String expected, final String tagName, final DomNameStrategy strategy) {
assertEquals(expected, new CollectionChildDescriptionImpl(new XmlName(tagName), DomElement.class, null).getCommonPresentableName(strategy));
}
private void assertFixedPresentableName(final String expected, final String tagName, final DomNameStrategy strategy) {
assertEquals(expected, new FixedChildDescriptionImpl(new XmlName(tagName), DomElement.class, 0, new Collection[0]).getCommonPresentableName(strategy));
}
public void testNameStrategy() throws Throwable {
assertTrue(createElement("<a/>").getNameStrategy() instanceof HyphenNameStrategy);
final AnotherElement anotherElement = createElement("<a/>", AnotherElement.class);
assertTrue(anotherElement.getNameStrategy() instanceof JavaNameStrategy);
assertTrue(anotherElement.getChild().getNameStrategy() instanceof JavaNameStrategy);
}
public void testModificationCount() throws Throwable {
final MyElement element = createElement("<a/>");
final long count = DomUtil.getFileElement(element).getModificationCount();
element.addChildElement();
assertTrue(DomUtil.getFileElement(element).getModificationCount() > count);
}
public void testIsTagValueElement() throws Throwable {
assertTrue(getDomManager().getGenericInfo(MyElement.class).isTagValueElement());
assertFalse(getDomManager().getGenericInfo(AnotherElement.class).isTagValueElement());
}
public void testAttributeChildrenGenerics() throws Throwable {
final StaticGenericInfo genericInfo = DomApplicationComponent.getInstance().getStaticGenericInfo(MyElement.class);
final List<? extends DomAttributeChildDescription> descriptions = genericInfo.getAttributeChildrenDescriptions();
assertEquals(1, descriptions.size());
final DomAttributeChildDescription description = descriptions.get(0);
final MyElement element = createElement("");
assertEquals(element.getAttr(), description.getValues(element).get(0));
assertEquals(element.getAttr(), description.getDomAttributeValue(element));
}
private MyElement createElement(final String xml) throws IncorrectOperationException {
return createElement(xml, MyElement.class);
}
public void testSubPropertyAccessing() throws Throwable {
final MyElement element = createElement("");
final GenericAttributeValue<String> attr = element.getChild().getChild().getAttr();
assertNotNull(attr);
assertEquals(element.getChildChildAttr(), attr);
final GenericAttributeValue<String> attr1 = element.getChild().addChildElement().getAttr();
final GenericAttributeValue<String> attr2 = element.getChild().addChildElement().getAttr();
assertOrderedEquals(element.getChildChildrenAttr(), attr1, attr2);
}
public void testInstanceImplementation() throws Throwable {
MyElement element = createElement("");
final Object o = new Object();
element.setObject(o);
assertSame(o, element.getObject());
element = createElement("", InheritedElement.class);
element.setObject(o);
assertSame(o, element.getObject());
assertSame(o, element.getObject());
}
public void testSeveralInstanceImplementations() throws Throwable {
InheritedElement element = createElement("", InheritedElement.class);
final Object o = new Object();
element.setObject(o);
assertSame(o, element.getObject());
assertSame(o, element._getObject());
element.setString("foo");
assertEquals("foo", element.getString());
}
public void testVisitor() throws Throwable {
final Integer[] visits = new Integer[]{0, 0, 0};
DomElementVisitor visitor = new MyVisitor() {
@Override
public void visit(InheritedElement element) {
visits[0]++;
}
@Override
public void visitDomElement(DomElement element) {
visits[1]++;
}
@Override
public void visitMyElement(MyElement element) {
visits[2]++;
}
};
createElement("", MyElement.class).accept(visitor);
final List<Integer> visitsList = Arrays.asList(visits);
assertEquals(Arrays.asList(0, 0, 1), visitsList);
createElement("", InheritedElement.class).accept(visitor);
assertEquals(Arrays.asList(1, 0, 1), visitsList);
createElement("", AnotherElement.class).accept(visitor);
assertEquals(Arrays.asList(1, 1, 1), visitsList);
createElement("", DomElement.class).accept(visitor);
assertEquals(Arrays.asList(1, 2, 1), visitsList);
createElement("", InheritedElement.class).accept(new DomElementVisitor() {
@Override
public void visitDomElement(DomElement element) {
visits[1]++;
}
});
assertEquals(Arrays.asList(1, 3, 1), visitsList);
}
public void testRegisteringImplementation() throws Throwable {
DomApplicationComponent.getInstance().registerImplementation(AnotherElement.class, EmptyImpl.class, getTestRootDisposable());
DomApplicationComponent.getInstance().registerImplementation(DomElement.class, BaseImpl.class, getTestRootDisposable());
final AnotherElement element = createElement("", AnotherElement.class);
assertTrue(element.getClass().getSuperclass().getName(), element instanceof EmptyImpl);
}
public void testMockElements() throws Throwable {
Module module = new MockModule(getTestRootDisposable());
final MyElement element = getDomManager().createMockElement(MyElement.class, module, false);
assertSame(module, element.getModule());
assertTrue(element.isValid());
assertNull(element.getXmlTag());
assertEquals(element, DomUtil.getFileElement(element).getRootElement());
assertFalse(DomUtil.getFile(element).isPhysical());
final MyElement element2 = getDomManager().createMockElement(MyElement.class, null, false);
assertNull(element2.getModule());
assertNull(element2.getXmlTag());
element2.addChildElement().getGenericValue().setStringValue("xxx");
assertNotNull(element2.getXmlTag());
final MyElement oldChild = element2.getChild();
element.getAttr().setValue("attr");
element.getGenericValue().setValue(Boolean.TRUE);
element.getChild().getGenericValue().setStringValue("abc");
element.addChildElement().getGenericValue().setStringValue("def");
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
element2.copyFrom(element);
}
}.execute();
assertEquals("attr", element2.getAttr().getValue());
assertEquals("true", element2.getGenericValue().getStringValue());
final MyElement newChild = element2.getChild();
assertEquals("abc", newChild.getGenericValue().getStringValue());
final List<MyElement> childElements = element2.getChildElements();
assertEquals(1, childElements.size());
assertEquals("def", childElements.get(0).getGenericValue().getStringValue());
}
public void testCopyingFromEmptyToEmpty() throws Throwable {
Module module = new MockModule(getTestRootDisposable());
MyElement element1 = getDomManager().createMockElement(MyElement.class, module, false);
MyElement element2 = getDomManager().createMockElement(MyElement.class, module, false);
element2.copyFrom(element1);
assertNull(element2.getXmlTag());
}
public void testCopyingFromNonEmptyToEmpty() throws Throwable {
Module module = new MockModule(getTestRootDisposable());
final MyElement element1 = getDomManager().createMockElement(MyElement.class, module, false);
final MyElement element2 = getDomManager().createMockElement(MyElement.class, module, false);
element2.ensureTagExists();
assertNull(element2.getChild().getChild().getGenericValue().getStringValue());
element1.getChild().getChild().getGenericValue().setStringValue("abc");
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
element2.copyFrom(element1);
}
}.execute();
assertEquals("abc", element2.getChild().getChild().getGenericValue().getStringValue());
}
public void testStableValues() throws Throwable {
final MyElement[] element = new MyElement[]{null};
final MyElement stable = getDomManager().createStableValue(new Factory<MyElement>() {
@Override
public MyElement create() {
try {
return element[0] = createElement("<root/>").addChildElement();
}
catch (IncorrectOperationException e) {
throw new RuntimeException(e);
}
}
});
assertNotNull(element[0]);
assertSame(element[0], ((StableElement)stable).getWrappedElement());
assertEquals(element[0], stable);
assertEquals(stable, element[0]);
MyElement oldElement = element[0];
assertFalse(stable.getChild().equals(stable));
final GenericDomValue<Boolean> oldGenericValue = stable.getGenericValue();
assertEquals(oldGenericValue, oldElement.getGenericValue());
assertEquals(stable.getChild(), oldElement.getChild());
assertSame(element[0], oldElement);
final MyElement child1 = stable.addChildElement();
final MyElement child2 = stable.addChildElement();
MyElement oldChild1 = oldElement.getChildElements().get(0);
assertEquals(oldChild1, child1);
assertEquals(child1, oldChild1);
final MyElement oldElement1 = oldElement;
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
oldElement1.undefine();
}
}.execute();
assertFalse(oldChild1.isValid());
assertFalse(oldElement.isValid());
assertFalse(element[0].isValid());
assertTrue(stable.isValid());
assertTrue(element[0].isValid());
assertNotSame(element[0], oldElement);
assertFalse(child1.isValid());
assertFalse(child2.isValid());
assertEquals(DomUtil.getFileElement(element[0]), DomUtil.getFileElement(stable));
assertEquals(element[0].getParent(), stable.getParent());
oldElement = element[0];
oldChild1 = oldElement.getChild();
((StableElement)stable).invalidate();
assertTrue(oldElement.isValid());
assertTrue(oldChild1.isValid());
assertFalse(oldElement.equals(((StableElement)stable).getWrappedElement()));
}
public void testStable_Revalidate() throws Throwable {
final MyElement[] element = new MyElement[]{createElement("")};
final MyElement stable = getDomManager().createStableValue(new Factory<MyElement>() {
@Override
public MyElement create() {
return element[0];
}
});
MyElement oldElement = element[0];
((StableElement) stable).revalidate();
assertSame(oldElement, ((StableElement) stable).getWrappedElement());
element[0] = createElement("");
assertTrue(oldElement.isValid());
((StableElement) stable).revalidate();
assertTrue(oldElement.isValid());
assertNotSame(oldElement, ((StableElement) stable).getWrappedElement());
assertSame(element[0], ((StableElement) stable).getWrappedElement());
}
public void testStable_Invalidate() throws Throwable {
final MyElement oldElement = createElement("");
final MyElement[] element = new MyElement[]{oldElement};
final MyElement stable = getDomManager().createStableValue(new Factory<MyElement>() {
@Override
public MyElement create() {
return element[0];
}
});
element[0] = null;
((StableElement) stable).invalidate();
assertTrue(stable.equals(stable));
assertEquals(oldElement.toString(), stable.toString());
}
public void testStableCopies() throws Throwable {
final MyElement element = createElement("<a><child-element/><child-element><child/></child-element></a>");
final MyElement parent = element.getChildElements().get(1);
final MyElement child = parent.getChild();
final MyElement copy = (MyElement) child.createStableCopy();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
parent.undefine();
element.addChildElement().getChild().ensureXmlElementExists();
}
}.execute();
assertFalse(child.isValid());
assertTrue(copy.isValid());
}
@Implementation(Impl.class)
public interface MyElement extends DomElement {
GenericAttributeValue<String> getAttr();
String getValue();
MyElement getFoo();
MyElement getChild();
MyElement addChildElement();
@SuppressWarnings({"UnusedDeclaration"})
MyElement addChildElement(int index);
List<MyElement> getChildElements();
GenericDomValue<Boolean> getGenericValue();
Object getObject();
void setObject(Object o);
@PropertyAccessor({"child", "child", "attr"})
GenericAttributeValue<String> getChildChildAttr();
@PropertyAccessor({"child", "childElements", "attr"})
List<GenericAttributeValue<String>> getChildChildrenAttr();
}
public static abstract class Impl implements MyElement {
private Object myObject;
public Object _getObject() {
return myObject;
}
@Override
public Object getObject() {
return myObject;
}
@Override
public void setObject(final Object object) {
myObject = object;
}
}
public static abstract class AnotherImpl extends Impl implements InheritedElement{
private String myString;
@Override
public String getString() {
return myString;
}
@Override
public void setString(final String string) {
myString = string;
}
}
@NameStrategy(JavaNameStrategy.class)
public interface AnotherElement extends DomElement {
DomElement getChild();
}
public static abstract class BaseImpl implements DomElement{}
public static abstract class EmptyImpl extends BaseImpl implements AnotherElement{}
@Implementation(AnotherImpl.class)
public interface InheritedElement extends MyElement, DomElement {
String getString();
void setString(final String string);
Object _getObject();
}
public interface MyVisitor extends DomElementVisitor{
void visitMyElement(MyElement element);
void visit(InheritedElement element);
}
}
@@ -0,0 +1,614 @@
package com.intellij.util.xml;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.events.DomEvent;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author peter
*/
public class DomChildrenTest extends DomTestCase {
private MyElement createElement(final String xml) throws IncorrectOperationException {
return createElement(xml, MyElement.class);
}
public void testGetChild() throws Throwable {
final MyElement element = createElement("<a>" + "<child>foo</child>" + "</a>");
element.toString();
assertEquals("foo", element.getMyChild().getValue());
assertEquals("foo", element.getChild().getValue());
assertSame(element.getChild(), element.getMyChild());
assertNull(element.getChild239().getXmlTag());
}
public void testGetChild239() throws Throwable {
final MyElement element = createElement("<a><child/><child-239/></a>");
assertNotNull(element.getChild239().getXmlTag());
}
public void testGetChildren() throws Throwable {
final MyElement element = createElement("<a>" + "<child-element>foo</child-element>" + "<child-element>bar</child-element>" + "</a>");
assertSubBars(element.getMyChildren());
assertSubBars(element.getChildElements());
assertSubBars(element.getMyChildren2());
}
public void testGetChildrenMultipleTimes() throws Throwable {
final MyElement element = createElement("<a>" + "<child-element>" + " <child-element/>" + "</child-element>" + "</a>");
for (int i = 0; i < 239; i++) {
final List<MyElement> children = element.getChildElements();
final MyElement child = children.get(0);
final List<MyElement> children1 = child.getChildElements();
final MyElement child1 = children1.get(0);
assertNotNull(child1.getChild());
}
}
private void assertSubBars(final List<? extends MyElement> subBars) {
assertEquals(2, subBars.size());
assertEquals("foo", subBars.get(0).getValue());
assertEquals("bar", subBars.get(1).getValue());
}
public void testClassChoosers() throws Throwable {
getTypeChooserManager().registerTypeChooser(MyAbstractElement.class, new MyTypeChooser());
try {
MyElement element = createElement("<a>" +
"<abstract-child>Foo</abstract-child>" +
"<abstract-element>Foo</abstract-element>" +
"<abstract-element>bar</abstract-element>" + "</a>");
assertFalse(element.getAbstractChild()instanceof MyBarConcreteElement);
final List<MyAbstractElement> abstractElements = element.getAbstractElements();
assertTrue(abstractElements.get(0)instanceof MyFooConcreteElement);
assertTrue(abstractElements.get(1)instanceof MyBarConcreteElement);
}
finally {
getTypeChooserManager().unregisterTypeChooser(MyAbstractElement.class);
}
}
public void testAddConcreteElements() throws Throwable {
getTypeChooserManager().registerTypeChooser(MyAbstractElement.class, new MyTypeChooser());
try {
MyElement element = createElement("<a/>");
element.addBarChild();
element.addFooChild();
element.addAbstractElement(MyFooConcreteElement.class);
element.addAbstractElement(MyFooConcreteElement.class, 1);
element.addAbstractElement(2, MyBarConcreteElement.class);
Class[] classes = new Class[]{MyBarConcreteElement.class, MyFooConcreteElement.class, MyBarConcreteElement.class,
MyFooConcreteElement.class, MyFooConcreteElement.class};
final List<MyAbstractElement> abstractElements = element.getAbstractElements();
for (int i = 0; i < abstractElements.size(); i++) {
MyAbstractElement abstractElement = abstractElements.get(i);
assertTrue(String.valueOf(i) + " " + abstractElement.getClass(), classes[i].isInstance(abstractElement));
assertEquals(String.valueOf(i), classes[i].getName(), abstractElement.getXmlTag().getAttributeValue("foo"));
}
}
finally {
getTypeChooserManager().unregisterTypeChooser(MyAbstractElement.class);
}
}
public void testIndexedChild() throws Throwable {
MyElement element = createElement("<a>" + "<child>foo</child>" + "<child>bar</child>" + "</a>");
assertCached(element.getChild2(), element.getXmlTag().getSubTags()[1]);
assertEquals(0, element.getChildElements().size());
}
public void testDefiningIndexedChild() throws Throwable {
final MyElement element = createElement("<a/>");
final XmlTag tag = element.getChild2().ensureTagExists();
final XmlTag[] subTags = element.getXmlTag().findSubTags("child");
assertEquals(2, subTags.length);
assertSame(tag, subTags[1]);
assertCached(element.getChild(), subTags[0]);
final DomElement element1 = element.getChild();
putExpected(new DomEvent(element1, true));
final DomElement element2 = element.getChild().getAttr();
putExpected(new DomEvent(element2, true));
final DomElement element3 = element.getChild().isGenericValue();
putExpected(new DomEvent(element3, true));
final DomElement element4 = element.getChild2();
putExpected(new DomEvent(element4, true));
final DomElement element5 = element.getChild2().getAttr();
putExpected(new DomEvent(element5, true));
final DomElement element6 = element.getChild2().isGenericValue();
putExpected(new DomEvent(element6, true));
assertResultsAndClear();
}
public void testAddChild() throws Throwable {
final MyElement element = createElement("<a><child-element/></a>");
assertEquals(1, element.getChildElements().size());
final MyElement firstChild = element.getChildElements().get(0);
final XmlTag firstChildTag = element.getXmlTag().findSubTags("child-element")[0];
assertCached(firstChild, firstChildTag);
final MyElement child = element.addChildElement();
assertEquals(Arrays.asList(firstChild, child), element.getChildElements());
final XmlTag childTag = element.getXmlTag().findSubTags("child-element")[1];
putExpected(new DomEvent(element, false));
final DomElement element1 = child.getAttr();
putExpected(new DomEvent(element1, true));
final DomElement element2 = child.isGenericValue();
putExpected(new DomEvent(element2, true));
final MyElement newChild = element.addChildElement(1);
assertEquals(Arrays.asList(firstChild, newChild, child), element.getChildElements());
final XmlTag newChildTag = element.getXmlTag().findSubTags("child-element")[1];
putExpected(new DomEvent(element, false));
final DomElement element3 = newChild.getAttr();
putExpected(new DomEvent(element3, true));
final DomElement element4 = newChild.isGenericValue();
putExpected(new DomEvent(element4, true));
final MyElement lastChild = element.addChildElement(239);
assertEquals(Arrays.asList(firstChild, newChild, child, lastChild), element.getChildElements());
final XmlTag lastChildTag = element.getXmlTag().findSubTags("child-element")[3];
putExpected(new DomEvent(element, false));
final DomElement element5 = lastChild.getAttr();
putExpected(new DomEvent(element5, true));
final DomElement element6 = lastChild.isGenericValue();
putExpected(new DomEvent(element6, true));
assertResultsAndClear();
assertCached(firstChild, firstChildTag);
assertCached(newChild, newChildTag);
assertCached(child, childTag);
assertCached(lastChild, lastChildTag);
assertSame(firstChildTag, element.getXmlTag().findSubTags("child-element")[0]);
assertSame(newChildTag, element.getXmlTag().findSubTags("child-element")[1]);
assertSame(childTag, element.getXmlTag().findSubTags("child-element")[2]);
assertSame(lastChildTag, element.getXmlTag().findSubTags("child-element")[3]);
}
public void testUndefineCollectionChild() throws Throwable {
final MyElement element = createElement("<a><child-element/><child-element/><child-element/></a>");
final MyElement child1 = element.getChildElements().get(0);
final MyElement child2 = element.getChildElements().get(1);
final MyElement child3 = element.getChildElements().get(2);
final List<XmlTag> oldChildren = new ArrayList<XmlTag>(Arrays.asList(element.getXmlTag().getSubTags()));
assertTrue(child2.isValid());
assertEquals(element, child2.getParent());
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
child2.undefine();
assertFalse(child2.isValid());
oldChildren.remove(1);
assertEquals(oldChildren, Arrays.asList(element.getXmlTag().getSubTags()));
assertEquals(Arrays.asList(child1, child3), element.getChildElements());
assertCached(child1, element.getXmlTag().findSubTags("child-element")[0]);
assertCached(child3, element.getXmlTag().findSubTags("child-element")[1]);
}
});
myCallRegistry.putExpected(new DomEvent(element, false));
myCallRegistry.assertResultsAndClear();
}
public void testUndefineFixedChild() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final MyElement child = createElement("<a><child/></a>").getChild();
incModCount();
child.ensureTagExists();
assertTrue(child.isValid());
assertNotNull(child.getXmlElement());
incModCount();
child.undefine();
assertTrue(child.isValid());
assertNull(child.getXmlElement());
child.ensureTagExists();
incModCount();
assertTrue(child.isValid());
assertNotNull(child.getXmlElement());
}
}.execute().throwException();
}
public void testAttributes() throws Throwable {
final MyElement element = createElement("<a/>");
final GenericAttributeValue<String> attr = element.getAttr();
assertSame(element.getXmlTag(), attr.getXmlTag());
assertNull(attr.getValue());
assertNull(attr.getXmlAttribute());
assertEquals(attr, element.getAttr());
attr.setValue("239");
assertEquals("239", attr.getValue());
final XmlAttribute attribute = element.getXmlTag().getAttribute("attr", null);
assertSame(attribute, attr.getXmlAttribute());
assertSame(attribute, attr.getXmlElement());
assertSame(attribute, attr.ensureXmlElementExists());
assertSame(attribute.getValueElement(), attr.getXmlAttributeValue());
attr.setValue(null);
assertFalse(attribute.isValid());
assertNull(element.getXmlTag().getAttributeValue("attr"));
assertNull(attr.getValue());
assertNull(attr.getXmlAttribute());
}
public void testUndefineLastFixedChildWithNotEmptyCollection() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final MyElement element = createElement("<a>" + "<child>1</child>" + "<child attr=\"\">2</child>" + "<child/></a>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
assertEquals("", child2.getAttr().getValue());
assertTrue(child.isValid());
assertTrue(child2.isValid());
child.undefine();
assertTrue(child.isValid());
assertTrue(child2.isValid());
assertTrue(child2.equals(element.getChild2()));
assertNotNull(child.getXmlTag());
child2.undefine();
assertTrue(child.isValid());
assertTrue(child2.isValid());
assertTrue(child2.equals(element.getChild2()));
assertEquals(child, element.getChild());
assertEquals("", child.getValue());
assertNull(element.getChild2().getValue());
myCallRegistry.putExpected(new DomEvent(child, false));
myCallRegistry.putExpected(new DomEvent(child2, false));
myCallRegistry.assertResultsAndClear();
}
}.execute().throwException();
}
public void testUndefineNotLastFixedChild() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final MyElement element = createElement("<a>" + "<child>1</child>" + "<child attr=\"\">2</child>" + "</a>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
assertTrue(child.isValid());
assertTrue(child2.isValid());
child.undefine();
assertTrue(child.isValid());
assertTrue(child2.isValid());
assertEquals(element, child.getParent());
assertEquals(element, child2.getParent());
assertEquals(child, element.getChild());
assertEquals(child2, element.getChild2());
myCallRegistry.putExpected(new DomEvent(child, false));
myCallRegistry.assertResultsAndClear();
XmlTag[] subTags = element.getXmlTag().getSubTags();
assertEquals(2, subTags.length);
assertCached(child, subTags[0]);
assertCached(child2, subTags[1]);
}
}.execute().throwException();
}
public void testUndefineLastFixedChild() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final MyElement element =
createElement("<a>" + "<child>1</child>" + "<child attr=\"\">2</child>" + "<child attr=\"\">2</child>" + "</a>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
child2.undefine();
myCallRegistry.putExpected(new DomEvent(child2, false));
myCallRegistry.assertResultsAndClear();
XmlTag[] subTags = element.getXmlTag().getSubTags();
assertTrue(child.isValid());
assertTrue(child2.isValid());
assertEquals(1, subTags.length);
assertNull(child2.getXmlTag());
assertEquals(element, child.getParent());
assertEquals(element, child2.getParent());
}
}.execute().throwException();
}
public void testUndefineFixedChildWithNoTag() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final MyElement element = createElement("<a/>");
final MyElement child = element.getChild();
child.undefine();
myCallRegistry.assertResultsAndClear();
assertTrue(child.isValid());
assertEquals(0, element.getXmlTag().getSubTags().length);
assertSame(element, child.getParent());
}
}.execute().throwException();
}
public void testGenericValuesCollection() throws Throwable {
final MyElement element = createElement("<a><generic-child>239</generic-child></a>");
assertEquals(239, (int)element.getGenericChildren().get(0).getValue());
}
public void testIsBooleanGenericValueMethod() throws Throwable {
assertNull(createElement("").isGenericValue().getValue());
}
public void testGetParentOfType() throws Throwable {
getTypeChooserManager().registerTypeChooser(MyAbstractElement.class, new MyTypeChooser());
try {
final MyElement element = createElement("");
final MyAbstractElement abstractChild = element.getAbstractChild();
final MyElement child239 = abstractChild.getChild239();
assertSame(child239, child239.getParentOfType(MyElement.class, false));
assertSame(abstractChild, child239.getParentOfType(MyElement.class, true));
assertSame(abstractChild, child239.getParentOfType(MyAbstractElement.class, true));
assertSame(DomUtil.getFileElement(element), child239.getParentOfType(DomFileElement.class, false));
assertSame(DomUtil.getFileElement(element), DomUtil.getFileElement(element).getParentOfType(DomFileElement.class, false));
assertNull(DomUtil.getFileElement(element).getParentOfType(DomFileElement.class, true));
}
finally {
getTypeChooserManager().unregisterTypeChooser(MyAbstractElement.class);
}
}
public void testChildrenValidAfterUndefine() throws Throwable {
final MyElement element = createElement("<a><child/></a>");
final MyElement child = element.getChild();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
element.undefine();
}
});
assertTrue(element.isValid());
assertFalse(child.isValid());
}
public void testGetCompositeCollection() throws Throwable {
final MyElement element = createElement("");
final MyFooConcreteElement foo = element.addFooChild();
final MyElement child = element.addChildElement();
final MyBarConcreteElement bar = element.addBarChild();
assertEquals(Arrays.asList(foo, bar, child), element.getCompositeList());
}
public void testAddToCompositeCollection() throws Throwable {
final MyElement element = createElement("");
final MyBarConcreteElement bar = element.addBarComposite();
final MyElement child = element.addChildComposite();
final MyElement child2 = element.addChildElement();
final MyFooConcreteElement foo1 = element.addFooComposite(2);
final MyFooConcreteElement foo2 = element.addFooComposite(0);
assertEquals(Arrays.asList(foo2, bar, child, foo1, child2), element.getCompositeList());
}
public void testCreateElementWithRequiredChild() throws Throwable {
final MyElement element = createElement("").addChildElement();
assertNotNull(element.getAttr().getXmlAttribute());
assertNotNull(element.isGenericValue().getXmlTag());
assertTrue(element.getMyChildren2().isEmpty());
}
public void testSetRequiredChildValue() throws Throwable {
final MyElement element = createElement("<a/>").getChild();
element.isGenericValue().setStringValue("true");
assertEquals(1, element.getXmlTag().findSubTags("generic-value").length);
assertTrue(element.isGenericValue().getValue());
}
public void testGetFixedPath() throws Throwable {
final MyElement element = createElement("");
final MyElement child2 = element.getChild2();
assertEquals(Arrays.asList("getChild2", "getChild2", "getChild239", "getAbstractChild", "getChild2"),
getFixedPath(child2.getChild2().getChild239().getAbstractChild().getChild2()));
assertEquals(Arrays.asList("getChild2"), getFixedPath(child2));
assertEquals(Arrays.asList(), getFixedPath(element));
assertEquals(Arrays.asList("getAttr"), getFixedPath(element.getAttr()));
assertNull(DomUtil.getFixedPath(element.addChildElement().getChild()));
}
public void testGetDomElementCustomChild() throws Throwable {
final MyElement myElement = createElement("<a><abstract-child/><generic-value/><bar/></a>", MyElement.class);
final XmlTag tag = myElement.getXmlTag();
assertEquals(1, myElement.getCustomChildren().size());
assertInstanceOf(getDomManager().getDomElement(tag.getSubTags()[0]), MyAbstractElement.class);
assertInstanceOf(getDomManager().getDomElement(tag.getSubTags()[1]), GenericDomValue.class);
assertInstanceOf(getDomManager().getDomElement(tag.getSubTags()[2]), MyElement.class);
}
public void testNoChildrenForMalformedTags() throws Throwable {
final MyElement myElement = createElement("<a><</a>", MyElement.class);
final XmlTag tag = myElement.getXmlTag();
assertEquals(0, myElement.getCustomChildren().size());
}
public void testCustomNameChildren() throws Throwable {
final MyElement myElement = createElement("<a><foo/><bar/><foo xmlns=\"z\"/></a>", MyElement.class);
final XmlTag tag = myElement.getXmlTag();
final List<MyElement> customChildren = myElement.getCustomChildren();
assertOrderedEquals(customChildren, myElement.getGenericInfo().getCustomNameChildrenDescription().getValues(myElement));
assertOrderedCollection(customChildren, new Consumer<MyElement>() {
@Override
public void consume(final MyElement element) {
assertInstanceOf(element, MyElement.class);
assertEquals(tag.getSubTags()[0], element.getXmlTag());
}
}, new Consumer<MyElement>() {
@Override
public void consume(final MyElement element) {
assertInstanceOf(element, MyElement.class);
assertEquals(tag.getSubTags()[1], element.getXmlTag());
}
}, new Consumer<MyElement>() {
@Override
public void consume(final MyElement element) {
assertInstanceOf(element, MyElement.class);
assertEquals(tag.getSubTags()[2], element.getXmlTag());
}
});
}
private List<String> getFixedPath(final DomElement element) {
return ContainerUtil.map2List(DomUtil.getFixedPath(element), new Function<JavaMethod, String>() {
@Override
public String fun(final JavaMethod s) {
return s.getName();
}
});
}
public void testElementsWithoutXmlGetItLater() throws Throwable {
final MyElement element = createElement("<a/>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
final PsiElement tag = element.getXmlTag().add(createTag("<child/>"));
incModCount();
assertTrue(child.isValid());
assertEquals(tag, child.getXmlTag());
assertTrue(child2.isValid());
assertNull(child2.getXmlTag());
}
public void testHigherOrderFixedsAreNotCustom() {
final MyElement element = createElement("<a><child/><child/><child/></a>");
XmlTag third = element.getXmlTag().getSubTags()[2];
assertNull(getDomManager().getDomElement(third));
assertEmpty(element.getCustomChildren());
}
public interface MyElement extends DomElement {
@Attribute
@Required
GenericAttributeValue<String> getAttr();
String getValue();
@SubTag("child")
MyElement getMyChild();
MyElement getChild();
@SubTag(value = "child", index = 1)
MyElement getChild2();
MyElement getChild239();
@SubTagList("child-element")
List<? extends MyElement> getMyChildren();
@CustomChildren
List<MyElement> getCustomChildren();
@SubTagList("child-element")
@Required
List<MyElement> getMyChildren2();
List<MyElement> getChildElements();
MyElement addChildElement();
MyElement addChildElement(int index);
MyAbstractElement getAbstractChild();
List<MyAbstractElement> getAbstractElements();
@SubTagList("abstract-element")
MyBarConcreteElement addBarChild();
@SubTagList("abstract-element")
MyFooConcreteElement addFooChild();
<T extends MyAbstractElement> T addAbstractElement(Class<T> aClass);
<T extends MyAbstractElement> T addAbstractElement(Class<T> aClass, int index);
<T extends MyAbstractElement> T addAbstractElement(int index, Class<T> aClass);
List<GenericDomValue<Integer>> getGenericChildren();
@Required
GenericDomValue<Boolean> isGenericValue();
@SubTagsList({"child-element", "abstract-element"})
List<MyElement> getCompositeList();
@SubTagsList(value = {"child-element", "abstract-element"}, tagName = "abstract-element")
MyBarConcreteElement addBarComposite();
@SubTagsList(value = {"child-element", "abstract-element"}, tagName = "child-element")
MyElement addChildComposite();
@SubTagsList(value = {"child-element", "abstract-element"}, tagName = "abstract-element")
MyFooConcreteElement addFooComposite(int index);
}
public interface MyAbstractElement extends MyElement {
}
public interface MyFooConcreteElement extends MyAbstractElement {
MyFooConcreteElement getFoo();
}
public interface MyBarConcreteElement extends MyAbstractElement {
}
private static class MyTypeChooser extends TypeChooser {
@Override
public Type chooseType(final XmlTag tag) {
return tag != null && tag.getText().contains("Foo") ? MyFooConcreteElement.class : MyBarConcreteElement.class;
}
@Override
public void distinguishTag(final XmlTag tag, final Type aClass) throws IncorrectOperationException {
tag.setAttribute("foo", ((Class)aClass).getName());
}
@Override
public Type[] getChooserTypes() {
return ArrayUtil.EMPTY_CLASS_ARRAY;
}
}
}
@@ -0,0 +1,233 @@
/*
* Copyright (c) 2000-2007 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.semantic.SemService;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.Timings;
import com.intellij.util.xml.impl.DomFileElementImpl;
import com.intellij.util.xml.reflect.DomExtender;
import com.intellij.util.xml.reflect.DomExtenderEP;
import com.intellij.util.xml.reflect.DomExtensionsRegistrar;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
/**
* @author peter
*/
public class DomConcurrencyStressTest extends DomTestCase {
private static final int ITERATIONS = Timings.adjustAccordingToMySpeed(239, true);
public void testInternalDomLocksReadConsistency() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription(MyElement.class, "a"), myTestRootDisposable);
registerExtender(MyElement.class, MyExtender.class);
final XmlFile file = createXmlFile("<a attr=\"1\" attr2=\"2\">" +
"<foo-child><foo-child/><custom-foo/></foo-child>" +
"<bar-child><foo-child/></bar-child>" +
"<foo-element>" +
" <foo-child/>" +
" <foo-child><foo-child attr=\"\"/></foo-child>" +
" <custom-foo/>" +
" <custom-bar/>" +
"</foo-element>" +
"<custom-bar/>" +
"<custom-bar>" +
" <foo-child/>" +
" <foo-element/>" +
" <foo-element/>" +
" <custom-bar/>" +
"</custom-bar>" +
"<custom-bar attr=\"\">" +
" <foo-child/>" +
" <some-child/>" +
" <custom-bar/>" +
"</custom-bar>" +
"<child/>" +
"<child/>" +
"<bool/>" +
"</a>");
System.out.println("ITERATIONS =" + ITERATIONS);
runThreads(42, new Runnable() {
@Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final DomFileElementImpl<DomElement> element = getDomManager().getFileElement(file);
assertNotNull(element);
element.getRootElement().accept(new DomElementVisitor() {
@Override
public void visitDomElement(final DomElement element) {
if (DomUtil.hasXml(element)) {
element.acceptChildren(this);
}
}
});
}
});
SemService.getSemService(getProject()).clearCache();
}
}
});
}
private void registerExtender(final Class elementClass, final Class extenderClass) {
final DomExtenderEP extenderEP = new DomExtenderEP();
extenderEP.domClassName = elementClass.getName();
extenderEP.extenderClassName = extenderClass.getName();
PlatformTestUtil.registerExtension(Extensions.getRootArea(), DomExtenderEP.EP_NAME, extenderEP, myTestRootDisposable);
}
private static void runThreads(int threadCount, final Runnable runnable) throws Throwable {
final Ref<Throwable> exc = Ref.create(null);
final CountDownLatch reads = new CountDownLatch(threadCount);
for (int j = 0; j < threadCount; j++) {
new Thread(){
@Override
public void run() {
try {
runnable.run();
}
catch (Throwable e) {
exc.set(e);
} finally {
reads.countDown();
}
}
}.start();
}
reads.await();
if (!exc.isNull()) {
throw exc.get();
}
}
public interface MyElement extends DomElement {
MyElement getFooChild();
MyElement getBarChild();
MyElement getSomeChild();
List<MyElement> getFooElements();
MyElement addFooElement();
List<MyElement> getChildren();
MyElement addChild();
GenericAttributeValue<String> getAttr();
GenericAttributeValue<String> getAttr2();
@SubTag(indicator = true)
GenericDomValue<Boolean> getBool();
}
public static class MyExtender extends DomExtender<MyElement> {
private final Random myRandom = new Random();
@Override
public void registerExtensions(@NotNull MyElement myElement, @NotNull DomExtensionsRegistrar registrar) {
for (MyElement element : myElement.getFooElements()) {
element.getFooElements();
}
if (myRandom.nextInt(20) < 2) {
try {
Thread.sleep(1);
}
catch (InterruptedException ignored) {
}
}
registrar.registerFixedNumberChildExtension(new XmlName("custom-foo", null), MyElement.class);
myElement.getSomeChild().getFooElements();
myElement.getFooChild().getFooChild().getAttr();
myElement.getAttr();
registrar.registerCollectionChildrenExtension(new XmlName("custom-bar", null), MyElement.class);
}
}
public void testBigCustomFile() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription(MyAllCustomElement.class, "component"), myTestRootDisposable);
registerExtender(MyAllCustomElement.class, MyAllCustomExtender.class);
VirtualFile bigXml = LocalFileSystem.getInstance().findFileByPath(PathManagerEx.getTestDataPath() + "/psi/formatter/xml/performance.xml");
assert bigXml != null;
final XmlFile file = (XmlFile)PsiManager.getInstance(ourProject).findFile(bigXml);
runThreads(42, new Runnable() {
@Override
public void run() {
final Random random = new Random();
for (int i = 0; i < ITERATIONS; i++) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
int offset = random.nextInt(file.getTextLength() - 10);
XmlTag tag = PsiTreeUtil.findElementOfClassAtOffset(file, offset, XmlTag.class, false);
assert tag != null : offset;
DomElement element = DomUtil.getDomElement(tag);
assert element instanceof MyAllCustomElement : element;
}
});
if (random.nextInt(50) == 0) {
SemService.getSemService(getProject()).clearCache();
}
}
}
});
}
public interface MyAllCustomElement extends DomElement {}
public static class MyAllCustomExtender extends DomExtender<MyAllCustomElement> {
@Override
public void registerExtensions(@NotNull MyAllCustomElement element, @NotNull DomExtensionsRegistrar registrar) {
try {
DomElement parent = element;
while (parent != null) {
for (DomElement child : DomUtil.getDefinedChildren(parent, true, true)) {
DomElement childParent = child.getParent();
if (!parent.equals(childParent)) {
String parentText = parent.getXmlTag().getText();
String childText = child.getXmlElement().getText();
child.getParent();
parent.equals(childParent);
throw new AssertionError(parent.getXmlElement() + "; " + childParent + "; " + child.getXmlElement().getText());
}
}
parent = parent.getParent();
}
}
catch (StackOverflowError e) {
System.out.println(Thread.currentThread() + ": " + element.getXmlTag().getName() + element.getXmlTag().hashCode());
throw e;
}
registrar.registerCustomChildrenExtension(MyAllCustomElement.class);
}
}
}
@@ -0,0 +1,310 @@
/*
* Copyright (c) 2000-2007 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Key;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ParameterizedTypeImpl;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.xml.reflect.*;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* @author peter
*/
public class DomExtensionsTest extends DomTestCase {
private static final Key<Boolean> BOOL_KEY = Key.create("aaa");
public void testExtendAttributes() throws Throwable {
registerDomExtender(AttrDomExtender.class);
assertEmpty(getCustomChildren(createElement("<a foo=\"xxx\"/>", MyElement.class)));
MyElement element = createElement("<a attr=\"foo\" foo=\"true\"/>", MyElement.class);
final GenericAttributeValue child = assertInstanceOf(assertOneElement(getCustomChildren(element)), GenericAttributeValue.class);
assertEquals("true", child.getStringValue());
assertEquals(Boolean.TRUE, child.getValue());
assertEquals(Boolean.class, DomUtil.getGenericValueParameter(child.getDomElementType()));
assertSame(element.getXmlTag().getAttribute("foo"), child.getXmlElement());
child.setStringValue("xxx");
assertEquals("xxx", child.getStringValue());
assertEquals("xxx", element.getXmlTag().getAttributeValue("foo"));
element = createElement("<a attr=\"foo\" foo=\"true\"/>", MyElement.class);
final GenericAttributeValue value = getDomManager().getDomElement(element.getXmlTag().getAttribute("foo"));
assertNotNull(value);
assertEquals(value, assertOneElement(getCustomChildren(element)));
assertNotNull(element.getGenericInfo().getAttributeChildDescription("foo"));
}
public void testCustomAttributeChildClass() throws Throwable {
registerDomExtender(AttrDomExtender3.class);
final MyElement element = createElement("<a attr=\"xxx\"/>", MyElement.class);
assertEquals("xxx", assertInstanceOf(assertOneElement(getCustomChildren(element)), MyAttribute.class).getXmlElementName());
}
public void testUserData() throws Throwable {
registerDomExtender(AttrDomExtender3.class);
final MyElement element = createElement("<a attr=\"xxx\"/>", MyElement.class);
final DomAttributeChildDescription description = element.getGenericInfo().getAttributeChildDescription("xxx");
assertNotNull(description);
assertSame(Boolean.TRUE, description.getUserData(BOOL_KEY));
}
public void testUseCustomConverter() throws Throwable {
registerDomExtender(AttrDomExtender2.class);
final MyElement myElement = createElement("<a attr=\"xxx\" xxx=\"zzz\" yyy=\"zzz\"/>", MyElement.class);
assertUnorderedCollection(getCustomChildren(myElement), new Consumer<DomElement>() {
@Override
public void consume(final DomElement element) {
final StringBuffer stringBuffer = ((GenericAttributeValue<StringBuffer>)element).getValue();
assertEquals("zzz", stringBuffer.toString());
assertInstanceOf(((GenericAttributeValue<StringBuffer>)element).getConverter(), StringBufferConverter.class);
assertNotNull(myElement.getGenericInfo().getAttributeChildDescription("xxx"));
Convert convert = element.getAnnotation(Convert.class);
assertNotNull(convert);
assertEquals(StringBufferConverter.class, convert.value());
assertTrue(convert.soft());
}
}, new Consumer<DomElement>() {
@Override
public void consume(final DomElement element) {
final StringBuffer stringBuffer = ((GenericAttributeValue<StringBuffer>)element).getValue();
assertEquals("zzz", stringBuffer.toString());
assertInstanceOf(((GenericAttributeValue<StringBuffer>)element).getConverter(), StringBufferConverter.class);
assertNotNull(myElement.getGenericInfo().getAttributeChildDescription("yyy"));
Convert convert = element.getAnnotation(Convert.class);
assertNotNull(convert);
assertEquals(StringBufferConverter.class, convert.value());
assertFalse(convert.soft());
}
});
}
public void testFixedChildren() throws Throwable {
registerDomExtender(FixedDomExtender.class);
final MyElement myElement = createElement("<a attr=\"xxx\"><xxx>zzz</xxx><yyy attr=\"foo\"/><yyy attr=\"bar\"/></a>", MyElement.class);
assertUnorderedCollection(getCustomChildren(myElement), new Consumer<DomElement>() {
@Override
public void consume(final DomElement element) {
assertEquals(GenericDomValue.class, ReflectionUtil.getRawType(element.getDomElementType()));
final StringBuffer stringBuffer = ((GenericDomValue<StringBuffer>)element).getValue();
assertEquals("zzz", stringBuffer.toString());
assertInstanceOf(((GenericDomValue<StringBuffer>)element).getConverter(), MyStringBufferConverter.class);
assertNotNull(myElement.getGenericInfo().getFixedChildDescription("xxx"));
Convert convert = element.getAnnotation(Convert.class);
assertNotNull(convert);
assertEquals(MyStringBufferConverter.class, convert.value());
assertTrue(convert.soft());
assertNotNull(element.getGenericInfo().getAttributeChildDescription("aaa"));
}
}, new Consumer<DomElement>() {
@Override
public void consume(final DomElement element) {
assertEquals("foo", ((MyElement) element).getAttr().getValue());
assertNull(element.getAnnotation(Convert.class));
}
}, new Consumer<DomElement>() {
@Override
public void consume(final DomElement element) {
assertEquals("bar", ((MyElement) element).getAttr().getValue());
assertNull(element.getAnnotation(Convert.class));
}
});
final DomFixedChildDescription description = myElement.getGenericInfo().getFixedChildDescription("yyy");
assertNotNull(description);
assertEquals(2, description.getCount());
}
public void testCollectionChildren() throws Throwable {
registerDomExtender(CollectionDomExtender.class);
final MyElement myElement = createElement("<a attr=\"xxx\"><xxx>zzz</xxx><xxx attr=\"foo\"/></a>", MyElement.class);
assertUnorderedCollection(getCustomChildren(myElement), new Consumer<DomElement>() {
@Override
public void consume(final DomElement element) {
assertEquals("foo", ((MyElement) element).getAttr().getValue());
assertNull(element.getAnnotation(Convert.class));
}
}, new Consumer<DomElement>() {
@Override
public void consume(final DomElement element) {
assertNull(((MyElement) element).getAttr().getValue());
assertNull(element.getAnnotation(Convert.class));
}
});
assertNotNull(myElement.getGenericInfo().getCollectionChildDescription("xxx"));
}
public void testCollectionAdders() throws Throwable {
registerDomExtender(CollectionDomExtender.class);
final MyElement myElement = createElement("<a attr=\"xxx\"></a>", MyElement.class);
final DomCollectionChildDescription description = myElement.getGenericInfo().getCollectionChildDescription("xxx");
final DomElement element2 = description.addValue(myElement);
final DomElement element0 = description.addValue(myElement, 0);
final DomElement element3 = description.addValue(myElement, MyConcreteElement.class);
final DomElement element1 = description.addValue(myElement, MyConcreteElement.class, 1);
assertSameElements(getCustomChildren(myElement), element0, element1, element2, element3);
}
public void testCustomChildrenAccessFromExtender() throws Throwable {
registerDomExtender(MyCustomChildrenElement.class, CustomDomExtender.class);
final MyCustomChildrenElement myElement = createElement("<a><xx/><yy/><concrete-child/><some-concrete-child/></a>", MyCustomChildrenElement.class);
final DomCollectionChildDescription description = myElement.getGenericInfo().getCollectionChildDescription("xx");
assertNotNull(description);
assertInstanceOf(assertOneElement(description.getValues(myElement)), MyDynamicElement.class);
assertInstanceOf(assertOneElement(myElement.getCustomChidren()), MyCustomElement.class);
assertInstanceOf(assertOneElement(myElement.getConcreteChildren()), MyConcreteElement.class);
assertNotNull(assertInstanceOf(myElement.getSomeConcreteChild(), MyConcreteElement.class).getXmlTag());
}
public void testFirstChildRedefinitionOnExtending() throws Exception {
registerDomExtender(MyCustomChildrenElement.class, ModestDomExtender.class);
final MyCustomChildrenElement myElement = createElement("<a><concrete-child/><concrete-child/></a>", MyCustomChildrenElement.class);
final List<MyConcreteElement> list = myElement.getConcreteChildren();
final List<MyConcreteElement> list2 = myElement.getConcreteChildren();
assertSame(list.get(0), list2.get(0));
assertSame(list.get(1), list2.get(1));
}
public static List<DomElement> getCustomChildren(final DomElement element) {
final List<DomElement> children = new ArrayList<DomElement>();
element.acceptChildren(new DomElementVisitor() {
@Override
public void visitDomElement(final DomElement element) {
if (!"attr".equals(element.getXmlElementName())) {
children.add(element);
}
}
});
return children;
}
public void registerDomExtender(Class<? extends DomExtender<MyElement>> extender) {
registerDomExtender(MyElement.class, extender);
}
public <T extends DomElement> void registerDomExtender(final Class<T> domClass, final Class<? extends DomExtender<T>> extenderClass) {
final DomExtenderEP extenderEP = new DomExtenderEP();
extenderEP.domClassName = domClass.getName();
extenderEP.extenderClassName = extenderClass.getName();
IdeaTestUtil.registerExtension(Extensions.getRootArea(), DomExtenderEP.EP_NAME, extenderEP, myTestRootDisposable);
}
public interface MyElement extends DomElement {
GenericAttributeValue<String> getAttr();
}
public interface MyCustomChildrenElement extends DomElement {
@CustomChildren List<MyCustomElement> getCustomChidren();
List<MyConcreteElement> getConcreteChildren();
MyConcreteElement getSomeConcreteChild();
}
public interface MyConcreteElement extends MyElement {
}
public interface MyCustomElement extends MyElement {
}
public interface MyDynamicElement extends MyElement {
}
public static class AttrDomExtender extends DomExtender<MyElement> {
@Override
public void registerExtensions(@NotNull final MyElement element, @NotNull final DomExtensionsRegistrar registrar) {
final String value = element.getAttr().getValue();
if (value != null) {
registrar.registerGenericAttributeValueChildExtension(new XmlName(value), Boolean.class);
}
}
}
public static class AttrDomExtender2 extends DomExtender<MyElement> {
@Override
public void registerExtensions(@NotNull final MyElement element, @NotNull final DomExtensionsRegistrar registrar) {
final String value = element.getAttr().getValue();
if (value != null) {
registrar.registerGenericAttributeValueChildExtension(new XmlName(value), StringBuffer.class).setConverter(new StringBufferConverter(), true);
registrar.registerGenericAttributeValueChildExtension(new XmlName("yyy"), StringBuffer.class).setConverter(new StringBufferConverter(), false);
}
}
}
public static class AttrDomExtender3 extends DomExtender<MyElement> {
@Override
public void registerExtensions(@NotNull final MyElement element, @NotNull final DomExtensionsRegistrar registrar) {
final String value = element.getAttr().getValue();
if (value != null) {
registrar.registerAttributeChildExtension(new XmlName(value), MyAttribute.class).putUserData(BOOL_KEY, Boolean.TRUE);
}
}
}
public static class FixedDomExtender extends DomExtender<MyElement> {
@Override
public void registerExtensions(@NotNull final MyElement element, @NotNull final DomExtensionsRegistrar registrar) {
final String value = element.getAttr().getValue();
if (value != null) {
final ParameterizedType type = new ParameterizedTypeImpl(GenericDomValue.class, StringBuffer.class);
final DomExtension extension =
registrar.registerFixedNumberChildExtension(new XmlName(value), type).setConverter(new MyStringBufferConverter(true), true);
extension.addExtender(new DomExtender<GenericDomValue<StringBuffer>>(){
@Override
public void registerExtensions(@NotNull final GenericDomValue<StringBuffer> stringBufferGenericDomValue, @NotNull final DomExtensionsRegistrar registrar) {
registrar.registerGenericAttributeValueChildExtension(new XmlName("aaa"), String.class);
}
});
((DomExtensionsRegistrarImpl)registrar).registerFixedNumberChildrenExtension(new XmlName("yyy"), MyElement.class, 2);
}
}
}
public static class CollectionDomExtender extends DomExtender<MyElement> {
@Override
public void registerExtensions(@NotNull final MyElement element, @NotNull final DomExtensionsRegistrar registrar) {
final String value = element.getAttr().getValue();
if (value != null) {
registrar.registerCollectionChildrenExtension(new XmlName(value), MyElement.class).setConverter(new MyStringBufferConverter(true), true);
}
}
}
public static class CustomDomExtender extends DomExtender<MyCustomChildrenElement> {
@Override
public void registerExtensions(@NotNull final MyCustomChildrenElement element, @NotNull final DomExtensionsRegistrar registrar) {
assertEmpty(element.getCustomChidren());
registrar.registerCollectionChildrenExtension(new XmlName("xx"), MyDynamicElement.class);
}
}
public static class ModestDomExtender extends DomExtender<MyCustomChildrenElement> {
@Override
public void registerExtensions(@NotNull final MyCustomChildrenElement element, @NotNull final DomExtensionsRegistrar registrar) {
registrar.registerCollectionChildrenExtension(new XmlName("xx"), MyDynamicElement.class);
}
}
public static class MyStringBufferConverter extends StringBufferConverter {
public MyStringBufferConverter(boolean b) {
}
}
public static interface MyAttribute extends GenericAttributeValue<Boolean> {}
}
@@ -0,0 +1,232 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.module.Module;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.xml.impl.DomFileElementImpl;
import com.intellij.util.xml.impl.MockDomFileDescription;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
/**
* @author peter
*/
public class DomFileDescriptionTest extends DomHardCoreTestCase {
private XmlFile myFooElementFile;
private XmlFile myBarElementFile;
@Override
protected void setUp() throws Exception {
super.setUp();
myFooElementFile = new WriteCommandAction<XmlFile>(getProject()) {
@Override
protected void run(Result<XmlFile> result) throws Throwable {
result.setResult((XmlFile)createFile("a.xml", "<a/>"));
}
}.execute().getResultObject();
getDomManager().registerFileDescription(new MockDomFileDescription<FooElement>(FooElement.class, "a", myFooElementFile), getTestRootDisposable());
myBarElementFile = new WriteCommandAction<XmlFile>(getProject()) {
@Override
protected void run(Result<XmlFile> result) throws Throwable {
result.setResult((XmlFile)createFile("b.xml", "<b/>"));
}
}.execute().getResultObject();
getDomManager().registerFileDescription(new DomFileDescription<BarElement>(BarElement.class, "b") {
@Override
public boolean isMyFile(@NotNull final XmlFile file, final Module module) {
return myFooElementFile.getText().contains("239");
}
@Override
public boolean isAutomaticHighlightingEnabled() {
return false;
}
}, getTestRootDisposable());
assertResultsAndClear();
}
public void testNoInitialDomnessInB() throws Throwable {
assertFalse(getDomManager().isDomFile(myBarElementFile));
assertNull(getDomManager().getFileElement(myBarElementFile));
}
public void testIsDomValue() throws Throwable {
final XmlFile file = (XmlFile)createFile("a.xml", "<b>42</b>");
getDomManager().registerFileDescription(new DomFileDescription(MyElement.class, "b") {
@Override
public boolean isMyFile(@NotNull final XmlFile file, final Module module) {
return /*super.isMyFile(file, module) && */file.getText().contains("239");
}
}, getTestRootDisposable());
assertFalse(getDomManager().isDomFile(file));
assertNull(getDomManager().getFileElement(file));
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
file.getDocument().getRootTag().getValue().setText("239");
}
}.execute();
assertTrue(getDomManager().isDomFile(file));
final DomFileElementImpl<MyElement> root = getDomManager().getFileElement(file);
assertNotNull(root);
final MyElement child = root.getRootElement().getChild();
assertTrue(root.isValid());
assertTrue(child.isValid());
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
file.getDocument().getRootTag().getValue().setText("57121");
}
}.execute();
assertFalse(getDomManager().isDomFile(file));
assertNull(getDomManager().getFileElement(file));
assertFalse(root.isValid());
assertFalse(child.isValid());
}
public void testCopyFileDescriptionFromOriginalFile() throws Throwable {
final XmlFile file = (XmlFile)createFile("a.xml", "<b>42</b>");
getDomManager().registerFileDescription(new MockDomFileDescription(MyElement.class, "b", file), getTestRootDisposable());
file.setName("b.xml");
assertTrue(getDomManager().isDomFile(file));
final XmlFile copy = (XmlFile)file.copy();
assertTrue(getDomManager().isDomFile(copy));
assertFalse(getDomManager().getFileElement(file).equals(getDomManager().getFileElement(copy)));
}
public void testDependantFileDescriptionCauseStackOverflow() throws Throwable {
final XmlFile interestingFile = (XmlFile)createFile("a.xml", "<b>42</b>");
getDomManager().registerFileDescription(new MockDomFileDescription(MyElement.class, "b", (XmlFile)null), getTestRootDisposable());
for (int i = 0; i < 239; i++) {
getDomManager().registerFileDescription(new MockDomFileDescription(AbstractElement.class, "b", (XmlFile)null) {
@Override
@NotNull
public Set getDependencyItems(final XmlFile file) {
getDomManager().isDomFile(interestingFile);
return super.getDependencyItems(file);
}
}, getTestRootDisposable());
}
getDomManager().isDomFile(interestingFile);
}
public void testCheckNamespace() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription(NamespacedElement.class, "xxx", "bar"){
@Override
protected void initializeFileDescription() {
registerNamespacePolicy("foo", "bar");
}
}, getTestRootDisposable());
final PsiFile file = createFile("xxx.xml", "<xxx/>");
assertFalse(getDomManager().isDomFile(file));
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
((XmlFile)file).getDocument().getRootTag().setAttribute("xmlns", "bar");
}
}.execute();
assertTrue(getDomManager().isDomFile(file));
}
public void testCheckDtdPublicId() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription(NamespacedElement.class, "xxx", "bar"){
@Override
protected void initializeFileDescription() {
registerNamespacePolicy("foo", "bar");
}
}, getTestRootDisposable());
final PsiFile file = createFile("xxx.xml", "<xxx/>");
assertFalse(getDomManager().isDomFile(file));
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = getDocument(file);
document.insertString(0, "<!DOCTYPE xxx PUBLIC \"bar\" \"http://java.sun.com/dtd/ejb-jar_2_0.dtd\">\n");
commitDocument(document);
}
}.execute();
assertTrue(getDomManager().isDomFile(file));
}
public void testChangeCustomDomness() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription(MyElement.class, "xxx"){
@Override
public boolean isMyFile(@NotNull final XmlFile file, @Nullable final Module module) {
return file.getText().contains("foo");
}
}, getTestRootDisposable());
final XmlFile file = (XmlFile)createFile("xxx.xml", "<xxx zzz=\"foo\"><boy/><boy/><xxx/>");
final MyElement boy = getDomManager().getFileElement(file, MyElement.class).getRootElement().getBoys().get(0);
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
file.getDocument().getRootTag().setAttribute("zzz", "bar");
}
}.execute();
assertFalse(getDomManager().isDomFile(file));
assertFalse(boy.isValid());
}
public interface AbstractElement extends GenericDomValue<String> {
GenericAttributeValue<String> getAttr();
}
public interface FooElement extends AbstractElement {
}
public interface BarElement extends AbstractElement {
}
public interface ZipElement extends AbstractElement {
}
public interface MyElement extends DomElement {
MyElement getChild();
List<MyElement> getBoys();
}
@Namespace("foo")
public interface NamespacedElement extends DomElement {
}
}
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.codeInsight.CodeInsightTestCase;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.PresentableLookupValue;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlTagValue;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.events.DomEvent;
import com.intellij.util.xml.impl.DomManagerImpl;
/**
* @author peter
*/
public abstract class DomHardCoreTestCase extends CodeInsightTestCase {
private CallRegistry<DomEvent> myCallRegistry;
@Override
protected void setUp() throws Exception {
super.setUp();
myCallRegistry = new CallRegistry<DomEvent>();
getDomManager().addDomEventListener(new DomEventListener() {
@Override
public void eventOccured(DomEvent event) {
myCallRegistry.putActual(event);
}
}, myProject);
}
protected DomManagerImpl getDomManager() {
return DomManagerImpl.getDomManager(getProject());
}
protected <T extends DomElement> T createElement(final String xml, final Class<T> aClass) throws IncorrectOperationException {
return DomTestCase.createElement(getDomManager(), xml, aClass);
}
protected void assertEventCount(final int size) {
assertEquals(myCallRegistry.toString(), size, myCallRegistry.getSize());
}
protected void putExpected(final DomEvent event) {
myCallRegistry.putExpected(event);
}
protected void assertResultsAndClear() {
myCallRegistry.assertResultsAndClear();
}
protected PsiReference assertReference(final GenericDomValue value) {
return assertReference(value, value.getXmlTag());
}
protected PsiReference assertReference(final GenericDomValue value, PsiElement resolveTo) {
final XmlTagValue tagValue = value.getXmlTag().getValue();
final TextRange textRange = tagValue.getTextRange();
final String s = value.getStringValue();
final int i = tagValue.getText().indexOf(s);
return assertReference(value, resolveTo, textRange.getStartOffset() + i + s.length());
}
protected PsiReference assertReference(final GenericDomValue value, PsiElement resolveTo, int offset) {
final XmlTag tag = value.getXmlTag();
final PsiReference reference = tag.getContainingFile().findReferenceAt(offset);
assertNotNull(reference);
assertEquals(resolveTo, reference.resolve());
return reference;
}
protected PsiReference getReference(final GenericAttributeValue value) {
final XmlAttributeValue attributeValue = value.getXmlAttributeValue();
final PsiReference reference = attributeValue.getContainingFile().findReferenceAt(attributeValue.getTextRange().getStartOffset() + 1);
assertNotNull(reference);
assertEquals(attributeValue, reference.resolve());
return reference;
}
protected void assertVariants(PsiReference reference, String... variants) {
Object[] refVariants = reference.getVariants();
assertNotNull(refVariants);
assertEquals(refVariants.length, variants.length);
int i = 0;
for (String variant : variants) {
Object refVariant = refVariants[i++];
if (refVariant instanceof LookupElement) {
assertEquals(variant, ((LookupElement)refVariant).getLookupString());
}
else if (refVariant instanceof PresentableLookupValue) {
assertEquals(variant, ((PresentableLookupValue)refVariant).getPresentation());
}
else {
assertEquals(variant, refVariant.toString());
}
}
}
protected DomReferencesTest.MyElement createElement(final String xml) throws IncorrectOperationException {
return createElement(xml, DomReferencesTest.MyElement.class);
}
}
@@ -0,0 +1,329 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.InspectionToolProvider;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
import com.intellij.lang.annotation.Annotation;
import com.intellij.mock.MockInspectionProfile;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiType;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.testFramework.MockSchemesManagerFactory;
import com.intellij.util.xml.highlighting.*;
import com.intellij.util.xml.impl.DefaultDomAnnotator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Type;
import java.util.ArrayList;
/**
* @author peter
*/
public class DomHighlightingLiteTest extends DomTestCase {
private DomElementAnnotationsManagerImpl myAnnotationsManager;
private MockDomFileElement myElement;
private MockInspectionProfile myInspectionProfile;
@Override
protected void setUp() throws Exception {
super.setUp();
final InspectionToolRegistrar registrar = new InspectionToolRegistrar(SearchableOptionsRegistrar.getInstance());
registrar.registerTools(new InspectionToolProvider[0]);
final InspectionProfileManager inspectionProfileManager = new InspectionProfileManager(registrar, new MockSchemesManagerFactory());
myInspectionProfile = new MockInspectionProfile();
myAnnotationsManager = new DomElementAnnotationsManagerImpl(getProject()) {
@Override
protected InspectionProfile getInspectionProfile(final DomFileElement fileElement) {
return myInspectionProfile;
}
};
final XmlFile file = createXmlFile("<a/>");
final MockDomElement rootElement = new MockDomElement() {
@Override
@Nullable
public XmlElement getXmlElement() {
return getXmlTag();
}
@Override
public XmlTag getXmlTag() {
return file.getDocument().getRootTag();
}
@Override
public Type getDomElementType() {
return DomElement.class;
}
};
myElement = new MockDomFileElement() {
@Override
@Nullable
public XmlElement getXmlElement() {
return file;
}
@Override
@NotNull
public XmlFile getFile() {
return file;
}
@Override
public DomElement getParent() {
return null;
}
@Override
@NotNull
public DomElement getRootElement() {
return rootElement;
}
@Override
public Class getRootElementClass() {
return DomElement.class;
}
@Override
public boolean isValid() {
return true;
}
};
}
public void testEmptyProblemDescriptorInTheBeginning() throws Throwable {
assertEmptyHolder(myAnnotationsManager.getProblemHolder(myElement));
}
private static void assertEmptyHolder(final DomElementsProblemsHolder holder) {
assertFalse(holder instanceof DomElementsProblemsHolderImpl);
assertEmpty(holder.getAllProblems());
}
public void testProblemDescriptorIsCreated() throws Throwable {
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
final DomElementsProblemsHolderImpl holder = assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement));
assertEmpty(holder.getAllProblems());
assertEmpty(holder.getAllProblems(new MyDomElementsInspection()));
}
private static DomElementsProblemsHolderImpl assertNotEmptyHolder(final DomElementsProblemsHolder holder1) {
return assertInstanceOf(holder1, DomElementsProblemsHolderImpl.class);
}
public void testInspectionMarkedAsPassedAfterAppend() throws Throwable {
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
final DomElementsProblemsHolderImpl holder = (DomElementsProblemsHolderImpl)myAnnotationsManager.getProblemHolder(myElement);
assertTrue(holder.isInspectionCompleted(MyDomElementsInspection.class));
assertFalse(holder.isInspectionCompleted(DomElementsInspection.class));
}
public void testHolderRecreationAfterChange() throws Throwable {
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
assertTrue(DomElementAnnotationsManagerImpl.isHolderUpToDate(myElement));
final DomElementsProblemsHolder holder = myAnnotationsManager.getProblemHolder(myElement);
myElement.incModificationCount();
assertFalse(DomElementAnnotationsManagerImpl.isHolderUpToDate(myElement));
assertSame(holder, myAnnotationsManager.getProblemHolder(myElement));
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MyDomElementsInspection.class);
assertNotSame(holder, assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement)));
}
public void testMockDomInspection() throws Throwable {
myElement.setFileDescription(new MyNonHighlightingDomFileDescription());
assertInstanceOf(myAnnotationsManager.getMockInspection(myElement), MockDomInspection.class);
}
public void testMockAnnotatingDomInspection() throws Throwable {
myElement.setFileDescription(new DomFileDescription(DomElement.class, "a"));
assertInstanceOf(myAnnotationsManager.getMockInspection(myElement), MockAnnotatingDomInspection.class);
}
public void testNoMockInspection() throws Throwable {
myElement.setFileDescription(new MyNonHighlightingDomFileDescription());
myInspectionProfile.setInspectionTools(new MyDomElementsInspection());
assertNull(myAnnotationsManager.getMockInspection(myElement));
}
public void testDefaultAnnotator() throws Throwable {
final DefaultDomAnnotator annotator = new DefaultDomAnnotator() {
@Override
protected DomElementAnnotationsManagerImpl getAnnotationsManager(final DomElement element) {
return myAnnotationsManager;
}
};
final StringBuilder s = new StringBuilder();
final ArrayList<Annotation> toFill = new ArrayList<Annotation>();
final MyDomElementsInspection inspection = new MyDomElementsInspection() {
@Override
public void checkFileElement(final DomFileElement fileElement, final DomElementAnnotationHolder holder) {
s.append("visited");
}
};
annotator.runInspection(inspection, myElement, toFill);
assertEquals("visited", s.toString());
final DomElementsProblemsHolderImpl holder = assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement));
assertEmpty(toFill);
annotator.runInspection(inspection, myElement, toFill);
assertEquals("visited", s.toString());
assertSame(holder, assertNotEmptyHolder(myAnnotationsManager.getProblemHolder(myElement)));
assertEmpty(toFill);
}
public void testHighlightStatus_MockDomInspection() throws Throwable {
myElement.setFileDescription(new MyNonHighlightingDomFileDescription());
assertEquals(DomHighlightStatus.NONE, myAnnotationsManager.getHighlightStatus(myElement));
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockDomInspection.class);
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
}
public void testHighlightStatus_MockAnnotatingDomInspection() throws Throwable {
myElement.setFileDescription(new DomFileDescription(DomElement.class, "a"));
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockAnnotatingDomInspection.class);
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
}
public void testHighlightStatus_OtherInspections() throws Throwable {
myElement.setFileDescription(new DomFileDescription(DomElement.class, "a"));
final MyDomElementsInspection inspection = new MyDomElementsInspection() {
@Override
public ProblemDescriptor[] checkFile(@NotNull final PsiFile file, @NotNull final InspectionManager manager,
final boolean isOnTheFly) {
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), this.getClass());
return new ProblemDescriptor[0];
}
@Override
public void checkFileElement(final DomFileElement fileElement, final DomElementAnnotationHolder holder) {
}
};
HighlightDisplayKey.register(inspection.getShortName());
myInspectionProfile.setInspectionTools(inspection);
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockAnnotatingDomInspection.class);
assertEquals(DomHighlightStatus.ANNOTATORS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), inspection.getClass());
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
}
public void testHighlightStatus_OtherInspections2() throws Throwable {
myElement.setFileDescription(new DomFileDescription(DomElement.class, "a"));
final MyDomElementsInspection inspection = new MyDomElementsInspection() {
@Override
public ProblemDescriptor[] checkFile(@NotNull final PsiFile file, @NotNull final InspectionManager manager,
final boolean isOnTheFly) {
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), this.getClass());
return new ProblemDescriptor[0];
}
@Override
public void checkFileElement(final DomFileElement fileElement, final DomElementAnnotationHolder holder) {
}
};
HighlightDisplayKey.register(inspection.getShortName());
myInspectionProfile.setInspectionTools(inspection);
myInspectionProfile.setEnabled(inspection, false);
myAnnotationsManager.appendProblems(myElement, new DomElementAnnotationHolderImpl(), MockAnnotatingDomInspection.class);
assertEquals(DomHighlightStatus.INSPECTIONS_FINISHED, myAnnotationsManager.getHighlightStatus(myElement));
}
public void testRequiredAttributeWithoutAttributeValue() throws Throwable {
final MyElement element = createElement("<a id />", MyElement.class);
new MyBasicDomElementsInspection().checkDomElement(element.getId(), new DomElementAnnotationHolderImpl(), DomHighlightingHelperImpl.INSTANCE);
}
private class MyDomElementsInspection extends DomElementsInspection {
public MyDomElementsInspection() {
super(DomElement.class);
}
@Override
@NotNull
public String getGroupDisplayName() {
throw new UnsupportedOperationException("Method getGroupDisplayName is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public String getDisplayName() {
throw new UnsupportedOperationException("Method getDisplayName is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public String getShortName() {
return "xxx";
}
}
private class MyBasicDomElementsInspection extends BasicDomElementsInspection {
public MyBasicDomElementsInspection() {
super(DomElement.class);
}
@Override
@NotNull
public String getGroupDisplayName() {
throw new UnsupportedOperationException("Method getGroupDisplayName is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public String getDisplayName() {
throw new UnsupportedOperationException("Method getDisplayName is not yet implemented in " + getClass().getName());
}
@Override
protected void checkDomElement(final DomElement element, final DomElementAnnotationHolder holder, final DomHighlightingHelper helper) {
super.checkDomElement(element, holder, helper);
}
@Override
@NotNull
public String getShortName() {
return "xxx";
}
}
private static class MyNonHighlightingDomFileDescription extends DomFileDescription {
public MyNonHighlightingDomFileDescription() {
super(DomElement.class, "a");
}
@Override
public boolean isAutomaticHighlightingEnabled() {
return false;
}
}
public interface MyElement extends DomElement {
@Convert(soft=true, value=JvmPsiTypeConverter.class)
@Required GenericAttributeValue<PsiType> getId();
}
}
@@ -0,0 +1,229 @@
/*
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.util.xml;
import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.PomTargetPsiElement;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.testFramework.Timings;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import com.intellij.util.Consumer;
import com.intellij.util.xml.impl.DomFileElementImpl;
import com.intellij.util.xml.impl.DomManagerImpl;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author peter
*/
public class DomIncludesTest extends JavaCodeInsightFixtureTestCase {
public void testGetChildrenHonorsIncludes() throws Throwable {
final MyElement rootElement = createDomFile("a.xml", "<root xmlns:xi=\"http://www.w3.org/2001/XInclude\">" +
"<xi:include href=\"b.xml\" xpointer=\"xpointer(/xxx/*)\"/>" +
"<child xxx=\"a\"/>" +
"</root>");
createFile("b.xml", "<xxx><child xxx=\"b\"/></xxx>");
final List<DomIncludesTest.Child> children = rootElement.getChildren();
Consumer<MyElement> consumer1 = new Consumer<MyElement>() {
@Override
public void consume(final MyElement element) {
assertFalse(element.getXmlElement().isPhysical());
assertEquals(rootElement, element.getParent());
assertEquals(DomUtil.getFileElement(rootElement), DomUtil.getFileElement(element));
assertEquals("b", element.getXxx().getValue());
}
};
Consumer<MyElement> consumer2 = new Consumer<MyElement>() {
@Override
public void consume(final MyElement element) {
assertTrue(element.getXmlElement().isPhysical());
assertEquals(rootElement, element.getParent());
assertEquals(DomUtil.getFileElement(rootElement), DomUtil.getFileElement(element));
assertEquals("a", element.getXxx().getValue());
}
};
assertOrderedCollection(children, new Consumer[] { consumer1, consumer2 });
}
public void testNamespaces() throws Throwable {
final MyElement rootElement = createDomFile("a.xml", "<root xmlns:xi=\"http://www.w3.org/2001/XInclude\" xmlns:foo=\"foo\">" +
"<xi:include href=\"b.xml\" xpointer=\"xpointer(/xxx/*)\"/>" +
"<foo:boy xxx=\"a\"/>" +
"</root>");
DomUtil.getFileElement(rootElement).getFileDescription().registerNamespacePolicy("foo", "foo");
createFile("b.xml", "<xxx xmlns:foo=\"foo\"><foo:boy xxx=\"b\"/></xxx>");
final List<Boy> children = rootElement.getBoys();
assertOrderedCollection(children, new Consumer<Boy>() {
@Override
public void consume(final Boy element) {
assertFalse(element.getXmlElement().isPhysical());
assertEquals(rootElement, element.getParent());
assertEquals(DomUtil.getFileElement(rootElement), DomUtil.getFileElement(element));
assertEquals("b", element.getXxx().getValue());
}
}, new Consumer<Boy>() {
@Override
public void consume(final Boy element) {
assertTrue(element.getXmlElement().isPhysical());
assertEquals(rootElement, element.getParent());
assertEquals(DomUtil.getFileElement(rootElement), DomUtil.getFileElement(element));
assertEquals("a", element.getXxx().getValue());
}
});
}
public void testEqualsWithMultiThreadedIncludes() throws Throwable {
final MyElement rootElement = createDomFile("a.xml", "<root xmlns:xi=\"http://www.w3.org/2001/XInclude\">" +
"<xi:include href=\"b.xml\" xpointer=\"xpointer(/xxx/*)\"/>" +
"</root>");
final PsiFile fileB = createFile("b.xml",
"<xxx><boy/><xi:include href=\"c.xml\" xpointer=\"xpointer(/xxx/*)\"/><child/><xi:include href=\"c.xml\" xpointer=\"xpointer(/xxx/*)\"/></xxx>");
final PsiFile fileC = createFile("c.xml",
"<xxx><child/><xi:include href=\"d.xml\" xpointer=\"xpointer(/xxx/*)\"/><boy/><xi:include href=\"d.xml\" xpointer=\"xpointer(/xxx/*)\"/></xxx>");
final PsiFile fileD = createFile("d.xml",
"<xxx><boy/><xi:include href=\"e.xml\" xpointer=\"xpointer(/xxx/*)\"/><child/><xi:include href=\"e.xml\" xpointer=\"xpointer(/xxx/*)\"/></xxx>");
final PsiFile fileE = createFile("e.xml",
"<xxx><boy/><child/><boy/><child/><boy/><child/><boy/><child/><boy/><child/><boy/><child/></xxx>");
final int threadCount = 100;
final int iterationCount = Timings.adjustAccordingToMySpeed(800, true);
System.out.println("iterationCount = " + iterationCount);
final CountDownLatch finished = new CountDownLatch(threadCount);
final AtomicReference<Exception> ex = new AtomicReference<Exception>();
Thread[] threads = new Thread[threadCount];
for (int j = 0; j < threadCount; j++) {
Thread thread = new Thread() {
@Override
public void run() {
for (int k = 0; k < iterationCount; k++) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
try {
final List<Boy> boys = rootElement.getBoys();
Thread.yield();
final List<Child> children = rootElement.getChildren();
Thread.yield();
assertEquals(boys, rootElement.getBoys());
assertEquals(children, rootElement.getChildren());
}
catch (Exception e) {
ex.set(e);
}
finally {
finished.countDown();
}
}
});
Thread.yield();
}
}
};
threads[j] = thread;
thread.start();
}
for (int i = 0; i < iterationCount; i++) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
fileB.getViewProvider().getDocument().insertString(0, " ");
fileD.getViewProvider().getDocument().insertString(0, " ");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); //clear xinclude caches
}
});
Thread.sleep(10);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
fileC.getViewProvider().getDocument().insertString(0, " ");
fileE.getViewProvider().getDocument().insertString(0, " ");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); //clear xinclude caches
}
});
Thread.sleep(10);
}
finished.await();
for (Thread thread : threads) {
thread.join();
}
final Exception exception = ex.get();
if (exception != null) {
throw exception;
}
}
public void testNavigationToIncluded() throws Throwable {
final MyElement rootElement = createDomFile("a.xml", "<root xmlns:xi=\"http://www.w3.org/2001/XInclude\">" +
"<xi:include href=\"b.xml\" xpointer=\"xpointer(/xxx/*)\"/>" +
"<child ref=\"b\"/>" +
"</root>");
final XmlFile includedFile = (XmlFile) createFile("b.xml", "<xxx><child xxx=\"b\"/></xxx>");
final List<Child> children = rootElement.getChildren();
final MyElement domTarget = children.get(0);
final GenericAttributeValue<Child> ref = children.get(1).getRef();
final MyElement value = ref.getValue();
assertEquals(domTarget, value);
myFixture.configureFromTempProjectFile("a.xml");
final int offset = ref.getXmlAttributeValue().getTextRange().getStartOffset() + 1;
myFixture.getEditor().getCaretModel().moveToOffset(offset);
final PsiElement target = GotoDeclarationAction.findTargetElement(getProject(), myFixture.getEditor(), offset);
PsiElement element = ((DomTarget)((PomTargetPsiElement)target).getTarget()).getNavigationElement();
// assertSame(PomService.convertToPsi(DomTarget.getTarget(domTarget)), target);
assertSame(includedFile.getDocument().getRootTag().getSubTags()[0].getAttributes()[0].getValueElement(), element);
}
private MyElement createDomFile(final String fileName, final String fileText) throws IOException {
final XmlFile xmlFile = (XmlFile) createFile(fileName, fileText);
final DomFileElementImpl<MyElement> element = getDomManager().getFileElement(xmlFile, MyElement.class, xmlFile.getDocument().getRootTag().getName());
return element.getRootElement();
}
private PsiFile createFile(final String fileName, final String fileText) throws IOException {
final VirtualFile file = myFixture.getTempDirFixture().createFile(fileName);
VfsUtil.saveText(file, fileText);
return getPsiManager().findFile(file);
}
private DomManagerImpl getDomManager() {
return DomManagerImpl.getDomManager(getProject());
}
public interface MyElement extends DomElement {
List<Child> getChildren();
List<Boy> getBoys();
@NameValue
GenericAttributeValue<String> getXxx();
GenericAttributeValue<Child> getRef();
}
@Namespace("foo")
public interface Boy extends MyElement {
}
public interface Child extends MyElement {
}
}
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.command.WriteCommandAction;
import java.util.*;
/**
* @author peter
*/
public class DomModelMergingTest extends DomTestCase{
private ModelMerger myMerger;
@Override
protected void setUp() throws Exception {
super.setUp();
myMerger = new ModelMergerImpl();
}
public void testVisitor() throws Throwable {
final MyElement element1 = createElement("", MyElement.class);
final MyElement foo1 = element1.getFoo();
final MyElement bar1 = element1.addBar();
final MyElement bar2 = element1.addBar();
final MyElement element2 = createElement("", MyElement.class);
final MyElement foo2 = element2.getFoo();
final MyElement bar3 = element2.addBar();
final MyElement element = myMerger.mergeModels(MyElement.class, element1, element2);
final MyElement foo = element.getFoo();
assertEquals(foo, myMerger.mergeModels(MyElement.class, foo1, foo2));
final int[] count = new int[]{0};
element.accept(new DomElementVisitor() {
@Override
public void visitDomElement(DomElement _element) {
count[0]++;
assertEquals(_element, element);
}
});
assertEquals(1, count[0]);
count[0] = 0;
final Set<DomElement> result = new HashSet<DomElement>();
element.acceptChildren(new DomElementVisitor() {
@Override
public void visitDomElement(DomElement element) {
count[0]++;
result.add(element);
}
});
assertEquals(new HashSet(Arrays.asList(foo, bar1, bar2, bar3)).toString().replace(",", "\n"), result.toString().replace(",", "\n"));
assertEquals(new HashSet(Arrays.asList(foo, bar1, bar2, bar3)), result);
assertEquals(4, count[0]);
}
public void testValidity() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final MyElement element = createElement("", MyElement.class);
final MyElement bar1 = element.addBar();
final MyElement bar2 = element.addBar();
final MyElement merged = myMerger.mergeModels(MyElement.class, bar1, bar2);
assertTrue(merged.isValid());
bar2.undefine();
assertFalse(merged.isValid());
}
}.execute().throwException();
}
public interface MyElement extends DomElement {
MyElement getFoo();
List<MyElement> getBars();
MyElement addBar();
}
}
@@ -0,0 +1,354 @@
/*
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.util.xml;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.impl.DomFileElementImpl;
import com.intellij.util.xml.reflect.DomGenericInfo;
import java.util.List;
/**
* @author peter
*/
public class DomNamespacesTest extends DomTestCase {
public void testUseExistingNamespace() throws Throwable {
final MyElement element = createElement("<a xmlns=\"foo\" xmlns:bar=\"bar\"/>", MyElement.class);
registerNamespacePolicies(element);
final XmlTag fooChildTag = element.getFooChild().ensureTagExists();
assertEquals("foo-child", fooChildTag.getName());
assertEquals("foo", fooChildTag.getNamespace());
assertEquals("", fooChildTag.getNamespacePrefix());
final XmlTag barChildTag = element.getBarChild().ensureTagExists();
assertEquals("bar:bar-child", barChildTag.getName());
assertEquals("bar", barChildTag.getNamespace());
assertEquals("bar", barChildTag.getNamespacePrefix());
}
public void testDefineNewNamespace() throws Throwable {
final MyElement element = createElement("<a/>", MyElement.class);
registerNamespacePolicies(element);
final XmlTag fooChildTag = element.getFooChild().ensureTagExists();
assertEquals("foo-child", fooChildTag.getName());
assertEquals("foo", fooChildTag.getNamespace());
assertEquals("", fooChildTag.getNamespacePrefix());
assertEquals("foo", fooChildTag.getAttributeValue("xmlns"));
final XmlTag barChildTag = element.getBarChild().ensureTagExists();
assertEquals("bar-child", barChildTag.getName());
assertEquals("bar", barChildTag.getNamespace());
assertEquals("", barChildTag.getNamespacePrefix());
assertEquals("bar", barChildTag.getAttributeValue("xmlns"));
}
public void testCollectionChildNamespace() throws Throwable {
final MyElement element = createElement("<a xmlns:foo=\"foo\"/>", MyElement.class);
registerNamespacePolicies(element);
final XmlTag fooChildTag = element.addFooElement().getXmlTag();
assertEquals("foo:foo-element", fooChildTag.getName());
assertEquals("foo", fooChildTag.getNamespace());
assertEquals("foo", fooChildTag.getNamespacePrefix());
assertNull(fooChildTag.getAttributeValue("xmlns"));
}
public void testNoNamespaceForFixedChild() throws Throwable {
final MyElement element = createElement("<a xmlns:foo=\"foo\"/>", MyElement.class);
registerNamespacePolicies(element);
final XmlTag childTag = element.getSomeChild().ensureTagExists();
assertEquals("some-child", childTag.getName());
assertEquals("", childTag.getNamespace());
assertEquals("", childTag.getNamespacePrefix());
assertNull(childTag.getAttributeValue("xmlns"));
}
public void testNoNamespaceForCollectionChild() throws Throwable {
final MyElement element = createElement("<a xmlns:foo=\"foo\"/>", MyElement.class);
registerNamespacePolicies(element);
final XmlTag childTag = element.addChild().getXmlTag();
assertEquals("child", childTag.getName());
assertEquals("", childTag.getNamespace());
assertEquals("", childTag.getNamespacePrefix());
assertNull(childTag.getAttributeValue("xmlns"));
}
public void testNamespaceEqualToParent() throws Throwable {
final MyElement element = createElement("<a xmlns=\"foo\"/>", MyElement.class);
registerNamespacePolicies(element);
final XmlTag childTag = element.addChild().getXmlTag();
assertEquals("child", childTag.getName());
assertEquals("foo", childTag.getNamespace());
assertEquals("", childTag.getNamespacePrefix());
assertNull(childTag.getAttributeValue("xmlns"));
}
public void testNamespaceEqualToParent2() throws Throwable {
final MyElement root = createElement("<a xmlns=\"foo\"/>", MyElement.class);
registerNamespacePolicies(root);
final MyFooElement element = root.addFooElement();
final MyElement child = element.addChild();
final XmlTag childTag = child.getXmlTag();
assertEquals("child", childTag.getName());
assertEquals("foo", childTag.getNamespace());
assertEquals("", childTag.getNamespacePrefix());
assertNull(childTag.getAttributeValue("xmlns"));
assertEquals("foo", element.getXmlElementNamespaceKey());
assertNull(child.getXmlElementNamespaceKey());
}
public void testHardcodedNamespacePrefix() throws Throwable {
final XmlFile xmlFile = createXmlFile("<a xmlns:sys=\"\"/>");
final MyElement element = getDomManager().getFileElement(xmlFile, MyElement.class, "a").getRootElement();
final MyElement hardcodedElement = element.getHardcodedElement();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
hardcodedElement.ensureTagExists();
}
}.execute();
assertTrue(element.isValid());
assertTrue(hardcodedElement.isValid());
assertNotNull(hardcodedElement.getXmlElement());
assertEquals("<sys:aaa/>", hardcodedElement.getXmlElement().getText());
assertEquals("sys:aaa", hardcodedElement.getXmlTag().getName());
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
hardcodedElement.getHardcodedElement().getHardcodedElement().ensureTagExists();
}
}.execute();
assertTrue(element.isValid());
assertTrue(hardcodedElement.isValid());
assertNotNull(hardcodedElement.getXmlElement());
assertEquals("sys:aaa", hardcodedElement.getHardcodedElement().getHardcodedElement().getXmlTag().getName());
assertEquals(1, element.getXmlTag().getSubTags().length);
}
public void testAutoChooseNamespaceIfPresent() throws Throwable {
final MyElement root = createElement("<a xmlns=\"foo\"/>", MyElement.class);
getDomManager().getDomFileDescription(root.getXmlElement()).registerNamespacePolicy("foo", "bar", "foo");
final XmlTag fooChildTag = root.getFooChild().ensureTagExists();
assertEquals("foo-child", fooChildTag.getName());
assertEquals("foo", fooChildTag.getNamespace());
assertEquals("", fooChildTag.getNamespacePrefix());
assertEquals(0, fooChildTag.getAttributes().length);
}
public void testNonemptyRootTagPrefix() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription<MyFooElement>(MyFooElement.class, "a", "foons") {
@Override
protected void initializeFileDescription() {
super.initializeFileDescription();
registerNamespacePolicy("foo", "foons");
}
}, getTestRootDisposable());
final XmlFile psiFile = createXmlFile("<f:a xmlns:f=\"foons\"/>");
final DomFileElementImpl<MyFooElement> element = getDomManager().getFileElement(psiFile, MyFooElement.class);
assertNotNull(element);
final MyFooElement root = element.getRootElement();
assertNotNull(root);
assertSame(psiFile.getDocument().getRootTag(), root.getXmlElement());
}
public void testSpringAopLike() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription<MyBeans>(MyBeans.class, "beans", "beans", "aop") {
@Override
protected void initializeFileDescription() {
super.initializeFileDescription();
registerNamespacePolicy("beans", "beans");
registerNamespacePolicy("aop", "aop");
}
}, getTestRootDisposable());
final XmlFile psiFile = createXmlFile("<beans xmlns=\"beans\" xmlns:aop=\"aop\">" +
"<aop:config>" +
"<aop:pointcut/>" +
"</aop:config>" +
"</beans>");
final MyBeans beans = getDomManager().getFileElement(psiFile, MyBeans.class).getRootElement();
final DomElement pointcut =
getDomManager().getDomElement(beans.getXmlTag().findFirstSubTag("aop:config").findFirstSubTag("aop:pointcut"));
assertNotNull(pointcut);
final MyAopConfig aopConfig = beans.getConfig();
assertEquals(assertOneElement(aopConfig.getPointcuts()), pointcut);
}
public void testSpringUtilLike() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription<MyBeans>(MyBeans.class, "beans", "beans", "util") {
@Override
protected void initializeFileDescription() {
super.initializeFileDescription();
registerNamespacePolicy("beans", "beans");
registerNamespacePolicy("util", "util");
}
}, getTestRootDisposable());
final XmlFile psiFile = createXmlFile("<beans xmlns=\"beans\" xmlns:util=\"util\">" +
"<util:list>" +
"<ref>aaa</ref>" +
"<util:child>bbb</util:child>" +
"</util:list></beans>");
final MyList listOrSet = assertInstanceOf(getDomManager().getFileElement(psiFile, MyBeans.class).getRootElement().getList(), MyList.class);
assertNotNull(listOrSet.getXmlTag());
final XmlTag listTag = psiFile.getDocument().getRootTag().findFirstSubTag("util:list");
assertNotNull(getDomManager().getDomElement(listTag.findFirstSubTag("ref")));
assertNotNull(getDomManager().getDomElement(listTag.findFirstSubTag("util:child")));
assertEquals("aaa", listOrSet.getRef().getValue());
assertEquals("bbb", listOrSet.getChild().getValue());
}
private void registerNamespacePolicies(final MyElement element) {
registerNamespacePolicies(element, "foo", "bar");
}
private void registerNamespacePolicies(final MyElement element, final String foo, final String bar) {
final DomFileDescription description = getDomManager().getDomFileDescription(element.getXmlElement());
description.registerNamespacePolicy("foo", foo);
description.registerNamespacePolicy("bar", bar);
}
public void testFindChildDescriptionWithoutNamespace() throws Throwable {
final DomGenericInfo info = getDomManager().getGenericInfo(MyListOrSet.class);
assertNotNull(info.getAttributeChildDescription("attr"));
assertNotNull(info.getAttributeChildDescription("attr").getType());
assertNotNull(info.getCollectionChildDescription("child"));
assertNotNull(info.getCollectionChildDescription("child").getType());
assertNotNull(info.getFixedChildDescription("ref"));
assertNotNull(info.getFixedChildDescription("ref").getType());
}
public void testCopyFromHonorsNamespaces() throws Throwable {
final MyElement element = createElement("<a xmlns=\"foo\" xmlns:bar=\"bar\"/>", MyElement.class);
registerNamespacePolicies(element);
final MyElement element2 = createElement("<f:a xmlns:f=\"foo1\" xmlns:b=\"bar1\" xmlns=\"foo1\">" +
"<foo-child/>" +
"<b:bar-child/>" +
"<f:some-child/>" +
"<f:foo-element attr-2=\"239\" attr=\"42\"/>" +
"<f:foo-element/>" +
"<f:bool/>" +
"<sys:aaa/>" +
"</f:a>", MyElement.class);
registerNamespacePolicies(element2, "foo1", "bar1");
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
element.copyFrom(element2);
}
}.execute();
assertEquals("<a xmlns=\"foo\" xmlns:bar=\"bar\">" +
"<bar:bar-child/>" +
"<bool/>" +
"<foo-child/>" +
"<some-child/>" +
"<sys:aaa/>" +
"<foo-element attr=\"42\" attr-2=\"239\"/>" +
"<foo-element/>" +
"</a>",
element.getXmlTag().getText());
}
public void testAttributeWithAnotherNamespace() throws Throwable {
final MyElement element = createElement("<a xmlns=\"foo\" xmlns:bar=\"bar\"><foo-child bar:my-attribute=\"xxx\"/></a>", MyElement.class);
registerNamespacePolicies(element);
final MyFooElement fooElement = element.getFooChild();
final MyAttribute myAttribute = fooElement.getMyAttribute();
assertNotNull(myAttribute.getXmlAttribute());
assertEquals("xxx", myAttribute.getStringValue());
}
public interface MyElement extends DomElement {
MyFooElement getFooChild();
MyBarElement getBarChild();
MyElement getSomeChild();
List<MyFooElement> getFooElements();
MyFooElement addFooElement();
List<MyElement> getChildren();
MyElement addChild();
GenericAttributeValue<String> getAttr();
GenericAttributeValue<String> getAttr2();
@SubTag(indicator = true)
GenericDomValue<Boolean> getBool();
@SubTag("sys:aaa")
MyElement getHardcodedElement();
}
@Namespace("foo")
public interface MyFooElement extends MyElement {
MyAttribute getMyAttribute();
}
@Namespace("bar")
public interface MyBarElement extends MyElement {
}
@Namespace("bar")
public interface MyAttribute extends GenericAttributeValue<String> {
}
@Namespace("beans")
public interface MyBeans extends DomElement {
MyAopConfig getConfig();
MyList getList();
}
@Namespace("aop")
public interface MyAopConfig extends DomElement {
List<MySpringPointcut> getPointcuts();
}
@Namespace("aop")
public interface MySpringPointcut extends DomElement {
}
@Namespace("beans")
public interface MyListOrSet extends DomElement {
GenericDomValue<String> getRef();
List<GenericDomValue<String>> getChildren();
GenericAttributeValue<String> getAttr();
}
@Namespace("util")
public interface MyList extends MyListOrSet {
GenericDomValue<String> getChild();
}
}
@@ -0,0 +1,208 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.meta.MetaRegistry;
import com.intellij.psi.xml.XmlFile;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.ThrowableRunnable;
import com.intellij.xml.impl.dtd.XmlNSDescriptorImpl;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.util.List;
/**
* @author peter
*/
public class DomPerformanceTest extends DomHardCoreTestCase{
public void testVisitorPerformance() throws Throwable {
final MyElement element = createElement("<!DOCTYPE faces-config PUBLIC\n" +
" \"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN\"\n" +
" \"http://java.sun.com/dtd/web-facesconfig_1_1.dtd\">", MyElement.class);
MetaRegistry.bindDataToElement(DomUtil.getFile(element).getDocument(), new XmlNSDescriptorImpl());
final MyElement child = element.addChildElement();
child.getAttr().setValue("239");
child.getChild239().getAttr().setValue("42");
child.getChild().getAttr().setValue("42xx");
child.getChild2().getAttr().setValue("42yy");
child.addChildElement().getChild().addFooChild().getAttr().setValue("xxx");
child.addChildElement().addFooChild().getAttr().setValue("yyy");
child.addChildElement().addFooChild().addBarChild().addBarChild().addChildElement().getChild().getAttr().setValue("xxx");
child.addChildElement().addBarComposite().setValue("ssss");
child.addBarChild().getChild2().getAttr().setValue("234178956023");
long start = System.currentTimeMillis();
for (int i = 0; i < 239; i++) {
element.addChildElement().copyFrom(child);
}
IdeaTestUtil.assertTiming("", 30000, System.currentTimeMillis() - start);
final MyElement newElement = createElement(DomUtil.getFile(element).getText(), MyElement.class);
//ProfilingUtil.startCPUProfiling();
PlatformTestUtil.startPerformanceTest(getTestName(false), 200, new ThrowableRunnable() {
@Override
public void run() throws Exception {
newElement.acceptChildren(new DomElementVisitor() {
@Override
public void visitDomElement(DomElement element) {
element.acceptChildren(this);
}
});
/*
try {
ProfilingUtil.captureCPUSnapshot("aaa");
}
catch (Exception e) {
e.printStackTrace();
}
*/
}
}).cpuBound().assertTiming();
}
public void testShouldntParseNonDomFiles() throws Throwable {
for (int i = 0; i < 420; i++) {
getDomManager().registerFileDescription(new DomFileDescription(MyChildElement.class, "foo") {
@Override
public boolean isMyFile(@NotNull final XmlFile file, final Module module) {
fail();
return super.isMyFile(file, module);
}
}, getTestRootDisposable());
getDomManager().registerFileDescription(new DomFileDescription(MyChildElement.class, "bar") {
@Override
public boolean isMyFile(@NotNull final XmlFile file, final Module module) {
fail();
return super.isMyFile(file, module);
}
}, getTestRootDisposable());
}
getDomManager().createMockElement(MyChildElement.class, null, true);
@NotNull final VirtualFile virtualFile = createFile("a.xml", "").getVirtualFile();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(virtualFile.getOutputStream(this)));
writer.write("<root>\n");
for (int i = 0; i < 23942; i++) {
writer.write("<bar/>\n");
}
writer.write("</root>");
writer.close();
virtualFile.refresh(false, false);
}
}.execute();
((PsiManagerImpl)getPsiManager()).getFileManager().cleanupForNextTest();
final XmlFile file = (XmlFile)getPsiManager().findFile(virtualFile);
assertFalse(file.getNode().isParsed());
assertTrue(StringUtil.isNotEmpty(file.getText()));
PlatformTestUtil.startPerformanceTest("", 100, new ThrowableRunnable() {
@Override
public void run() throws Exception {
assertNull(getDomManager().getFileElement(file));
}
}).cpuBound().assertTiming();
assertFalse(file.getNode().isParsed());
}
public void testDontParseNamespacedDomFiles() throws Exception {
getDomManager().registerFileDescription(new DomFileDescription(MyNamespacedElement.class, "foo") {
@Override
protected void initializeFileDescription() {
registerNamespacePolicy("project", "project");
}
}, getTestRootDisposable());
XmlFile file = (XmlFile)createFile("a.xml", "<foo xmlns=\"project\"/>");
assertFalse(file.getNode().isParsed());
assertNotNull(DomManager.getDomManager(getProject()).getFileElement(file, MyNamespacedElement.class));
assertFalse(file.getNode().isParsed());
file = (XmlFile)createFile("a.xml", "<foo xmlns=\"project2\"/>");
assertFalse(file.getNode().isParsed());
assertNull(DomManager.getDomManager(getProject()).getFileElement(file, MyNamespacedElement.class));
assertFalse(file.getNode().isParsed());
}
@Namespace("project")
public interface MyNamespacedElement extends DomElement {
}
public interface MyChildElement extends DomElement {
@Attribute
@Required
GenericAttributeValue<String> getAttr();
List<MyFooConcreteElement> getFooChildren();
MyFooConcreteElement addFooChild();
}
public interface MyElement extends DomElement {
@Attribute
@Required
GenericAttributeValue<String> getAttr();
String getValue();
void setValue(String s);
MyChildElement getChild();
@SubTag(value = "child", index = 1)
MyChildElement getChild2();
MyChildElement getChild239();
List<MyElement> getChildElements();
MyElement addChildElement();
List<MyAbstractElement> getAbstractElements();
@SubTagList("abstract-element")
MyBarConcreteElement addBarChild();
@SubTagList("abstract-element")
MyFooConcreteElement addFooChild();
@SubTagsList({"child-element", "abstract-element"})
List<MyElement> getCompositeList();
@SubTagsList(value = {"child-element", "abstract-element"}, tagName = "abstract-element")
MyBarConcreteElement addBarComposite();
}
public interface MyAbstractElement extends MyElement {
}
public interface MyFooConcreteElement extends MyAbstractElement {
}
public interface MyBarConcreteElement extends MyAbstractElement {
}
}
@@ -0,0 +1,456 @@
package com.intellij.util.xml;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.util.IncorrectOperationException;
import com.intellij.lang.Language;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
public class DomReferenceInjectorTest extends DomHardCoreTestCase {
public void testBasic() throws Exception {
MyElement element = createElement("<a><value>abc${prop}def</value></a>", MyElement.class);
assertEquals("abc${prop}def", element.getValue().getStringValue());
assertEquals("abc${prop}def", element.getValue().getValue());
}
public void testWithInjector() throws Exception {
MyElement element = createElement("<a><value>abc${prop}def</value></a>", MyElement.class);
registerInjectorFor(element, null);
assertEquals("abcFOOdef", element.getValue().getStringValue());
assertEquals("abcFOOdef", element.getValue().getValue());
}
public void testCorrectlyCalculateOffsetWithInjector() throws Exception {
MyElement element = createElement("<a><value> abc${prop}def </value></a>", MyElement.class);
registerInjectorFor(element, null);
assertEquals("abcFOOdef", element.getValue().getStringValue());
assertEquals("abcFOOdef", element.getValue().getValue());
}
public void testWithInjectorAndConverter() throws Exception {
MyElement element = createElement("<a><converted-value>abc${prop}def</converted-value></a>", MyElement.class);
registerInjectorFor(element, null);
assertEquals("abcFOOdef", element.getConvertedValue().getStringValue());
assertEquals("abcBARdef", element.getConvertedValue().getValue());
}
public void testReference() throws Exception {
String text = "<a><value>abc${prop}def</value></a>";
MyElement element = createElement(text, MyElement.class);
MyPsiElement targetElement = new MyPsiElement();
registerInjectorFor(element, targetElement);
assertEquals("abcFOOdef", element.getValue().getStringValue());
assertEquals("abcFOOdef", element.getValue().getValue());
assertReference(element.getValue(), targetElement, text.indexOf("${prop}") + 1);
}
public void testAttribute() throws Exception {
String text = "<a attr=\"abc${prop}def\"/>";
MyElement element = createElement(text, MyElement.class);
MyPsiElement targetElement = new MyPsiElement();
registerInjectorFor(element, targetElement);
assertEquals("abcFOOdef", element.getAttr().getStringValue());
assertEquals("abcFOOdef", element.getAttr().getValue());
assertReference(element.getAttr(), targetElement, text.indexOf("${prop}") + 1);
}
private void registerInjectorFor(DomElement element, PsiElement targetElement) {
DomUtil.getFileElement(element).getFileDescription().registerReferenceInjector(new MyInjector(targetElement));
}
public interface MyElement extends DomElement {
GenericDomValue<String> getValue();
@Convert(MyConverter.class)
GenericDomValue<String> getConvertedValue();
GenericAttributeValue<String> getAttr();
}
public static class MyConverter extends Converter<String> {
@Override
public String fromString(@Nullable @NonNls String s, ConvertContext context) {
return s == null ? null : s.replaceAll("FOO", "BAR");
}
@Override
public String toString(@Nullable String s, ConvertContext context) {
return s;
}
}
public static class MyPsiElement implements PsiElement {
@Override
@NotNull
public Project getProject() throws PsiInvalidElementAccessException {
throw new UnsupportedOperationException();
}
@Override
@NotNull
public Language getLanguage() {
throw new UnsupportedOperationException();
}
@Override
public PsiManager getManager() {
throw new UnsupportedOperationException();
}
@Override
@NotNull
public PsiElement[] getChildren() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getParent() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getFirstChild() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getLastChild() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getNextSibling() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getPrevSibling() {
throw new UnsupportedOperationException();
}
@Override
public PsiFile getContainingFile() throws PsiInvalidElementAccessException {
throw new UnsupportedOperationException();
}
@Override
public TextRange getTextRange() {
throw new UnsupportedOperationException();
}
@Override
public int getStartOffsetInParent() {
throw new UnsupportedOperationException();
}
@Override
public int getTextLength() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement findElementAt(int offset) {
throw new UnsupportedOperationException();
}
@Override
public PsiReference findReferenceAt(int offset) {
throw new UnsupportedOperationException();
}
@Override
public int getTextOffset() {
throw new UnsupportedOperationException();
}
@Override
public String getText() {
throw new UnsupportedOperationException();
}
@Override
@NotNull
public char[] textToCharArray() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getNavigationElement() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getOriginalElement() {
throw new UnsupportedOperationException();
}
@Override
public boolean textMatches(@NotNull @NonNls CharSequence text) {
throw new UnsupportedOperationException();
}
@Override
public boolean textMatches(@NotNull PsiElement element) {
throw new UnsupportedOperationException();
}
@Override
public boolean textContains(char c) {
throw new UnsupportedOperationException();
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
throw new UnsupportedOperationException();
}
@Override
public void acceptChildren(@NotNull PsiElementVisitor visitor) {
throw new UnsupportedOperationException();
}
@Override
public PsiElement copy() {
throw new UnsupportedOperationException();
}
@Override
public PsiElement add(@NotNull PsiElement element) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public void checkAdd(@NotNull PsiElement element) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public PsiElement addRangeBefore(@NotNull PsiElement first, @NotNull PsiElement last, PsiElement anchor)
throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public void delete() throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public void checkDelete() throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public void deleteChildRange(PsiElement first, PsiElement last) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException {
throw new UnsupportedOperationException();
}
@Override
public boolean isValid() {
throw new UnsupportedOperationException();
}
@Override
public boolean isWritable() {
throw new UnsupportedOperationException();
}
@Override
public PsiReference getReference() {
throw new UnsupportedOperationException();
}
@Override
@NotNull
public PsiReference[] getReferences() {
throw new UnsupportedOperationException();
}
@Override
public <T> T getCopyableUserData(Key<T> key) {
throw new UnsupportedOperationException();
}
@Override
public <T> void putCopyableUserData(Key<T> key, T value) {
throw new UnsupportedOperationException();
}
@Override
public boolean processDeclarations(@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@Nullable PsiElement lastParent,
@NotNull PsiElement place) {
throw new UnsupportedOperationException();
}
@Override
public PsiElement getContext() {
throw new UnsupportedOperationException();
}
@Override
public boolean isPhysical() {
throw new UnsupportedOperationException();
}
@Override
@NotNull
public GlobalSearchScope getResolveScope() {
throw new UnsupportedOperationException();
}
@Override
@NotNull
public SearchScope getUseScope() {
throw new UnsupportedOperationException();
}
@Override
public ASTNode getNode() {
throw new UnsupportedOperationException();
}
@Override
public boolean isEquivalentTo(PsiElement another) {
throw new UnsupportedOperationException();
}
@Override
public <T> T getUserData(@NotNull Key<T> key) {
throw new UnsupportedOperationException();
}
@Override
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
throw new UnsupportedOperationException();
}
@Override
public Icon getIcon(int flags) {
throw new UnsupportedOperationException();
}
}
private static class MyInjector implements DomReferenceInjector {
private final PsiElement myMyTargetElement;
public MyInjector(PsiElement myTargetElement) {
myMyTargetElement = myTargetElement;
}
@Override
public String resolveString(@Nullable String unresolvedText, @NotNull ConvertContext context) {
return unresolvedText == null ? null : unresolvedText.replaceAll("\\$\\{prop\\}", "FOO");
}
@Override
@NotNull
public PsiReference[] inject(@Nullable String unresolvedText, @NotNull final PsiElement element, @NotNull ConvertContext context) {
final String prop = "${prop}";
int index = unresolvedText == null ? -1 : unresolvedText.indexOf(prop);
if (index == -1) return PsiReference.EMPTY_ARRAY;
TextRange textRange = ElementManipulators.getValueTextRange(element);
final TextRange refRange = TextRange.from(textRange.getStartOffset() + index, prop.length());
return new PsiReference[] {
new PsiReference() {
@Override
public PsiElement getElement() {
return element;
}
@Override
public TextRange getRangeInElement() {
return refRange;
}
@Override
public PsiElement resolve() {
return myMyTargetElement;
}
@Override
@NotNull
public String getCanonicalText() {
return prop;
}
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
return null;
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
return null;
}
@Override
public boolean isReferenceTo(PsiElement element) {
return false;
}
@Override
@NotNull
public Object[] getVariants() {
return EMPTY_ARRAY;
}
@Override
public boolean isSoft() {
return true;
}
}
};
}
}
}
@@ -0,0 +1,249 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlTagValue;
import com.intellij.util.xml.impl.GenericDomValueReference;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author peter
*/
public class DomReferencesTest extends DomHardCoreTestCase {
public void testMetaData() throws Throwable {
final MyElement element = createElement("");
element.getName().setValue("A");
final XmlTag tag = element.getXmlTag();
final DomMetaData metaData = assertInstanceOf(tag.getMetaData(), DomMetaData.class);
assertEquals(tag, metaData.getDeclaration());
assertOrderedEquals(metaData.getDependences(), DomUtil.getFileElement(element), tag);
assertEquals("A", metaData.getName());
assertEquals("A", metaData.getName(null));
metaData.setName("B");
assertEquals("B", element.getName().getValue());
}
public void testNameReference() throws Throwable {
final MyElement element = createElement("<a><name>abc</name></a>");
final DomTarget target = DomTarget.getTarget(element);
assertNotNull(target);
final XmlTag tag = element.getName().getXmlTag();
assertNull(tag.getContainingFile().findReferenceAt(tag.getValue().getTextRange().getStartOffset()));
}
public void testProcessingInstruction() throws Throwable {
createElement("<a><?xml version=\"1.0\"?></a>").getXmlTag().accept(new PsiRecursiveElementVisitor() {
@Override public void visitElement(PsiElement element) {
super.visitElement(element);
for (final PsiReference reference : element.getReferences()) {
assertFalse(reference instanceof GenericDomValueReference);
}
}
});
}
public void testBooleanReference() throws Throwable {
final MyElement element = createElement("<a><boolean>true</boolean></a>");
assertVariants(assertReference(element.getBoolean()), "false", "true");
}
public void testBooleanAttributeReference() throws Throwable {
final MyElement element = createElement("<a boolean-attribute=\"true\"/>");
final PsiReference reference = getReference(element.getBooleanAttribute());
assertVariants(reference, "false", "true");
final XmlAttributeValue xmlAttributeValue = element.getBooleanAttribute().getXmlAttributeValue();
final PsiElement psiElement = reference.getElement();
assertEquals(xmlAttributeValue, psiElement);
assertEquals(new TextRange(0, "true".length()).shiftRight(1), reference.getRangeInElement());
}
public void testEnumReference() throws Throwable {
assertVariants(assertReference(createElement("<a><enum>239</enum></a>").getEnum(), null), "A", "B", "C");
assertVariants(assertReference(createElement("<a><enum>A</enum></a>").getEnum()), "A", "B", "C");
}
public void testPsiClass() throws Throwable {
final MyElement element = createElement("<a><psi-class>java.lang.String</psi-class></a>");
assertReference(element.getPsiClass(), PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject())).resolve(),
element.getPsiClass().getXmlTag().getValue().getTextRange().getEndOffset() - 1);
}
public void testPsiType() throws Throwable {
final MyElement element = createElement("<a><psi-type>java.lang.String</psi-type></a>");
assertReference(element.getPsiType(), PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject())).resolve());
}
public void testIndentedPsiType() throws Throwable {
final MyElement element = createElement("<a><psi-type> java.lang.Strin </psi-type></a>");
final PsiReference psiReference = assertReference(element.getPsiType(), null);
assertEquals(new TextRange(22, 22 + "Strin".length()), psiReference.getRangeInElement());
}
public void testPsiPrimitiveType() throws Throwable {
final MyElement element = createElement("<a><psi-type>int</psi-type></a>");
assertReference(element.getPsiType());
}
public void testPsiPrimitiveTypeArray() throws Throwable {
final MyElement element = createElement("<a><psi-type>int[]</psi-type></a>");
final GenericDomValue value = element.getPsiType();
final XmlTagValue tagValue = value.getXmlTag().getValue();
final int i = tagValue.getText().indexOf(value.getStringValue());
assertReference(value, value.getXmlTag(), tagValue.getTextRange().getStartOffset() + i + "int".length());
}
public void testPsiUnknownType() throws Throwable {
final MyElement element = createElement("<a><psi-type>#$^%*$</psi-type></a>");
assertReference(element.getPsiType(), null);
}
public void testPsiArrayType() throws Throwable {
final MyElement element = createElement("<a><psi-type>java.lang.String[]</psi-type></a>");
final XmlTag tag = element.getPsiType().getXmlTag();
final TextRange valueRange = tag.getValue().getTextRange();
final PsiReference reference = tag.getContainingFile().findReferenceAt(valueRange.getStartOffset() + "java.lang.".length());
assertNotNull(reference);
assertEquals(PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject())).resolve(), reference.resolve());
assertEquals("<psi-type>java.lang.".length(), reference.getRangeInElement().getStartOffset());
assertEquals("String".length(), reference.getRangeInElement().getLength());
}
public void testJvmArrayType() throws Throwable {
final MyElement element = createElement("<a><jvm-psi-type>[Ljava.lang.String;</jvm-psi-type></a>");
final XmlTag tag = element.getJvmPsiType().getXmlTag();
final TextRange valueRange = tag.getValue().getTextRange();
final PsiReference reference = tag.getContainingFile().findReferenceAt(valueRange.getEndOffset() - 1);
assertNotNull(reference);
assertEquals(PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject())).resolve(), reference.resolve());
assertEquals("<jvm-psi-type>[Ljava.lang.".length(), reference.getRangeInElement().getStartOffset());
assertEquals("String".length(), reference.getRangeInElement().getLength());
}
public void testCustomResolving() throws Throwable {
final MyElement element = createElement("<a><string-buffer>239</string-buffer></a>");
assertVariants(assertReference(element.getStringBuffer()), "239", "42", "foo", "zzz");
}
public void testAdditionalValues() throws Throwable {
final MyElement element = createElement("<a><string-buffer>zzz</string-buffer></a>");
final XmlTag tag = element.getStringBuffer().getXmlTag();
assertTrue(tag.getContainingFile().findReferenceAt(tag.getValue().getTextRange().getStartOffset()).isSoft());
}
public interface MyElement extends DomElement {
GenericDomValue<Boolean> getBoolean();
GenericAttributeValue<Boolean> getBooleanAttribute();
@Convert(MyStringConverter.class)
GenericDomValue<String> getConvertedString();
GenericDomValue<MyEnum> getEnum();
@NameValue GenericDomValue<String> getName();
GenericDomValue<PsiClass> getPsiClass();
GenericDomValue<PsiType> getPsiType();
@Convert(JvmPsiTypeConverter.class)
GenericDomValue<PsiType> getJvmPsiType();
List<GenericDomValue<MyEnum>> getEnumChildren();
@Convert(MyStringBufferConverter.class)
GenericDomValue<StringBuffer> getStringBuffer();
MyAbstractElement getChild();
MyElement getRecursiveChild();
List<MyGenericValue> getMyGenericValues();
MyGenericValue getMyAnotherGenericValue();
}
@Convert(MyStringConverter.class)
public interface MyGenericValue extends GenericDomValue<String> {
}
public interface MySomeInterface {
GenericValue<PsiType> getFoo();
}
public interface MyAbstractElement extends DomElement {
GenericAttributeValue<String> getFubar239();
GenericAttributeValue<Runnable> getFubar();
}
public interface MyFooElement extends MyAbstractElement, MySomeInterface {
@Override
GenericDomValue<PsiType> getFoo();
GenericAttributeValue<Set> getFubar2();
}
public interface MyBarElement extends MyAbstractElement {
GenericDomValue<StringBuffer> getBar();
}
public enum MyEnum {
A,B,C
}
public static class MyStringConverter extends ResolvingConverter<String> {
@Override
@NotNull
public Collection<? extends String> getVariants(final ConvertContext context) {
return Collections.emptyList();
}
@Override
public String fromString(final String s, final ConvertContext context) {
return s;
}
@Override
public String toString(final String s, final ConvertContext context) {
return s;
}
}
public static class MyStringBufferConverter extends ResolvingConverter<StringBuffer> {
@Override
public StringBuffer fromString(final String s, final ConvertContext context) {
return s == null ? null : new StringBuffer(s);
}
@Override
public String toString(final StringBuffer t, final ConvertContext context) {
return t == null ? null : t.toString();
}
@Override
public Collection<? extends StringBuffer> getVariants(final ConvertContext context) {
return Arrays.asList(new StringBuffer("239"), new StringBuffer("42"), new StringBuffer("foo"));
}
@Override
public Set<String> getAdditionalVariants() {
return Collections.singleton("zzz");
}
}
}
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
* Use is subject to license terms.
*/
package com.intellij.util.xml;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.xml.XmlFile;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.Nullable;
import org.xml.sax.SAXException;
import java.io.IOException;
/**
* @author peter
*/
public class DomSaxParserTest extends LightCodeInsightFixtureTestCase {
public void testGetRootTagNameWithoutNamespace() throws Throwable {
assertData("<root>", "root", null, null, null);
}
public void testGetRootTagNameWithNamespaceWithEmptyPrefix() throws Throwable {
assertData("<root xmlns=\"foo\">", "root", "foo", null, null);
}
public void testGetRootTagNameWithUnfinishedAttribute() throws Throwable {
XmlFile file = createXmlFile("<root xmlns=\"foo\" aaa>");
ensureParsed(file);
final XmlFileHeader header = DomService.getInstance().getXmlFileHeader(file);
assertEquals(new XmlFileHeader("root", "foo", null, null), header);
}
public void testGetRootTagNameWithNamespaceWithNonEmptyPrefix() throws Throwable {
assertData("<bar:root xmlns=\"foo\" xmlns:bar=\"b\">", "root", "b", null, null);
}
public void testGetRootTagNameWithDtdNamespace() throws Throwable {
assertData("<!DOCTYPE ejb-jar PUBLIC\n" +
"\"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN\"\n" +
"\"http://java.sun.com/dtd/ejb-jar_2_0.dtd\"><root>", "root", null, "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN", "http://java.sun.com/dtd/ejb-jar_2_0.dtd");
}
public void testGetRootTagNameWithDtdNamespace2() throws Throwable {
assertData("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE ejb-jar PUBLIC\n" +
"\"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN\"\n" +
"\"http://java.sun.com/dtd/ejb-jar_2_0.dtd\"><root>", "root", null, "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN", "http://java.sun.com/dtd/ejb-jar_2_0.dtd");
}
public void testNoTag() throws Throwable {
assertData("aaaaaaaaaaaaaaaaaaaaa", null, null, null, null);
}
public void testEmptyFile() throws Throwable {
assertData("", null, null, null, null);
}
public void testInvalidContent() throws Throwable {
assertData("<?xmlmas8v6708986><OKHD POH:&*$%*&*I8yo9", null, null, null, null);
}
public void testInvalidContent2() throws Throwable {
assertData("?xmlmas8v6708986><OKHD POH:&*$%*&*I8yo9", null, null, null, null);
}
private static PsiElement ensureParsed(PsiFile file) {
return file.findElementAt(2);
}
public void testInvalidContent3() throws Throwable {
assertData("<?xmlmas8v67089", null, null, null, null);
}
public void testSubtag() throws Throwable {
assertData("<root><foo/>", "root", null, null, null);
}
public void testSpring() throws Throwable {
assertData("<?xml version=\"1.0\" encoding=\"gbk\"?>\n" + "\n" + "\n" +
"<beans xmlns=\"http://www.springframework.org/schema/beans\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n" +
" xmlns:tx=\"http://www.springframework.org/schema/tx\"\n" +
" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd\n" +
" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd\n" +
" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd\">\n" +
"</beans>", "beans", "http://www.springframework.org/schema/beans", null, null);
}
public void testInternalDtd() throws Throwable {
assertData("<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE \n" +
" hibernate-mapping SYSTEM\n" +
"\t\t\t\"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd\"\n" + "[\n" +
"<!ENTITY % globals SYSTEM \"classpath://auction/persistence/globals.dtd\">\n" + "%globals;\n" + "]><a/>", "a", null, null, "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd");
}
private void assertData(final String start, @Nullable final String localName, @Nullable String namespace, @Nullable String publicId, @Nullable String systemId) throws IOException, SAXException {
XmlFileHeader expected = new XmlFileHeader(localName, namespace, publicId, systemId);
XmlFile file = createXmlFile(start);
assert !file.getNode().isParsed();
assertEquals(expected, DomService.getInstance().getXmlFileHeader(file));
ensureParsed(file);
assert file.getNode().isParsed();
assertEquals(expected, DomService.getInstance().getXmlFileHeader(file));
}
private XmlFile createXmlFile(String text) {
return (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("a.xml", XMLLanguage.INSTANCE, text, false, false, false);
}
}
@@ -0,0 +1,539 @@
package com.intellij.util.xml;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.events.DomEvent;
import com.intellij.util.xml.ui.DomUIFactory;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* @author peter
*/
public class DomSimpleValuesTest extends DomTestCase {
private MyElement createElement(final String xml) throws IncorrectOperationException {
return createElement(xml, MyElement.class);
}
public void testGetValue() throws Throwable {
final String text = "<a>foo</a>";
assertEquals("foo", createElement(text).getTagValue());
assertEquals("foo", createElement(text).getValue());
}
public void testSetValue() throws Throwable {
final MyElement element = createElement("<a/>");
assertEquals("", element.getValue());
element.setValue(239);
assertEquals("239", element.getValue());
assertEquals("239", element.getXmlTag().getValue().getText());
myCallRegistry.putExpected(new DomEvent(element, false));
myCallRegistry.assertResultsAndClear();
}
public void testDefineAndSet() throws Throwable {
final MyElement element = getDomManager().getFileElement(createXmlFile(""), MyElement.class, "root").getRootElement();
myCallRegistry.clear();
assertNull(element.getXmlTag());
element.setValue(42);
assertNotNull(element.getXmlTag());
assertEquals("42", element.getXmlTag().getValue().getText());
final DomElement element1 = element;
myCallRegistry.putExpected(new DomEvent(element1, true));
myCallRegistry.putExpected(new DomEvent(element, false));
element.setValue((Integer)null);
assertNull(element.getXmlTag());
assertEquals(null, element.getValue());
myCallRegistry.putExpected(new DomEvent(element, false));
myCallRegistry.assertResultsAndClear();
}
public void testSimpleConverters() throws Throwable {
assertEquals(239, createElement("<a>239</a>").getInt());
assertEquals(true, createElement("<a>true</a>").getBoolean());
assertEquals("true", createElement("<a>true</a>").getBuffer().toString());
try {
createElement("<a>true</a>").getInt();
fail();
}
catch (NullPointerException e) {
}
try {
createElement("<a>42</a>").getBoolean();
fail();
}
catch (NullPointerException e) {
}
}
public void testComment() throws Throwable {
assertEquals(239, createElement("<a>" +
" <!-- some comment-->" +
" 239" +
" <!-- some another comment-->" +
"</a>").getInt());
}
public void testPsiClassConverter() throws Throwable {
final String className = Object.class.getName();
final PsiClass objectClass = getJavaFacade().findClass(className, GlobalSearchScope.allScope(getProject()));
assertEquals(objectClass, createElement("<a>" + className + "</a>").getPsiClass());
assertNull(createElement("<a>abcdef</a>").getPsiClass());
}
public void testEnums() throws Throwable {
final MyElement element = createElement("<a/>", MyElement.class);
assertNull(element.getEnum());
element.setEnum(DomTestCase.MyEnum.BAR);
assertEquals(DomTestCase.MyEnum.BAR, element.getEnum());
assertEquals(DomTestCase.MyEnum.BAR.getValue(), element.getXmlTag().getValue().getText());
element.setEnum(null);
assertNull(element.getEnum());
assertNull(element.getXmlTag());
element.setValue(239);
assertNull(element.getEnum());
}
public void testAttributeValues() throws Throwable {
final MyElement element = createElement("<a attra=\"foo\"/>");
final GenericAttributeValue<String> attributeValue = element.getAttributeValue();
assertEquals("attra", attributeValue.getXmlElementName());
assertEquals("foo", attributeValue.getValue());
final GenericAttributeValue<Integer> attr = element.getAttr();
attr.setValue(239);
assertEquals(239, (int)attr.getValue());
assertEquals("239", element.getXmlTag().getAttributeValue("attr"));
final DomElement element1 = attr;
myCallRegistry.putExpected(new DomEvent(element1, true));
myCallRegistry.assertResultsAndClear();
attr.setValue(42);
myCallRegistry.putExpected(new DomEvent(attr, false));
myCallRegistry.assertResultsAndClear();
attr.setValue(null);
assertNull(attr.getValue());
assertNull(element.getXmlTag().getAttributeValue("attr"));
assertNull(element.getXmlTag().getAttribute("attr", ""));
myCallRegistry.putExpected(new DomEvent(attr, false));
myCallRegistry.assertResultsAndClear();
assertEquals("some-attribute", element.getSomeAttribute().getXmlElementName());
assertNull(createElement("<a attra\"attr\"/>").getAttributeValue().getStringValue());
assertNull(createElement("<a attra\"\"/>").getAttributeValue().getStringValue());
assertNull(createElement("<a attra\"/>").getAttributeValue().getStringValue());
}
public void testGenericValue() throws Throwable {
final MyElement element = createElement("<a><generic-child>239</generic-child></a>");
final GenericDomValue<Integer> integerChild = element.getGenericChild();
assertEquals(239, (int)integerChild.getValue());
assertEquals("239", integerChild.getStringValue());
integerChild.setValue(42);
assertEquals(42, (int)integerChild.getValue());
assertEquals("42", integerChild.getStringValue());
}
public void testAnnotatedGenericValue() throws Throwable {
final MyElement element = createElement("<a><buffer>239</buffer></a>");
element.getGenericChild().getValue();
final GenericDomValue<StringBuffer> genericChild2 = element.getGenericChild2();
assertEquals("239", genericChild2.getValue().toString());
}
public void testSpecialCharacters() throws Throwable {
final MyElement element = createElement("");
element.setValue("<");
assertEquals("<", element.getValue());
assertEquals("<![CDATA[<]]>", element.getXmlTag().getValue().getText());
element.getAttributeValue().setValue("<");
assertEquals("<", element.getAttributeValue().getValue());
assertEquals("\"&lt;\"", element.getXmlTag().getAttribute("attra", null).getValueElement().getText());
}
public void testIndicators() throws Throwable {
final MyElement element = createElement("<a><indicator/></a>");
final GenericDomValue<Boolean> indicator = element.getIndicator();
assertTrue(indicator.getValue());
indicator.setValue(false);
assertFalse(indicator.getValue());
assertNull(indicator.getStringValue());
assertNull(indicator.getXmlTag());
assertEquals(0, element.getXmlTag().getSubTags().length);
putExpected(new DomEvent(indicator, false));
assertResultsAndClear();
indicator.setValue(true);
assertTrue(indicator.getValue());
assertEquals("", indicator.getStringValue());
assertSame(indicator.getXmlTag(), element.getXmlTag().getSubTags()[0]);
final DomElement element1 = indicator;
putExpected(new DomEvent(element1, true));
assertResultsAndClear();
final XmlTag tag = element.getXmlTag();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
tag.add(createTag("<indicator/>"));
tag.add(createTag("<indicator/>"));
}
}.execute();
assertTrue(element.isValid());
assertTrue(element.getIndicator().getValue());
element.getIndicator().setValue(false);
assertFalse(element.getIndicator().getValue());
assertEquals(0, element.getXmlTag().findSubTags("indicator").length);
}
public void testConcreteGenericValue() throws Throwable {
final ConcreteGeneric generic = createElement("", ConcreteGeneric.class);
generic.setValue("abc");
assertEquals("abc", generic.getValue());
DomUIFactory.SET_VALUE_METHOD.invoke(generic, "def");
assertEquals("def", DomUIFactory.GET_VALUE_METHOD.invoke(generic));
}
public void testConcreteGenericValueWithMethods() throws Throwable {
final ConcreteGenericWithMethods generic = createElement("", ConcreteGenericWithMethods.class);
generic.setValue("abc");
assertEquals("abc", generic.getValue());
DomUIFactory.SET_VALUE_METHOD.invoke(generic, "def");
assertEquals("def", DomUIFactory.GET_VALUE_METHOD.invoke(generic));
}
public void testNameValueInPresentation() throws Throwable {
final MyElement element = createElement("");
element.getAttr().setValue(23942);
assertEquals("23942", element.getPresentation().getElementName());
}
public void testResolveToDomElement() throws Throwable {
final RootInterface element = createElement("", RootInterface.class);
final MyElement child1 = element.addChild();
child1.getAttr().setValue(555);
final MyElement child2 = element.addChild();
child2.getAttr().setValue(777);
final GenericDomValue<MyElement> resolve = child2.getResolve();
resolve.setStringValue("777");
assertEquals(child2, resolve.getValue());
resolve.setValue(child1);
assertEquals("555", resolve.getStringValue());
assertEquals(child1, resolve.getValue());
resolve.setStringValue("239");
assertNull(resolve.getValue());
final GenericDomValue<MyElement> resolve2 = child2.getResolve2();
resolve2.setStringValue("777");
assertEquals(child2, resolve2.getValue());
}
public void testPlainPsiTypeConverter() throws Throwable {
assertNull(createElement("").getPsiType());
assertSame(PsiType.INT, createElement("<a>int</a>").getPsiType());
final PsiType psiType = createElement("<a>java.lang.String</a>").getPsiType();
assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(psiType, PsiClassType.class).getCanonicalText());
final PsiType arrayType = createElement("<a>int[]</a>").getPsiType();
assertTrue(arrayType instanceof PsiArrayType);
assertSame(PsiType.INT, ((PsiArrayType) arrayType).getComponentType());
}
public void testJvmPsiTypeConverter() throws Throwable {
assertNull(createElement("").getJvmPsiType());
assertNotNull(createElement("<a>int</a>").getJvmPsiType());
final PsiClassType string = PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject()));
final PsiType psiType = createElement("<a>java.lang.String</a>").getJvmPsiType();
assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(psiType, PsiClassType.class).getCanonicalText());
final PsiArrayType intArray = assertInstanceOf(createElement("<a>[I</a>").getJvmPsiType(), PsiArrayType.class);
final PsiArrayType stringArray = assertInstanceOf(createElement("<a>[Ljava.lang.String;</a>").getJvmPsiType(), PsiArrayType.class);
assertSame(PsiType.INT, intArray.getComponentType());
assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(stringArray.getComponentType(), PsiClassType.class).getCanonicalText());
assertJvmPsiTypeToString(intArray, "[I");
assertJvmPsiTypeToString(stringArray, "[Ljava.lang.String;");
assertJvmPsiTypeToString(string, "java.lang.String");
}
public void testValueCaching() throws Throwable {
final GenericDomValue<String> element = createElement("<a><cached-value/></a>", MyElement.class).getCachedValue();
assertEquals(0, ((MyConverter) element.getConverter()).fromStringCalls);
assertEquals("", element.getValue());
assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls);
assertEquals("", element.getValue());
assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls);
element.setValue("1");
assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls);
assertEquals("1", element.getValue());
assertEquals(2, ((MyConverter) element.getConverter()).fromStringCalls);
}
private void assertJvmPsiTypeToString(final PsiType type, final String expected) throws IncorrectOperationException {
final MyElement element = createElement("");
element.setJvmPsiType(type);
assertEquals(expected, element.getValue());
}
public void testJavaStyledElement() throws IncorrectOperationException {
JavaStyledElement element = createElement("<tag javaStyledAttribute=\"666\"></tag>", JavaStyledElement.class);
assertEquals(element.getJavaStyledAttribute().getXmlElementName(), "javaStyledAttribute");
}
public void testGenericValueListConverter() throws Throwable {
final MyElement element = createElement("<a><string-buffer>abc</string-buffer></a>");
assertEquals("abc", element.getStringBuffers().get(0).getValue().toString());
}
public void testConvertAnnotationOnType() throws Throwable {
final MyElement element =
createElement("<a>" + "<my-generic-value>abc</my-generic-value>" + "<my-foo-generic-value>abc</my-foo-generic-value>" + "");
assertEquals("bar", element.getMyGenericValue().getValue());
assertEquals("foo", element.getMyFooGenericValue().getValue());
}
public void testEntities() throws Throwable {
final MyElement element = createElement("<!DOCTYPE a SYSTEM \"aaa\"\n" +
"[<!ENTITY idgenerator \"identity\">]>\n" +
"<a attra=\"a&lt;b\" some-attribute=\"&idgenerator;\">&xxx;+&idgenerator;+&amp;</a>");
assertEquals("a<b", element.getAttributeValue().getValue());
assertEquals("identity", element.getSomeAttribute().getValue());
// assertEquals("&xxx;+identity+&", element.getValue());
}
public interface RootInterface extends DomElement {
List<MyElement> getChildren();
MyElement addChild();
}
public interface MyElement extends DomElement {
@Attribute("attra")
GenericAttributeValue<String> getAttributeValue();
@NameValue
GenericAttributeValue<Integer> getAttr();
GenericAttributeValue<String> getSomeAttribute();
String getValue();
void setValue(Integer value);
@TagValue()
int getInt();
void setValue(String value);
@TagValue()
boolean getBoolean();
@TagValue()
PsiType getPsiType();
@Convert(JvmPsiTypeConverter.class)
@TagValue()
PsiType getJvmPsiType();
@TagValue()
@Convert(JvmPsiTypeConverter.class)
void setJvmPsiType(PsiType psiType);
@TagValue()
DomTestCase.MyEnum getEnum();
@TagValue
void setEnum(DomTestCase.MyEnum value);
@TagValue()
@Convert(StringBufferConverter.class)
StringBuffer getBuffer();
@TagValue()
PsiClass getPsiClass();
@TagValue()
String getTagValue();
GenericDomValue<Integer> getGenericChild();
@SubTag("buffer")
@Convert(StringBufferConverter.class)
GenericDomValue<StringBuffer> getGenericChild2();
@SubTag(indicator = true)
GenericDomValue<Boolean> getIndicator();
@Resolve(MyElement.class)
GenericDomValue<MyElement> getResolve();
GenericDomValue<MyElement> getResolve2();
@Convert(StringBufferConverter.class)
List<GenericDomValue<StringBuffer>> getStringBuffers();
@Convert(MyConverter.class) GenericDomValue<String> getCachedValue();
MyGenericValue getMyGenericValue();
@Convert(FooConverter.class)
MyGenericValue getMyFooGenericValue();
}
@Convert(BarConverter.class)
public interface MyGenericValue extends GenericDomValue<String> {
}
@NameStrategyForAttributes(JavaNameStrategy.class)
public interface JavaStyledElement extends DomElement {
GenericAttributeValue<String> getJavaStyledAttribute();
}
public interface ConcreteGeneric extends GenericDomValue<String> {
}
public interface ConcreteGenericWithMethods extends GenericDomValue<String> {
@Override
String getValue();
@Override
void setValue(String s);
}
public void testFuhrer() throws Throwable {
final FieldGroup group = createElement("<field-group>\n" +
"<group-name>myGroup</load-group-name>\n" +
"<field-name>myField1</field-name>\n" +
"<field-name>myField2</field-name>\n" +
"</field-group>",
FieldGroup.class);
assertEquals(2, group.getFieldNames().size());
assertEquals("myField1", group.getFieldNames().get(0).getValue().getName().getValue());
assertEquals(null, group.getFieldNames().get(1).getValue());
}
public interface JavaeeModelElement {
}
public interface JavaeeDomModelElement extends JavaeeModelElement, DomElement {
}
public interface FieldGroup extends JavaeeDomModelElement {
GenericDomValue<String> getGroupName();
List<GroupField> getFieldNames();
GroupField addFieldName();
}
public interface GroupField extends JavaeeDomModelElement {
@Convert(value = CmpFieldConverter.class)
CmpField getValue();
@Convert(value = CmpFieldConverter.class)
void setValue(CmpField value);
}
public static class CmpFieldConverter extends ResolvingConverter<CmpField> {
@Override
public CmpField fromString(String s, ConvertContext context) {
return ElementPresentationManager.findByName(getVariants(context), s);
}
@Override
public String toString(CmpField t, ConvertContext context) {
return t == null ? null : t.getName().getValue();
}
@Override
@NotNull
public Collection<CmpField> getVariants(ConvertContext context) {
final DomElement element = context.getInvocationElement();
return Arrays.asList(createCmpField(null, element), createCmpField("myField1", element), createCmpField("def", element));
}
private CmpField createCmpField(String name, DomElement element) {
final CmpField mockElement = element.getManager().createMockElement(CmpField.class, element.getModule(), false);
mockElement.getName().setValue(name);
return mockElement;
}
}
public interface CmpField extends JavaeeDomModelElement {
@NameValue
public GenericDomValue<String> getName();
}
public static class MyConverter extends Converter<String> {
public int fromStringCalls = 0;
@Override
public String fromString(@Nullable @NonNls String s, final ConvertContext context) {
fromStringCalls++;
return s;
}
@Override
public String toString(@Nullable String s, final ConvertContext context) {
return s;
}
}
public static class FooConverter extends Converter<String> {
@Override
public String fromString(@Nullable @NonNls final String s, final ConvertContext context) {
return s == null ? null : "foo";
}
@Override
public String toString(@Nullable final String s, final ConvertContext context) {
return s;
}
}
public static class BarConverter extends Converter<String> {
@Override
public String fromString(@Nullable @NonNls final String s, final ConvertContext context) {
return s == null ? null : "bar";
}
@Override
public String toString(@Nullable final String s, final ConvertContext context) {
return s;
}
}
}
@@ -0,0 +1,135 @@
package com.intellij.util.xml;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.XmlElementFactory;
import com.intellij.psi.impl.PsiModificationTrackerImpl;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.testFramework.LightIdeaTestCase;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.events.DomEvent;
import com.intellij.util.xml.impl.DomApplicationComponent;
import com.intellij.util.xml.impl.DomFileElementImpl;
import com.intellij.util.xml.impl.DomInvocationHandler;
import com.intellij.util.xml.impl.DomManagerImpl;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author peter
*/
public abstract class DomTestCase extends LightIdeaTestCase {
protected CallRegistry<DomEvent> myCallRegistry;
private final DomEventListener myListener = new DomEventListener() {
@Override
public void eventOccured(DomEvent event) {
myCallRegistry.putActual(event);
}
};
@Override
protected void setUp() throws Exception {
super.setUp();
myCallRegistry = new CallRegistry<DomEvent>();
getDomManager().addDomEventListener(myListener, myTestRootDisposable);
}
@Override
protected void tearDown() throws Exception {
DomApplicationComponent.getInstance().clearImplementations();
super.tearDown();
}
protected void assertCached(final DomElement element, final XmlElement xmlElement) {
assertNotNull(xmlElement);
assertSame(element.getXmlTag(), xmlElement);
final DomInvocationHandler cachedElement = getCachedHandler(xmlElement);
assertNotNull(cachedElement);
assertEquals(element, cachedElement.getProxy());
}
protected void assertCached(final DomFileElementImpl element, final XmlFile file) {
assertNotNull(file);
assertEquals(element, getDomManager().getFileElement(file));
}
protected XmlTag createTag(final String text) throws IncorrectOperationException {
return XmlElementFactory.getInstance(getProject()).createTagFromText(text);
}
protected DomManagerImpl getDomManager() {
return (DomManagerImpl)DomManager.getDomManager(getProject());
}
protected static XmlFile createXmlFile(@NonNls final String text) throws IncorrectOperationException {
return (XmlFile)createLightFile("a.xml", text);
}
protected <T extends DomElement> T createElement(final String xml, final Class<T> aClass) throws IncorrectOperationException {
final DomManagerImpl domManager = getDomManager();
T element = createElement(domManager, xml, aClass);
myCallRegistry.clear();
return element;
}
protected static <T extends DomElement> T createElement(final DomManager domManager, final String xml, final Class<T> aClass)
throws IncorrectOperationException {
final String name = "a.xml";
final XmlFile file = (XmlFile)PsiFileFactory.getInstance(domManager.getProject()).createFileFromText(name, xml);
final XmlTag tag = file.getDocument().getRootTag();
final String rootTagName = tag != null ? tag.getName() : "root";
final T element = domManager.getFileElement(file, aClass, rootTagName).getRootElement();
assertNotNull(element);
assertSame(tag, element.getXmlTag());
return element;
}
protected void putExpected(final DomEvent event) {
myCallRegistry.putExpected(event);
}
protected void assertResultsAndClear() {
myCallRegistry.assertResultsAndClear();
}
protected TypeChooserManager getTypeChooserManager() {
return getDomManager().getTypeChooserManager();
}
protected static void incModCount() {
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
((PsiModificationTrackerImpl)getPsiManager().getModificationTracker()).incCounter();
}
}.execute();
}
@Nullable
public DomInvocationHandler getCachedHandler(XmlElement element) {
final List<DomInvocationHandler> option = getDomManager().getSemService().getCachedSemElements(DomManagerImpl.DOM_HANDLER_KEY, element);
return option == null || option.isEmpty() ? null : option.get(0);
}
public enum MyEnum implements NamedEnum {
FOO("foo"),
BAR("bar");
private final String myName;
MyEnum(final String name) {
myName = name;
}
@Override
public String getValue() {
return myName;
}
}
}
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.xml.events.DomEvent;
import com.intellij.util.xml.impl.DomFileElementImpl;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class DomVirtualFileEventsTest extends DomHardCoreTestCase{
@Override
protected void setUp() throws Exception {
super.setUp();
getDomManager().registerFileDescription(new DomFileDescription(MyElement.class, "a") {
@Override
public boolean isMyFile(@NotNull final XmlFile file, final Module module) {
return super.isMyFile(file, module) && file.getName().contains("a");
}
}, getTestRootDisposable());
}
public void testCreateFile() throws Throwable {
new WriteCommandAction.Simple(myProject) {
@Override
protected void run() throws Throwable {
final VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(getModule(), dir);
final VirtualFile childData = dir.createChildData(this, "abc.xml");
System.gc();
System.gc();
System.gc();
System.gc();
assertResultsAndClear();
VfsUtil.saveText(childData, "<a/>");
assertEventCount(0);
assertResultsAndClear();
}
}.execute().throwException();
}
public void testDeleteFile() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(getModule(), dir);
final VirtualFile childData = dir.createChildData(this, "abc.xml");
assertResultsAndClear();
VfsUtil.saveText(childData, "<a/>");
final DomFileElementImpl<DomElement> fileElement = getFileElement(childData);
assertResultsAndClear();
childData.delete(this);
assertEventCount(1);
putExpected(new DomEvent(fileElement, false));
assertResultsAndClear();
assertFalse(fileElement.isValid());
}
}.execute().throwException();
}
public void testRenameFile() throws Throwable {
new WriteCommandAction.Simple(getProject()) {
@Override
protected void run() throws Throwable {
final VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(getModule(), dir);
final VirtualFile data = dir.createChildData(this, "abc.xml");
VfsUtil.saveText(data, "<a/>");
final DomFileElementImpl<DomElement> fileElement = getFileElement(data);
assertEventCount(0);
assertResultsAndClear();
data.rename(this, "deaf.xml");
assertEventCount(1);
putExpected(new DomEvent(fileElement, false));
assertResultsAndClear();
assertEquals(fileElement, getFileElement(data));
assertTrue(fileElement.isValid());
data.rename(this, "fff.xml");
assertEventCount(1);
putExpected(new DomEvent(fileElement, false));
assertResultsAndClear();
assertNull(getFileElement(data));
assertFalse(fileElement.isValid());
}
}.execute().throwException();
}
private DomFileElementImpl<DomElement> getFileElement(final VirtualFile file) {
return getDomManager().getFileElement((XmlFile)getPsiManager().findFile(file));
}
public interface MyElement extends DomElement {
}
}
@@ -0,0 +1,169 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.reflect.DomGenericInfo;
import com.intellij.util.xml.reflect.AbstractDomChildrenDescription;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* @author peter
*/
public class MockDomElement extends UserDataHolderBase implements DomElement{
@Override
@Nullable
public XmlTag getXmlTag() {
throw new UnsupportedOperationException("Method getXmlTag is not yet implemented in " + getClass().getName());
}
@NotNull
public <T extends DomElement> DomFileElement<T> getRoot() {
throw new UnsupportedOperationException("Method getRoot is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public DomElement getParent() {
throw new UnsupportedOperationException("Method getParent is not yet implemented in " + getClass().getName());
}
@Override
public XmlTag ensureTagExists() {
throw new UnsupportedOperationException("Method ensureTagExists is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public XmlElement getXmlElement() {
throw new UnsupportedOperationException("Method getXmlElement is not yet implemented in " + getClass().getName());
}
@Override
public XmlElement ensureXmlElementExists() {
throw new UnsupportedOperationException("Method ensureXmlElementExists is not yet implemented in " + getClass().getName());
}
@Override
public void undefine() {
throw new UnsupportedOperationException("Method undefine is not yet implemented in " + getClass().getName());
}
@Override
public boolean isValid() {
throw new UnsupportedOperationException("Method isValid is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public DomGenericInfo getGenericInfo() {
throw new UnsupportedOperationException("Method getGenericInfo is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
@NonNls
public String getXmlElementName() {
throw new UnsupportedOperationException("Method getXmlElementName is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
@NonNls
public String getXmlElementNamespace() {
throw new UnsupportedOperationException("Method getXmlElementNamespace is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
@NonNls
public String getXmlElementNamespaceKey() {
throw new UnsupportedOperationException("Method getXmlElementNamespaceKey is not yet implemented in " + getClass().getName());
}
@Override
public void accept(final DomElementVisitor visitor) {
throw new UnsupportedOperationException("Method accept is not yet implemented in " + getClass().getName());
}
@Override
public void acceptChildren(DomElementVisitor visitor) {
throw new UnsupportedOperationException("Method acceptChildren is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public DomManager getManager() {
throw new UnsupportedOperationException("Method getManager is not yet implemented in " + getClass().getName());
}
@Override
public Type getDomElementType() {
throw new UnsupportedOperationException("Method getDomElementType is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public AbstractDomChildrenDescription getChildDescription() {
throw new UnsupportedOperationException("Method getChildDescription is not yet implemented in " + getClass().getName());
}
@Override
public DomNameStrategy getNameStrategy() {
throw new UnsupportedOperationException("Method getNameStrategy is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public ElementPresentation getPresentation() {
throw new UnsupportedOperationException("Method getPresentation is not yet implemented in " + getClass().getName());
}
@Override
public GlobalSearchScope getResolveScope() {
throw new UnsupportedOperationException("Method getResolveScope is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public <T extends DomElement> T getParentOfType(Class<T> requiredClass, boolean strict) {
throw new UnsupportedOperationException("Method getParentOfType is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public Module getModule() {
throw new UnsupportedOperationException("Method getModule is not yet implemented in " + getClass().getName());
}
@Override
public void copyFrom(DomElement other) {
throw new UnsupportedOperationException("Method copyFrom is not yet implemented in " + getClass().getName());
}
@Override
public <T extends DomElement> T createMockCopy(final boolean physical) {
throw new UnsupportedOperationException("Method createMockCopy is not yet implemented in " + getClass().getName());
}
@Override
public <T extends DomElement> T createStableCopy() {
return (T)this;
}
@Override
@Nullable
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
throw new UnsupportedOperationException("Method getAnnotation is not yet implemented in " + getClass().getName());
}
}
@@ -0,0 +1,219 @@
/*
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.reflect.DomGenericInfo;
import com.intellij.util.xml.reflect.AbstractDomChildrenDescription;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* @author peter
*/
public class MockDomFileElement extends UserDataHolderBase implements DomFileElement<DomElement>{
private long myModCount = 0;
private DomFileDescription myFileDescription;
public void setFileDescription(final DomFileDescription fileDescription) {
myFileDescription = fileDescription;
}
@Override
@NotNull
public XmlFile getFile() {
throw new UnsupportedOperationException("Method getFile is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public XmlFile getOriginalFile() {
throw new UnsupportedOperationException("Method getOriginalFile is not yet implemented in " + getClass().getName());
}
@Override
public XmlTag getRootTag() {
throw new UnsupportedOperationException("Method getRootTag is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public DomElement getRootElement() {
throw new UnsupportedOperationException("Method getRootElement is not yet implemented in " + getClass().getName());
}
@Override
public Class getRootElementClass() {
throw new UnsupportedOperationException("Method getRootElementType is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public DomFileDescription getFileDescription() {
return myFileDescription;
}
@Override
@Nullable
public XmlTag getXmlTag() {
throw new UnsupportedOperationException("Method getXmlTag is not yet implemented in " + getClass().getName());
}
@NotNull
public <T extends DomElement> DomFileElement<T> getRoot() {
return (DomFileElement<T>)this;
}
@Override
@Nullable
public DomElement getParent() {
throw new UnsupportedOperationException("Method getParent is not yet implemented in " + getClass().getName());
}
@Override
public XmlTag ensureTagExists() {
throw new UnsupportedOperationException("Method ensureTagExists is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public XmlElement getXmlElement() {
throw new UnsupportedOperationException("Method getXmlElement is not yet implemented in " + getClass().getName());
}
@Override
public XmlElement ensureXmlElementExists() {
throw new UnsupportedOperationException("Method ensureXmlElementExists is not yet implemented in " + getClass().getName());
}
@Override
public void undefine() {
throw new UnsupportedOperationException("Method undefine is not yet implemented in " + getClass().getName());
}
@Override
public boolean isValid() {
throw new UnsupportedOperationException("Method isValid is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public DomGenericInfo getGenericInfo() {
throw new UnsupportedOperationException("Method getGenericInfo is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
@NonNls
public String getXmlElementName() {
throw new UnsupportedOperationException("Method getXmlElementName is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
@NonNls
public String getXmlElementNamespace() {
throw new UnsupportedOperationException("Method getXmlElementNamespace is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
@NonNls
public String getXmlElementNamespaceKey() {
throw new UnsupportedOperationException("Method getXmlElementNamespaceKey is not yet implemented in " + getClass().getName());
}
@Override
public void accept(final DomElementVisitor visitor) {
throw new UnsupportedOperationException("Method accept is not yet implemented in " + getClass().getName());
}
@Override
public void acceptChildren(DomElementVisitor visitor) {
}
@Override
@NotNull
public DomManager getManager() {
throw new UnsupportedOperationException("Method getManager is not yet implemented in " + getClass().getName());
}
@Override
public Type getDomElementType() {
throw new UnsupportedOperationException("Method getDomElementType is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public AbstractDomChildrenDescription getChildDescription() {
throw new UnsupportedOperationException("Method getChildDescription is not yet implemented in " + getClass().getName());
}
@Override
public DomNameStrategy getNameStrategy() {
throw new UnsupportedOperationException("Method getNameStrategy is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public ElementPresentation getPresentation() {
throw new UnsupportedOperationException("Method getPresentation is not yet implemented in " + getClass().getName());
}
@Override
public GlobalSearchScope getResolveScope() {
throw new UnsupportedOperationException("Method getResolveScope is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public <T extends DomElement> T getParentOfType(Class<T> requiredClass, boolean strict) {
throw new UnsupportedOperationException("Method getParentOfType is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public Module getModule() {
throw new UnsupportedOperationException("Method getModule is not yet implemented in " + getClass().getName());
}
@Override
public void copyFrom(DomElement other) {
throw new UnsupportedOperationException("Method copyFrom is not yet implemented in " + getClass().getName());
}
@Override
public <T extends DomElement> T createMockCopy(final boolean physical) {
throw new UnsupportedOperationException("Method createMockCopy is not yet implemented in " + getClass().getName());
}
@Override
public <T extends DomElement> T createStableCopy() {
throw new UnsupportedOperationException("Method createStableCopy is not yet implemented in " + getClass().getName());
}
@Override
@Nullable
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
throw new UnsupportedOperationException("Method getAnnotation is not yet implemented in " + getClass().getName());
}
@Override
public long getModificationCount() {
return myModCount;
}
public void incModificationCount() {
myModCount++;
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2000-2007 JetBrains s.r.o. All Rights Reserved.
*/
package com.intellij.util.xml;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class MockGenericAttributeValue extends MockDomElement implements GenericAttributeValue<Object> {
@Override
public XmlAttribute getXmlAttribute() {
throw new UnsupportedOperationException("Method getXmlAttribute is not yet implemented in " + getClass().getName());
}
@Override
public XmlAttributeValue getXmlAttributeValue() {
throw new UnsupportedOperationException("Method getXmlAttributeValue is not yet implemented in " + getClass().getName());
}
@Override
@NotNull
public Converter getConverter() {
throw new UnsupportedOperationException("Method getConverter is not yet implemented in " + getClass().getName());
}
@Override
public void setStringValue(String value) {
throw new UnsupportedOperationException("Method setStringValue is not yet implemented in " + getClass().getName());
}
@Override
public void setValue(Object value) {
throw new UnsupportedOperationException("Method setValue is not yet implemented in " + getClass().getName());
}
@Override
public String getStringValue() {
throw new UnsupportedOperationException("Method getStringValue is not yet implemented in " + getClass().getName());
}
@Override
public String getRawText() {
throw new UnsupportedOperationException("Method getRawText is not yet implemented in " + getClass().getName());
}
@Override
public Object getValue() {
throw new UnsupportedOperationException("Method getValue is not yet implemented in " + getClass().getName());
}
}
@@ -0,0 +1,44 @@
package com.intellij.util.xml;
import junit.framework.TestCase;
/**
* @author peter
*/
public class NameStrategyTest extends TestCase {
public void testHyphenStrategy() throws Throwable {
assertEquals("aaa-bbb-ccc", DomNameStrategy.HYPHEN_STRATEGY.convertName("aaaBbbCcc"));
assertEquals("aaa-bbb-ccc", DomNameStrategy.HYPHEN_STRATEGY.convertName("AaaBbbCcc"));
assertEquals("aaa", DomNameStrategy.HYPHEN_STRATEGY.convertName("Aaa"));
assertEquals("aaa", DomNameStrategy.HYPHEN_STRATEGY.convertName("aaa"));
assertEquals("AAA-bbb", DomNameStrategy.HYPHEN_STRATEGY.convertName("AAABbb"));
assertEquals("aaa-BBB", DomNameStrategy.HYPHEN_STRATEGY.convertName("AaaBBB"));
}
public void testHyphenStrategySplit() throws Throwable {
assertEquals("aaa bbb ccc", DomNameStrategy.HYPHEN_STRATEGY.splitIntoWords("aaa-bbb-ccc"));
assertEquals("Aaa", DomNameStrategy.HYPHEN_STRATEGY.splitIntoWords("Aaa"));
assertEquals("aaa", DomNameStrategy.HYPHEN_STRATEGY.splitIntoWords("aaa"));
assertEquals("AAA bbb", DomNameStrategy.HYPHEN_STRATEGY.splitIntoWords("AAA-bbb"));
assertEquals("aaa BBB", DomNameStrategy.HYPHEN_STRATEGY.splitIntoWords("aaa-BBB"));
}
public void testJavaStrategy() throws Throwable {
assertEquals("aaaBbbCcc", DomNameStrategy.JAVA_STRATEGY.convertName("aaaBbbCcc"));
assertEquals("aaaBbbCcc", DomNameStrategy.JAVA_STRATEGY.convertName("AaaBbbCcc"));
assertEquals("aaa", DomNameStrategy.JAVA_STRATEGY.convertName("Aaa"));
assertEquals("aaa", DomNameStrategy.JAVA_STRATEGY.convertName("aaa"));
assertEquals("AAABbb", DomNameStrategy.JAVA_STRATEGY.convertName("AAABbb"));
assertEquals("aaaBBB", DomNameStrategy.JAVA_STRATEGY.convertName("AaaBBB"));
}
public void testJavaStrategySplit() throws Throwable {
assertEquals("aaa bbb ccc", DomNameStrategy.JAVA_STRATEGY.splitIntoWords("aaaBbbCcc"));
assertEquals("aaa", DomNameStrategy.JAVA_STRATEGY.splitIntoWords("Aaa"));
assertEquals("aaa", DomNameStrategy.JAVA_STRATEGY.splitIntoWords("aaa"));
assertEquals("AAA bbb", DomNameStrategy.JAVA_STRATEGY.splitIntoWords("AAABbb"));
assertEquals("aaa BBB", DomNameStrategy.JAVA_STRATEGY.splitIntoWords("aaaBBB"));
}
}
@@ -0,0 +1,171 @@
package com.intellij.util.xml;
import com.intellij.util.ArrayUtil;
import junit.framework.TestCase;
import net.sf.cglib.proxy.AdvancedProxy;
import net.sf.cglib.proxy.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author peter
*/
public class ProxyTest extends TestCase {
public void testExtendClass() throws Throwable {
final List<String> invocations = new ArrayList<String>();
Implementation implementation = AdvancedProxy.createProxy(Implementation.class, new Class[]{Interface3.class}, new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
invocations.add(method.getName());
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
return Implementation.class.getMethod("getField").invoke(proxy);
}
}, "239");
implementation.hashCode();
implementation.method();
assertEquals("239", implementation.getFoo());
implementation.setField("42");
assertEquals("42", implementation.getBar());
assertEquals("42", implementation.toString());
assertEquals(Arrays.asList("hashCode", "getFoo", "getFoo", "getBar"), invocations);
assertEquals("42", Interface1.class.getMethod("getFoo").invoke(implementation));
assertEquals("42", Interface3.class.getMethod("bar").invoke(implementation));
assertEquals("42", Interface1.class.getMethod("foo").invoke(implementation));
assertEquals("42", Interface2.class.getMethod("foo").invoke(implementation));
assertEquals("42", Interface2.class.getMethod("foo").invoke(implementation));
assertEquals("42", Implementation.class.getMethod("foo").invoke(implementation));
}
public interface Interface1 {
Object getFoo();
Object foo();
}
public interface Interface2 extends Interface1 {
@Override
CharSequence getFoo();
@Override
CharSequence foo();
}
public interface Interface3 extends Interface1 {
@Override
String foo();
String bar();
}
private abstract static class Implementation implements Interface2 {
private String myField;
protected Implementation(final String field) {
myField = field;
}
public String getField() {
return myField;
}
public void setField(final String field) {
myField = field;
}
public void method() {
getFoo();
}
public String toString() {
return myField;
}
@Override
public abstract String getFoo();
public abstract String getBar();
}
public void testAddInterfaces() throws Throwable {
final BaseImpl proxy = AdvancedProxy.createProxy(BaseImpl.class, BaseIEx.class);
assertEquals(proxy.sayA(), "a");
assertEquals(((BaseI)proxy).sayA(), "a");
assertEquals(((BaseIEx)proxy).sayA(), "a");
}
public interface BaseI {
Object sayA();
}
public interface BaseIEx extends BaseI {
@Override
CharSequence sayA();
}
public static abstract class BaseImpl implements BaseI {
@Override
public String sayA() {
return "a";
}
}
public static abstract class AbstractBase implements BaseI {
@Override
public abstract String sayA();
public abstract static class AbstractBaseImpl extends AbstractBase {}
}
public void testCovariantFromInterface() throws Throwable {
final AbstractBase.AbstractBaseImpl proxy = AdvancedProxy.createProxy(AbstractBase.AbstractBaseImpl.class, ArrayUtil.EMPTY_CLASS_ARRAY,
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return "a";
}
}, false, new Object[0]);
assertEquals(proxy.sayA(), "a");
assertEquals(((AbstractBase)proxy).sayA(), "a");
assertEquals(((BaseI)proxy).sayA(), "a");
}
public static class CovariantFromBaseClassTest {
public static interface Intf {
String sayA();
}
public static class Base {
public Object sayA() {
return "beeee";
}
}
public abstract static class Impl extends Base implements Intf {
@Override
public abstract String sayA();
}
}
public void testCovariantFromBaseClass() throws Throwable {
final CovariantFromBaseClassTest.Impl proxy = AdvancedProxy.createProxy(CovariantFromBaseClassTest.Impl.class,
ArrayUtil.EMPTY_CLASS_ARRAY, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return "a";
}
}, false, new Object[0]);
assertEquals(proxy.sayA(), "a");
assertEquals(((CovariantFromBaseClassTest.Base)proxy).sayA(), "a");
assertEquals(((CovariantFromBaseClassTest.Intf)proxy).sayA(), "a");
}
}
@@ -0,0 +1,81 @@
package com.intellij.util.xml;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.events.DomEvent;
/**
* @author peter
*/
public class SimpleValuesIncrementalUpdateTest extends DomTestCase{
public void testAttributeChange() throws Throwable {
final MyElement element = createElement("<a/>");
element.getXmlTag().setAttribute("attr", "foo");
putExpected(new DomEvent(element, false));
assertResultsAndClear();
assertTrue(element.getAttr().isValid());
element.getXmlTag().setAttribute("bttr", "foo");
element.getXmlTag().setAttribute("attr", "bar");
putExpected(new DomEvent(element, false));
putExpected(new DomEvent(element, false));
assertResultsAndClear();
assertTrue(element.getAttr().isValid());
element.getXmlTag().setAttribute("attr", null);
putExpected(new DomEvent(element, false));
assertResultsAndClear();
assertTrue(element.getAttr().isValid());
}
public void testAttributeValueChangeAsXmlElementChange() throws Throwable {
final MyElement element = createElement("<a attr=\"foo\"/>");
final GenericAttributeValue<String> attr = element.getAttr();
attr.getXmlAttributeValue().getFirstChild().replace(createTag("<a attr=\"bar\"/>").getAttribute("attr", null).getValueElement().getFirstChild());
putExpected(new DomEvent(element, false));
assertResultsAndClear();
assertTrue(attr.isValid());
}
public void testTagValueChange() throws Throwable {
final MyElement element = createElement("<a><child> </child></a>").getChild();
element.getXmlTag().getValue().setText("abc");
putExpected(new DomEvent(element, false));
assertResultsAndClear();
element.getXmlTag().getValue().setText(null);
putExpected(new DomEvent(element, false));
assertResultsAndClear();
}
public void testAttrXmlEmptyUri() throws Throwable {
final MyElement element = createElement("<a xmlns=\"foo\"><ns-child attr=\"239\"/></a>" , MyElement.class);
getDomManager().getDomFileDescription(element.getXmlElement()).registerNamespacePolicy("foo", "foo");
final GenericAttributeValue<String> attr = element.getNsChild().getAttr();
attr.getXmlTag().setAttribute("attr", "42");
putExpected(new DomEvent(element.getNsChild(), false));
assertResultsAndClear();
}
private MyElement createElement(final String xml) throws IncorrectOperationException {
return createElement(xml, MyElement.class);
}
public interface MyElement extends DomElement{
GenericAttributeValue<String> getAttr();
Integer getValue();
MyElement getChild();
MyNsElement getNsChild();
}
@Namespace("foo")
public interface MyNsElement extends DomElement{
GenericAttributeValue<String> getAttr();
}
}
@@ -0,0 +1,17 @@
package com.intellij.util.xml;
/**
* @author peter
*/
public class StringBufferConverter extends Converter<StringBuffer> {
@Override
public StringBuffer fromString(final String s, final ConvertContext context) {
return s==null?null:new StringBuffer(s);
}
@Override
public String toString(final StringBuffer t, final ConvertContext context) {
return t==null?null:t.toString();
}
}
@@ -0,0 +1,133 @@
package com.intellij.util.xml.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomTestCase;
import com.intellij.util.xml.SubTag;
import com.intellij.util.xml.events.DomEvent;
import java.util.List;
/**
* @author peter
*/
public class IncrementalUpdateEventsTest extends DomTestCase {
private MyElement myElement;
@Override
protected void setUp() throws Exception {
super.setUp();
myElement = createElement("<a><child/><child/><child-element/><child-element/></a>");
}
public void testRemove0() throws IncorrectOperationException {
deleteTag(0);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
deleteTag(0);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
deleteTag(0);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
deleteTag(0);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testRemove1() throws IncorrectOperationException {
deleteTag(1);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testRemove2() throws IncorrectOperationException {
deleteTag(2);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
deleteTag(2);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testRemove3() throws IncorrectOperationException {
deleteTag(3);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testAdd0() throws Throwable {
addChildTag(0);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testAdd1() throws Throwable {
addChildTag(1);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testAdd2() throws Throwable {
addChildElementTag(2);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testAdd3() throws Throwable {
addChildElementTag(3);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
public void testAdd4() throws Throwable {
final XmlTag tag = myElement.getXmlTag();
tag.addAfter(createTag("<child-element/>"), tag.getSubTags()[3]);
putExpected(new DomEvent(myElement, false));
assertResultsAndClear();
}
private MyElement getChild(final int index) {
return myElement.getChildElements().get(index);
}
private void addChildTag(int index) throws IncorrectOperationException {
final XmlTag tag = myElement.getXmlTag();
tag.addBefore(createTag("<child/>"), tag.getSubTags()[index]);
}
private void addChildElementTag(int index) throws IncorrectOperationException {
final XmlTag tag = myElement.getXmlTag();
tag.addBefore(createTag("<child-element/>"), tag.getSubTags()[index]);
}
private void deleteTag(final int index) throws IncorrectOperationException {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
myElement.getXmlTag().getSubTags()[index].delete();
}
});
}
private MyElement createElement(final String xml) throws IncorrectOperationException {
return createElement(xml, MyElement.class);
}
public interface MyElement extends DomElement {
MyElement getChild();
@SubTag(value = "child", index = 1)
MyElement getChild2();
List<MyElement> getChildElements();
}
}
@@ -0,0 +1,694 @@
package com.intellij.util.xml.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.XmlElementFactory;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.*;
import com.intellij.util.xml.events.DomEvent;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
/**
* @author peter
*/
public class TreeIncrementalUpdateTest extends DomTestCase {
public void testRenameCollectionTag() throws Throwable {
final MyElement rootElement = createPhysicalElement(
"<?xml version='1.0' encoding='UTF-8'?>\n" + "<a>\n" + " <boy>\n" + " </boy>\n" + " <girl/>\n" + "</a>");
myCallRegistry.clear();
assertEquals(1, rootElement.getBoys().size());
assertEquals(1, rootElement.getGirls().size());
final MyElement oldBoy = rootElement.getBoys().get(0);
final XmlTag tag = oldBoy.getXmlTag();
assertNotNull(tag);
final int offset = tag.getTextOffset();
final int endoffset = offset+tag.getTextLength();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
rootElement.getGirls().get(0).undefine();
final Document document = getDocument(DomUtil.getFile(rootElement));
PsiDocumentManager.getInstance(getProject()).doPostponedOperationsAndUnblockDocument(document);
document.replaceString(offset+1, offset+1+"boy".length(), "girl");
commitDocument(document);
}
}.execute();
assertFalse(oldBoy.isValid());
assertEquals(0, rootElement.getBoys().size());
assertEquals(1, rootElement.getGirls().size());
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = getDocument(DomUtil.getFile(rootElement));
document.replaceString(endoffset - "boy".length(), endoffset, "girl");
commitDocument(document);
}
}.execute();
assertEquals(0, rootElement.getBoys().size());
assertEquals(1, rootElement.getGirls().size());
}
private MyElement createPhysicalElement(final String text) throws IncorrectOperationException {
final XmlFile file = (XmlFile)createFile("file.xml", text);
final DomFileElementImpl<MyElement> fileElement = getDomManager().getFileElement(file, MyElement.class, "a");
final MyElement rootElement = fileElement.getRootElement();
return rootElement;
}
public void testRenameFixedTag() throws Throwable {
final XmlFile file = (XmlFile)createFile("file.xml", "<?xml version='1.0' encoding='UTF-8'?>\n" +
"<a>\n" +
" <aboy>\n" +
" </aboy>\n" +
" <agirl/>\n" +
"</a>");
final DomFileElementImpl<MyElement> fileElement = getDomManager().getFileElement(file, MyElement.class, "a");
myCallRegistry.clear();
final MyElement rootElement = fileElement.getRootElement();
assertNotNull(rootElement.getAboy().getXmlElement());
assertNotNull(rootElement.getAgirl().getXmlElement());
final MyElement oldBoy = rootElement.getAboy();
final XmlTag tag = oldBoy.getXmlTag();
assertNotNull(tag);
final int offset = tag.getTextOffset();
final int endoffset = offset+tag.getTextLength();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
rootElement.getAgirl().undefine();
final Document document = getDocument(file);
PsiDocumentManager.getInstance(getProject()).doPostponedOperationsAndUnblockDocument(document);
document.replaceString(offset+1, offset+1+"aboy".length(), "agirl");
commitDocument(document);
}
}.execute();
assertFalse(oldBoy.isValid());
assertNull(rootElement.getAboy().getXmlElement());
assertNotNull(rootElement.getAgirl().getXmlElement());
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = getDocument(file);
document.replaceString(endoffset - "aboy".length(), endoffset, "agirl");
commitDocument(document);
}
}.execute();
assertNull(rootElement.getAboy().getXmlElement());
assertNotNull(rootElement.getAgirl().getXmlElement());
}
public void testDocumentChange() throws Throwable {
final XmlFile file = (XmlFile)createFile("file.xml", "<?xml version='1.0' encoding='UTF-8'?>\n" +
"<a>\n" +
" <child>\n" +
" <child/>\n" +
" </child>\n" +
"</a>");
final DomFileElementImpl<MyElement> fileElement =
getDomManager().getFileElement(file, MyElement.class, "a");
myCallRegistry.clear();
final MyElement rootElement = fileElement.getRootElement();
final MyElement oldLeaf = rootElement.getChild().getChild();
final XmlTag oldLeafTag = oldLeaf.getXmlTag();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = getDocument(file);
document.replaceString(0, document.getText().length(), "<a/>");
commitDocument(document);
}
}.execute();
assertFalse(oldLeafTag.isValid());
putExpected(new DomEvent(fileElement, false));
assertResultsAndClear();
assertEquals(fileElement.getRootElement(), rootElement);
assertTrue(rootElement.isValid());
assertFalse(oldLeaf.isValid());
assertTrue(rootElement.getChild().isValid());
assertNull(rootElement.getChild().getXmlTag());
assertNull(rootElement.getChild().getChild().getXmlTag());
}
public void testDocumentChange2() throws Throwable {
final XmlFile file = (XmlFile)createFile("file.xml", "<?xml version='1.0' encoding='UTF-8'?>\n" +
"<!DOCTYPE ejb-jar PUBLIC \"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN\" \"http://java.sun.com/dtd/ejb-jar_2_0.dtd\">\n" +
"<a>\n" +
" <child>\n" +
" <child/>\n" +
" </child>\n" +
"</a>");
final DomFileElementImpl<MyElement> fileElement =
getDomManager().getFileElement(file, MyElement.class, "a");
myCallRegistry.clear();
final MyElement rootElement = fileElement.getRootElement();
final MyElement oldLeaf = rootElement.getChild().getChild();
final XmlTag oldLeafTag = oldLeaf.getXmlTag();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
file.getDocument().getProlog().delete();
final XmlTag tag = file.getDocument().getRootTag();
tag.setAttribute("xmlns", "something");
tag.setAttribute("xmlns:xsi", "something");
}
}.execute();
assertTrue(oldLeafTag.isValid());
putExpected(new DomEvent(fileElement, false));
putExpected(new DomEvent(rootElement, false));
putExpected(new DomEvent(rootElement, false));
assertResultsAndClear();
assertEquals(fileElement.getRootElement(), rootElement);
assertTrue(rootElement.isValid());
assertTrue(rootElement.getChild().isValid());
assertTrue(rootElement.getChild().getXmlTag().isValid());
assertTrue(rootElement.getChild().getChild().getXmlTag().isValid());
}
public void testMoveUp() throws Throwable {
final XmlFile file = (XmlFile)createFile("file.xml", "<?xml version='1.0' encoding='UTF-8'?>\n" +
"<a>\n" +
" <child>\n" +
" <aboy />\n" +
" <agirl/>\n" +
" </child>\n" +
"</a>");
final DomFileElementImpl<MyElement> fileElement = getDomManager().getFileElement(file, MyElement.class, "a");
myCallRegistry.clear();
final MyElement rootElement = fileElement.getRootElement();
rootElement.getChild().getAboy();
rootElement.getChild().getAgirl();
final Document document = getDocument(file);
final int len = "<agirl/>".length();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final int agirl = document.getText().indexOf("<agirl/>");
final int boy = document.getText().indexOf("<aboy />");
document.replaceString(agirl, agirl + len, "<aboy />");
document.replaceString(boy, boy + len, "<agirl/>");
commitDocument(document);
}
}.execute();
assertTrue(rootElement.isValid());
final XmlTag tag1 = rootElement.getXmlTag().getSubTags()[0];
assertEquals(getDomManager().getDomElement(tag1.findFirstSubTag("agirl")), rootElement.getChild().getAgirl());
assertEquals(getDomManager().getDomElement(tag1.findFirstSubTag("aboy")), rootElement.getChild().getAboy());
}
public void testRemoveAttributeParent() throws Throwable {
final XmlFile file = (XmlFile)createFile("file.xml", "<?xml version='1.0' encoding='UTF-8'?>\n" +
"<!DOCTYPE ejb-jar PUBLIC \"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN\" \"http://java.sun.com/dtd/ejb-jar_2_0.dtd\">\n" +
"<a>\n" +
" <child-element xxx=\"239\"/>\n" +
"</a>");
final DomFileElementImpl<MyElement> fileElement =
getDomManager().getFileElement(file, MyElement.class, "a");
myCallRegistry.clear();
final MyElement rootElement = fileElement.getRootElement();
final MyElement oldLeaf = rootElement.getChildElements().get(0);
final GenericAttributeValue<String> xxx = oldLeaf.getXxx();
final XmlTag oldLeafTag = oldLeaf.getXmlTag();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
oldLeafTag.delete();
}
}.execute();
assertFalse(oldLeaf.isValid());
assertFalse(xxx.isValid());
}
public void testTypeBeforeRootTag() throws Throwable {
getDomManager().registerFileDescription(new DomFileDescription<MyElement>(MyElement.class, "a"), getTestRootDisposable());
final XmlFile file = (XmlFile)createFile("file.xml", "<?xml version='1.0' encoding='UTF-8'?>\n" +
"<a/>");
assertTrue(getDomManager().isDomFile(file));
final DomFileElementImpl<MyElement> fileElement = getDomManager().getFileElement(file, MyElement.class);
assertTrue(fileElement.isValid());
myCallRegistry.clear();
putExpected(new DomEvent(fileElement, false));
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = getDocument(file);
final int i = document.getText().indexOf("<a");
document.insertString(i, "a");
commitDocument(document);
}
}.execute();
assertFalse(getDomManager().isDomFile(file));
assertFalse(fileElement.isValid());
assertResultsAndClear();
}
private void assertNoCache(XmlTag tag) {
assertNull(tag.getText(), getCachedHandler(tag));
if (tag.isValid()) {
for (XmlTag xmlTag : tag.getSubTags()) {
assertNoCache(xmlTag);
}
}
}
private MyElement createElement(final String xml) throws IncorrectOperationException {
return createElement(xml, MyElement.class);
}
public void testAddCollectionElement() throws Throwable {
final MyElement element = createElement("<a><child/><child/><child-element/></a>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
final MyElement firstChild = element.getChildElements().get(0);
element.getXmlTag().add(createTag("<child-element/>"));
final XmlTag[] subTags = element.getXmlTag().getSubTags();
assertEquals(2, element.getChildElements().size());
assertEquals(firstChild, element.getChildElements().get(0));
MyElement nextChild = element.getChildElements().get(1);
putExpected(new DomEvent(element, false));
assertResultsAndClear();
}
public void testAddFixedElement() throws Throwable {
final MyElement element = createPhysicalElement("<a>" +
"<child/>" +
"<child><child/></child>" +
"<child/></a>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
final XmlTag leafTag = child2.getChild().getXmlTag();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
element.getXmlTag().addAfter(createTag("<child/>"), child.getXmlTag());
}
}.execute();
assertNoCache(leafTag);
final XmlTag[] subTags = element.getXmlTag().getSubTags();
assertFalse(child2.isValid());
assertEquals(child, element.getChild());
assertFalse(child2.equals(element.getChild2()));
assertCached(child, subTags[0]);
assertNoCache(subTags[2]);
assertNoCache(subTags[3]);
putExpected(new DomEvent(element, false));
putExpected(new DomEvent(element, false));
assertResultsAndClear();
}
public void testAddFixedElementCanDefineIt() throws Throwable {
final MyElement element = createElement("<a></a>");
final MyElement child = element.getChild();
element.getXmlTag().add(createTag("<child/>"));
final XmlTag[] subTags = element.getXmlTag().getSubTags();
assertTrue(child.equals(element.getChild()));
assertTrue(element.getChild().equals(child));
assertCached(element.getChild(), subTags[0]);
putExpected(new DomEvent(element, false));
assertResultsAndClear();
}
public void testActuallyRemoveCollectionElement() throws Throwable {
final MyElement element = createElement("<a><child-element><child/></child-element><child-element/></a>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
final MyElement firstChild = element.getChildElements().get(0);
final MyElement lastChild = element.getChildElements().get(1);
final XmlTag tag = element.getXmlTag();
final XmlTag childTag = tag.getSubTags()[0];
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
childTag.delete();
}
});
putExpected(new DomEvent(element, false));
assertResultsAndClear();
assertEquals(child, element.getChild());
assertEquals(child2, element.getChild2());
assertEquals(Arrays.asList(lastChild), element.getChildElements());
assertCached(lastChild, tag.getSubTags()[0]);
}
public void testCustomChildrenEvents() throws Throwable {
final Sepulka element = createElement("<a><foo/><bar/></a>", Sepulka.class);
final List<MyElement> list = element.getCustomChildren();
final XmlTag tag = element.getXmlTag();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
tag.getSubTags()[0].delete();
tag.getSubTags()[0].delete();
}
});
tag.add(createTag("<goo/>"));
putExpected(new DomEvent(element, false));
putExpected(new DomEvent(element, false));
putExpected(new DomEvent(element, false));
assertResultsAndClear();
assertEquals(1, element.getCustomChildren().size());
}
public void testRemoveFixedElement() throws Throwable {
final MyElement element = createElement("<a>" +
"<child/>" +
"<child><child/></child>" +
"<child><child/></child>" +
"</a>");
final MyElement child = element.getChild();
final MyElement child2 = element.getChild2();
final MyElement oldLeaf = child2.getChild();
final XmlTag tag = element.getXmlTag();
XmlTag leafTag = tag.getSubTags()[2].getSubTags()[0];
assertNoCache(leafTag);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
tag.getSubTags()[1].delete();
assertFalse(oldLeaf.isValid());
putExpected(new DomEvent(element, false));
assertResultsAndClear();
assertEquals(child, element.getChild());
assertFalse(child2.isValid());
tag.getSubTags()[1].delete();
}
});
putExpected(new DomEvent(element, false));
assertResultsAndClear();
}
public void testRootTagAppearsLater() throws Throwable {
final XmlFile file = createXmlFile("");
final DomFileElementImpl<MyElement> fileElement = getDomManager().getFileElement(file, MyElement.class, "root");
myCallRegistry.clear();
assertNull(fileElement.getRootElement().getXmlTag());
file.getDocument().replace(createXmlFile("<root/>").getDocument());
final XmlTag rootTag = fileElement.getRootTag();
assertEquals(rootTag, file.getDocument().getRootTag());
putExpected(new DomEvent(fileElement.getRootElement(), false));
assertResultsAndClear();
}
public void testAnotherChildren() throws Throwable {
final MyElement element = createElement("<a><child/></a>");
element.getXmlTag().add(createTag("<another-child/>"));
assertEquals(1, element.getAnotherChildren().size());
putExpected(new DomEvent(element, false));
assertResultsAndClear();
}
public void testInvalidateParent() throws Throwable {
final MyElement root = getDomManager().createMockElement(MyElement.class, null, true);
new WriteCommandAction<MyElement>(getProject()) {
@Override
protected void run(Result<MyElement> result) throws Throwable {
root.getChild().ensureTagExists();
root.getChild2().ensureTagExists();
final MyElement element = root.addChildElement().getChild();
result.setResult(element);
element.ensureTagExists().getValue().setText("abc");
root.addChildElement();
root.addChildElement();
}
}.execute().getResultObject();
assertTrue(root.isValid());
final MyElement element = root.getChildElements().get(0).getChild();
assertTrue(element.isValid());
final MyElement child = element.getChild();
final MyElement genericValue = child.getChild();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = getDocument(DomUtil.getFile(element));
final TextRange range = element.getXmlTag().getTextRange();
document.replaceString(range.getStartOffset(), range.getEndOffset(), "");
commitDocument(document);
}
}.execute();
assertFalse(genericValue.isValid());
assertFalse(child.isValid());
assertFalse(element.isValid());
}
public void testCollectionChildValidAfterFormattingReparse() throws Throwable {
final MyElement root = getDomManager().createMockElement(MyElement.class, null, true);
final MyElement element = new WriteCommandAction<MyElement>(getProject()) {
@Override
protected void run(Result<MyElement> result) throws Throwable {
result.setResult(root.addChildElement());
}
}.execute().getResultObject();
assertTrue(root.isValid());
assertNotNull(element.getXmlElement());
}
public void testChangeImplementationClass() throws Throwable {
getTypeChooserManager().registerTypeChooser(MyElement.class, createClassChooser());
try {
final MyElement element = getDomManager().createMockElement(MyElement.class, getModule(), true);
final DomFileElement<MyElement> root = DomUtil.getFileElement(element);
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
element.addChildElement().addChildElement();
}
}.execute();
final MyElement child = element.getChildElements().get(0);
MyElement grandChild = child.getChildElements().get(0);
assertTrue(child instanceof BarInterface);
assertTrue(grandChild instanceof BarInterface);
grandChild = element.getChildElements().get(0).getChildElements().get(0);
final XmlTag tag = grandChild.getXmlTag();
assertTrue(grandChild.isValid());
assertEquals(grandChild, root.getRootElement().getChildElements().get(0).getChildElements().get(0));
assertNotNull(element.getXmlTag());
assertNotNull(child.getXmlTag());
assertNotNull(tag);
assertTrue(tag.isValid());
myCallRegistry.clear();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
tag.add(XmlElementFactory.getInstance(getProject()).createTagFromText("<foo/>"));
}
}.execute();
assertTrue(root.isValid());
assertTrue(element.isValid());
assertTrue(grandChild.isValid());
final MyElement newChild = root.getRootElement().getChildElements().get(0);
assertTrue(newChild instanceof BarInterface);
final MyElement newGrandChild = newChild.getChildElements().get(0);
assertTrue(newGrandChild.isValid());
assertTrue(newGrandChild instanceof FooInterface);
putExpected(new DomEvent(child, false));
putExpected(new DomEvent(grandChild, false));
assertResultsAndClear();
} finally {
getTypeChooserManager().unregisterTypeChooser(MyElement.class);
}
}
public void testChangeImplementationClass_InCollection() throws Throwable {
getTypeChooserManager().registerTypeChooser(MyElement.class, createClassChooser());
try {
final MyElement element = getDomManager().createMockElement(MyElement.class, getModule(), true);
final DomFileElement<MyElement> root = DomUtil.getFileElement(element);
new WriteCommandAction<MyElement>(getProject()) {
@Override
protected void run(Result<MyElement> result) throws Throwable {
element.addChildElement().addChildElement();
}
}.execute().getResultObject();
final MyElement child = element.getChildElements().get(0);
final MyElement grandChild = child.getChildElements().get(0);
assertTrue(child instanceof BarInterface);
assertTrue(grandChild instanceof BarInterface);
assertTrue(element.isValid());
assertTrue(child.isValid());
assertTrue(grandChild.isValid());
assertNotNull(element.getXmlTag());
assertNotNull(child.getXmlTag());
final XmlTag tag = grandChild.getXmlTag();
assertNotNull(tag);
myCallRegistry.clear();
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
tag.add(XmlElementFactory.getInstance(getProject()).createTagFromText("<foo/>"));
}
}.execute();
assertTrue(root.isValid());
assertTrue(element.isValid());
assertTrue(child.isValid());
final MyElement newChild = element.getChildElements().get(0);
assertTrue(newChild.isValid());
assertTrue(newChild.getClass().toString(), newChild instanceof BarInterface);
assertTrue(grandChild.isValid());
final MyElement newGrandChild = newChild.getChildElements().get(0);
assertTrue(newGrandChild.isValid());
assertTrue(newGrandChild instanceof FooInterface);
putExpected(new DomEvent(child, false));
putExpected(new DomEvent(grandChild, false));
assertResultsAndClear();
} finally {
getTypeChooserManager().unregisterTypeChooser(MyElement.class);
}
}
/*
public void testCommentTag() throws Throwable {
final String prefix = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE application PUBLIC \"-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN\" \"http://java.sun.com/dtd/application_1_3.dtd\">\n" +
"<application>\n" + " <display-name>MyAppa</display-name>\n" + " <description>ss</description>\n" +
" <module id=\"MyWebApp2\">\n" + " <web> a\n" + " <web-uri>MyWebApp2.war</web-uri>\n" +
" ";
final String infix = "<context-root>MyWebApp2</context-root>";
String suffix = "\n" + " </web>\n" + " </module>\n" +
" <module id=\"MyWebApp22\">\n" + " <web>\n" + " <web-uri>MyWebApp2.war</web-uri>\n" +
" <context-root>MyWebApp2</context-root>\n" + " </web>\n" + " </module>\n" +
" <module id=\"MyEjb32\">\n" + " <ejb>MyEjb32.jar</ejb>\n" + " </module>\n" +
" <module id=\"MyEjb4\">\n" + " <ejb>MyEjb4.jar</ejb>\n" + " </module>\n" + " <security-role>\n" +
" <description>asdf</description>\n" + " <role-name>nameasdf</role-name>\n" +
" </security-role>\n" + "\n" + "</application>";
final XmlFile file = (XmlFile)createFile("web.xml", prefix + infix + suffix);
final JavaeeApplication javaeeApplication = getDomManager().getFileElement(file, JavaeeApplication.class).getRootElement();
assertEquals("MyWebApp2", javaeeApplication.getModules().get(0).getWeb().getContextRoot().getValue());
new WriteCommandAction(getProject()) {
@Override
protected void run(Result result) throws Throwable {
final Document document = getDocument(file);
document.insertString(prefix.length() + infix.length(), "-->");
document.insertString(prefix.length(), "<!--");
commitDocument(document);
}
}.execute();
assertTrue(javaeeApplication.isValid());
assertTrue(javaeeApplication.getModules().get(0).getWeb().getContextRoot().isValid());
assertTrue(javaeeApplication.getModules().get(0).getWeb().isValid());
assertNull(javaeeApplication.getModules().get(0).getWeb().getContextRoot().getXmlElement());
}
*/
private static TypeChooser createClassChooser() {
return new TypeChooser() {
@Override
public Type chooseType(final XmlTag tag) {
return tag != null && tag.findFirstSubTag("foo") != null
? FooInterface.class
: BarInterface.class;
}
@Override
public void distinguishTag(final XmlTag tag, final Type aClass)
throws IncorrectOperationException {
if (FooInterface.class.equals(aClass) && tag.findFirstSubTag("foo") == null) {
tag.add(XmlElementFactory.getInstance(getProject()).createTagFromText("<foo/>"));
}
}
@Override
public Type[] getChooserTypes() {
return new Class[]{FooInterface.class,
BarInterface.class};
}
};
}
public interface MyElement extends DomElement{
MyElement getChild();
@SubTag(value="child",index=1) MyElement getChild2();
List<MyElement> getChildElements();
List<MyElement> getBoys();
List<MyElement> getGirls();
List<MyElement> getAnotherChildren();
MyElement addChildElement();
GenericAttributeValue<String> getXxx();
MyElement getAboy();
MyElement getAgirl();
}
public interface FooInterface extends MyElement {
}
public interface BarInterface extends MyElement {
}
public interface Sepulka extends DomElement{
@CustomChildren
List<MyElement> getCustomChildren();
}
}
@@ -0,0 +1,57 @@
package com.intellij.util.xml.stubs;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.stubs.ObjectStubTree;
import com.intellij.psi.stubs.StubTreeLoader;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import com.intellij.util.xml.DomFileDescription;
import com.intellij.util.xml.DomManager;
import com.intellij.util.xml.impl.DomManagerImpl;
/**
* @author Dmitry Avdeev
* Date: 8/3/12
*/
public class DomStubsTest extends LightPlatformCodeInsightFixtureTestCase {
public void testDomLoading() throws Exception {
PsiFile psiFile = myFixture.configureByFile("foo.xml");
StubTreeLoader loader = StubTreeLoader.getInstance();
VirtualFile file = psiFile.getVirtualFile();
assertTrue(loader.canHaveStub(file));
ObjectStubTree stubTree = loader.readFromVFile(getProject(), file);
assertNotNull(stubTree);
}
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
public DomStubsTest() {
IdeaTestCase.initPlatformPrefix();
}
@Override
protected boolean isCommunity() {
return true;
}
private static final DomFileDescription<Foo> DOM_FILE_DESCRIPTION = new DomFileDescription<Foo>(Foo.class, "foo") {
@Override
public boolean hasStubs() {
return true;
}
};
@Override
public void setUp() throws Exception {
super.setUp();
((DomManagerImpl)DomManager.getDomManager(getProject())).registerFileDescription(DOM_FILE_DESCRIPTION, getTestRootDisposable());
}
@Override
protected String getBasePath() {
return "/xml/dom-tests/testData/stubs";
}
}
@@ -0,0 +1,10 @@
package com.intellij.util.xml.stubs;
import com.intellij.util.xml.DomElement;
/**
* @author Dmitry Avdeev
* Date: 8/3/12
*/
public interface Foo extends DomElement {
}