blob: 52fb77ece4c2bc535f9ceadfa18794e1cbe87cc8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Technical University Berlin - adapted for Object Teams
*******************************************************************************/
package org.eclipse.jdt.core.tests.dom;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import junit.framework.Test;
import org.eclipse.jdt.core.dom.*;
@SuppressWarnings({"rawtypes", "unchecked"})
public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase {
/** @deprecated using deprecated code */
public static Test suite() {
// TODO (frederic) use buildList + setAstLevel(init) instead...
junit.framework.TestSuite suite = new junit.framework.TestSuite(ASTStructuralPropertyTest.class.getName());
Class c = ASTStructuralPropertyTest.class;
Method[] methods = c.getMethods();
for (int i = 0, max = methods.length; i < max; i++) {
if (methods[i].getName().startsWith("test")) { //$NON-NLS-1$
suite.addTest(new ASTStructuralPropertyTest(methods[i].getName(), AST.JLS2));
suite.addTest(new ASTStructuralPropertyTest(methods[i].getName(), AST.JLS3));
suite.addTest(new ASTStructuralPropertyTest(methods[i].getName(), AST.JLS4));
suite.addTest(new ASTStructuralPropertyTest(methods[i].getName(), AST.JLS8));
}
}
return suite;
}
AST ast;
ASTParser parser;
int API_LEVEL;
public ASTStructuralPropertyTest(String name) {
super(name.substring(0, name.indexOf(" - JLS")));
name.indexOf(" - JLS");
this.API_LEVEL = Integer.parseInt(name.substring(name.indexOf(" - JLS") + 6));
}
public ASTStructuralPropertyTest(String name, int apiLevel) {
super(name);
this.API_LEVEL = apiLevel;
}
protected void setUp() throws Exception {
super.setUp();
this.ast = AST.newAST(this.API_LEVEL, true);
this.parser = ASTParser.newParser(this.API_LEVEL);
}
protected void tearDown() throws Exception {
this.ast = null;
super.tearDown();
}
public String getName() {
String name = super.getName() + " - JLS" + this.API_LEVEL;
return name;
}
public void testLocationInParent() {
final ASTNode root = SampleASTs.oneOfEach(this.ast);
ASTVisitor v = new ASTVisitor(true) {
public void postVisit(ASTNode node) {
StructuralPropertyDescriptor me = node.getLocationInParent();
assertTrue(me != null || (node == root));
ASTNode p = node.getParent();
if (p != null) {
List parentProperties = p.structuralPropertiesForType();
boolean foundMe = false;
for (Iterator it = parentProperties.iterator(); it
.hasNext();) {
StructuralPropertyDescriptor prop =
(StructuralPropertyDescriptor) it.next();
if (me == prop || prop.getId().equals(me.getId())) {
foundMe = true;
break;
}
}
assertTrue(foundMe);
}
}
};
root.accept(v);
}
/**
* @deprecated since using deprecated constant
*/
public void testStructuralProperties() {
final ASTNode root = SampleASTs.oneOfEach(this.ast);
final Set simpleProperties = new LinkedHashSet(400);
final Set childProperties = new LinkedHashSet(400);
final Set childListProperties = new LinkedHashSet(400);
final Set visitedProperties = new LinkedHashSet(400);
final Set nodeClasses = new LinkedHashSet(100);
ASTVisitor v = new ASTVisitor(true) {
public void postVisit(ASTNode node) {
StructuralPropertyDescriptor me = node.getLocationInParent();
if (me != null) {
visitedProperties.add(me);
}
nodeClasses.add(node.getClass());
List ps = node.structuralPropertiesForType();
for (Iterator it = ps.iterator(); it.hasNext(); ) {
StructuralPropertyDescriptor p = (StructuralPropertyDescriptor) it.next();
Object o = node.getStructuralProperty(p);
if (p.isSimpleProperty()) {
simpleProperties.add(p);
// slam simple properties
node.setStructuralProperty(p, o);
} else if (p.isChildProperty()) {
childProperties.add(p);
// replace child with a copy
ASTNode copy = ASTNode.copySubtree(ASTStructuralPropertyTest.this.ast, (ASTNode) o);
node.setStructuralProperty(p, copy);
} else if (p.isChildListProperty()) {
childListProperties.add(p);
// replace child list with copies
List list = (List) o;
List copy = ASTNode.copySubtrees(ASTStructuralPropertyTest.this.ast, list);
list.clear();
list.addAll(copy);
}
}
}
};
root.accept(v);
switch(this.API_LEVEL) {
case AST.JLS2 :
assertEquals("Wrong number of visited node classes", 67, nodeClasses.size());
assertEquals("Wrong number of visited properties", 81, visitedProperties.size());
//{ObjectTeams: 2 new simple properties in TypeDeclaration: TEAM_PROPERTY and ROLE_PROPERTY:
/* orig:
assertEquals("Wrong number of simple properties", 26, simpleProperties.size());
:giro */
assertEquals("Wrong number of simple properties", 28, simpleProperties.size());
// 2 new child properties: GUARD_PROPERTY (in TypeDeclaration and MethodDeclaration)
/* orig:
assertEquals("Wrong number of child properties", 90, childProperties.size());
:giro */
assertEquals("Wrong number of child properties", 92, childProperties.size());
// 1 new child list property: PRECEDENCES_PROPERTY
/* orig:
assertEquals("Wrong number of child list properties", 26, childListProperties.size());
:giro */
assertEquals("Wrong number of child list properties", 27, childListProperties.size());
// SH}
break;
case AST.JLS3 :
assertEquals("Wrong number of visited node classes", 80, nodeClasses.size());
assertEquals("Wrong number of visited properties", 103, visitedProperties.size());
//{ObjectTeams: 2 new simple properties in TypeDeclaration: TEAM_PROPERTY and ROLE_PROPERTY:
// 1 new property in ImportDeclaration: BASE_PROPERTY
/* orig:
assertEquals("Wrong number of simple properties", 23, simpleProperties.size());
:giro */
assertEquals("Wrong number of simple properties", 26, simpleProperties.size());
// 2 new child properties: GUARD_PROPERTY (in TypeDeclaration and MethodDeclaration)
/* orig:
assertEquals("Wrong number of child properties", 115, childProperties.size());
:giro */
assertEquals("Wrong number of child properties", 117, childProperties.size());
// 2 new child list properties: TypeDeclaration.PRECEDENCES_PROPERTY, PackageDeclaration.MODIFIERS_PROPERTY
/* orig:
assertEquals("Wrong number of child list properties", 52, childListProperties.size());
:giro */
assertEquals("Wrong number of child list properties", 54, childListProperties.size());
// SH}
break;
case AST.JLS4 :
assertEquals("Wrong number of visited node classes", 81, nodeClasses.size());
assertEquals("Wrong number of visited properties", 103, visitedProperties.size());
//{ObjectTeams: 2 new simple properties in TypeDeclaration: TEAM_PROPERTY and ROLE_PROPERTY:
// 1 new property in ImportDeclaration: BASE_PROPERTY
/* orig:
assertEquals("Wrong number of simple properties", 23, simpleProperties.size());
:giro */
assertEquals("Wrong number of simple properties", 26, simpleProperties.size());
// 2 new child properties: GUARD_PROPERTY (in TypeDeclaration and MethodDeclaration)
/* orig:
assertEquals("Wrong number of child properties", 115, childProperties.size());
:giro */
assertEquals("Wrong number of child properties", 117, childProperties.size());
// 2 new child list properties: TypeDeclaration.PRECEDENCES_PROPERTY, PackageDeclaration.MODIFIERS_PROPERTY
/* orig:
assertEquals("Wrong number of child list properties", 54, childListProperties.size());
:giro */
assertEquals("Wrong number of child list properties", 56, childListProperties.size());
// SH}
break;
case AST.JLS8 :
assertEquals("Wrong number of visited node classes", 84, nodeClasses.size());
assertEquals("Wrong number of visited properties", 106, visitedProperties.size());
//{ObjectTeams: 2 new simple properties in TypeDeclaration: TEAM_PROPERTY and ROLE_PROPERTY:
// 1 new property in ImportDeclaration: BASE_PROPERTY
/* orig:
assertEquals("Wrong number of simple properties", 21, simpleProperties.size());
:giro */
assertEquals("Wrong number of simple properties", 24, simpleProperties.size());
// 2 new child properties: GUARD_PROPERTY (in TypeDeclaration and MethodDeclaration)
/* orig:
assertEquals("Wrong number of child properties", 118, childProperties.size());
:giro */
assertEquals("Wrong number of child properties", 120, childProperties.size());
// 2 new child list properties: TypeDeclaration.PRECEDENCES_PROPERTY, PackageDeclaration.MODIFIERS_PROPERTY
/* orig:
assertEquals("Wrong number of child list properties", 66, childListProperties.size());
:giro */
assertEquals("Wrong number of child list properties", 68, childListProperties.size());
// SH}
break;
default :
fail();
}
// visit should rebuild tree
ASTNode newRoot = SampleASTs.oneOfEach(this.ast);
assertTrue(root.subtreeMatch(new ASTMatcher(), newRoot));
}
public void testProtect() {
final ASTNode root = SampleASTs.oneOfEach(this.ast);
// check that all properties are again modifiable
class Slammer extends ASTVisitor {
boolean shouldBeProtected;
Slammer(boolean shouldBeProtected){
super(true); // visit doc
this.shouldBeProtected = shouldBeProtected;
}
public void postVisit(ASTNode node) {
try {
node.setSourceRange(1, 1);
assertTrue(!this.shouldBeProtected);
} catch (RuntimeException e) {
assertTrue(this.shouldBeProtected);
}
List ps = node.structuralPropertiesForType();
for (Iterator it = ps.iterator(); it.hasNext(); ) {
StructuralPropertyDescriptor p = (StructuralPropertyDescriptor) it.next();
Object o = node.getStructuralProperty(p);
if (p.isSimpleProperty()) {
// slam simple properties
try {
node.setStructuralProperty(p, o);
assertTrue(!this.shouldBeProtected);
} catch (RuntimeException e) {
assertTrue(this.shouldBeProtected);
}
} else if (p.isChildProperty()) {
// replace child with a copy
ASTNode copy = ASTNode.copySubtree(ASTStructuralPropertyTest.this.ast, (ASTNode) o);
try {
node.setStructuralProperty(p, copy);
assertTrue(!this.shouldBeProtected);
} catch (RuntimeException e) {
assertTrue(this.shouldBeProtected);
}
} else if (p.isChildListProperty()) {
// replace child list with copies
List list = (List) o;
List copy = ASTNode.copySubtrees(ASTStructuralPropertyTest.this.ast, list);
if (!list.isEmpty()) {
try {
list.clear();
assertTrue(!this.shouldBeProtected);
} catch (RuntimeException e) {
assertTrue(this.shouldBeProtected);
}
try {
list.addAll(copy);
assertTrue(!this.shouldBeProtected);
} catch (RuntimeException e) {
assertTrue(this.shouldBeProtected);
}
}
}
}
}
}
class Protector extends ASTVisitor {
boolean shouldBeProtected;
Protector(boolean shouldBeProtected){
super(true); // visit doc
this.shouldBeProtected = shouldBeProtected;
}
public void preVisit(ASTNode node) {
int f = node.getFlags();
if (this.shouldBeProtected) {
f |= ASTNode.PROTECT;
} else {
f &= ~ASTNode.PROTECT;
}
node.setFlags(f);
}
}
// mark all nodes as protected
root.accept(new Protector(true));
root.accept(new Slammer(true));
// mark all nodes as unprotected
root.accept(new Protector(false));
root.accept(new Slammer(false));
}
public void testDelete() {
final ASTNode root = SampleASTs.oneOfEach(this.ast);
// check that nodes can be deleted unless mandatory
root.accept(new ASTVisitor(true) {
public void postVisit(ASTNode node) {
List ps = node.structuralPropertiesForType();
for (Iterator it = ps.iterator(); it.hasNext(); ) {
StructuralPropertyDescriptor p = (StructuralPropertyDescriptor) it.next();
if (p.isChildProperty()) {
ChildPropertyDescriptor c = (ChildPropertyDescriptor) p;
ASTNode child = (ASTNode) node.getStructuralProperty(c);
if (!c.isMandatory() && child != null) {
try {
child.delete();
assertTrue(node.getStructuralProperty(c) == null);
} catch (RuntimeException e) {
assertTrue(false);
}
}
} else if (p.isChildListProperty()) {
// replace child list with copies
List list = (List) node.getStructuralProperty(p);
// iterate over a copy and try removing all members
List copy = new ArrayList();
copy.addAll(list);
for (Iterator it2 = copy.iterator(); it2.hasNext(); ) {
ASTNode n = (ASTNode) it2.next();
try {
n.delete();
assertTrue(!list.contains(n));
} catch (RuntimeException e) {
assertTrue(false);
}
}
}
}
}
});
}
/** @deprecated using deprecated code */
public void testCreateInstance() {
int maxNodeType;
switch (this.ast.apiLevel()) {
case AST.JLS2:
maxNodeType = 69;
break;
case AST.JLS3:
maxNodeType = 83;
break;
case AST.JLS4:
maxNodeType = 84;
break;
case AST.JLS8:
maxNodeType = 92;
break;
default:
fail();
return;
}
for (int nodeType = 0; nodeType < 100; nodeType++) {
Class nodeClass = null;
try {
nodeClass = ASTNode.nodeClassForType(nodeType);
} catch (IllegalArgumentException e) {
// oops - guess that's not valid
}
if (nodeClass != null) {
try {
ASTNode node = this.ast.createInstance(nodeClass);
//{ObjectTeams: adpated for new OT-specific ASTNodes
if ((nodeType >= 85) && (nodeType <= 100)) {
// good: OT node
} else
// SH}
assertTrue(nodeType <= maxNodeType);
assertTrue(node.getNodeType() == nodeType);
//ASTNode node2 = ast.createInstance(nodeType);
//assertTrue(node2.getNodeType() == nodeType);
} catch (RuntimeException e) {
assertTrue((nodeType < 1) || (nodeType > maxNodeType));
}
}
}
}
public void testNodeClassForType() {
//{ObjectTeams: larger range:
/* orig:
Set classes = new HashSet(103);
// make sure node types are contiguous starting at 0
int hi = 0;
for (int nodeType = 1; nodeType < 110; nodeType++) {
:giro */
Set classes = new HashSet(133);
// make sure node types are contiguous starting at 0
int hi = 0;
for (int nodeType = 1; nodeType < 133; nodeType++) {
// SH}
try {
Class nodeClass = ASTNode.nodeClassForType(nodeType);
assertTrue(ASTNode.class.isAssignableFrom(nodeClass));
classes.add(nodeClass);
if (nodeType > 1) {
assertTrue(hi == nodeType - 1);
}
hi = nodeType;
} catch (IllegalArgumentException e) {
// oops - guess that's not valid
}
}
// {ObjectTeams: adapted for OT specific ASTNodes
/* orig:
assertEquals("Wrong last known type", 109, hi); // last known one
:giro */
assertEquals("Wrong last known type", 127, hi); // last known one
// jwl}
assertEquals("Wrong number of distinct types", hi, classes.size()); // all classes are distinct
}
}