/*******************************************************************************
* Copyright (c) 2010 Michal Antkiewicz.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michal Antkiewicz - initial API and implementation
******************************************************************************/
package ca.uwaterloo.gsd.fsml.javaMappingInterpreter;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.AssertStatement;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BlockComment;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.BooleanLiteral;
import org.eclipse.jdt.core.dom.BreakStatement;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.CharacterLiteral;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.ContinueStatement;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EmptyStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.InstanceofExpression;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.LineComment;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MemberRef;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.MethodRefParameter;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.NullLiteral;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PostfixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.SynchronizedStatement;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TextElement;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.dom.WildcardType;
class StackEntry {
public final ASTNode node;
public ASTNode nearestChild;
public final List<VarDesc> vars;
public StackEntry(ASTNode node) {
this.node=node;
vars=new ArrayList<VarDesc>();
}
public String toString() {
return node.getClass().getSimpleName()+" ["+vars.size()+"]";
}
}
public class VarCollector extends JDTVisitor
{
private String fSource;
private int fOffset;
// private CumulativeProgressMonitor fMonitor;
private int level;
private final List<StackEntry> stack;
public VarCollector() {
this.stack=new ArrayList<StackEntry>();
level=0;
}
public void collect(CompilationUnit cu, String source, int offset) {
this.fOffset=offset;
this.fSource=source;
// fMonitor=new CumulativeProgressMonitor(monitor);
// fMonitor.beginTask("", offset);
expand(list(cu),true);
// fMonitor.done();
}
public void printStack() {
for(StackEntry entry: stack) {
System.out.println(">>"+entry.node.getClass().getSimpleName());
for(VarDesc var: entry.vars)
System.out.println("++"+var.type+" "+var.name);
}
}
public boolean isInsideMethod() {
if(stack.isEmpty()) return false;
for(int i=stack.size()-1;i>=0;i--) {
ASTNode node = stack.get(i).node;
switch(node.getNodeType()) {
case ASTNode.METHOD_DECLARATION:
if(!nodeContainsOffset(node, fOffset))
return false;
return true;
case ASTNode.TYPE_DECLARATION:
case ASTNode.ENUM_DECLARATION:
return false;
}
}
return false;
}
public VarDesc getExpectedType() {
if(fSource==null) return null;
if(stack.isEmpty()) return null;
/*
* Assignment "=": VariableDeclarationFragment, Assignment, SingleVariableDeclaration??
* Call "(", ",": ClassInstanceCreation, ConstructorInvocation, MethodInvocation, SuperConstructorInvocation, SuperMethodInvocation
* Return "return": ReturnStatement
* Array Init "{", ",": ArrayInitializer
* Ternary "?", ":": ConditionalExpression
*/
int pos=fOffset-1;
while(pos>=0 && Character.isWhitespace(fSource.charAt(pos))) pos--;
if(pos<0) return null;
char marker=fSource.charAt(pos);
if(marker=='=') { //probably assignment
//rewind further to finid the var name; the "=" will not be part of the AST when the assignment is incomplete
pos--; while(pos>=0 && Character.isWhitespace(fSource.charAt(pos))) pos--;
if(pos<0) return null;
ASTNode assigner=lastNodeContaining(pos);
if(assigner==null) return null;
if(assigner.getNodeType()==ASTNode.VARIABLE_DECLARATION_FRAGMENT) {
return makeDesc((VariableDeclarationFragment) assigner);
} else if(assigner.getNodeType()==ASTNode.ASSIGNMENT) {
ITypeBinding type=((Assignment)assigner).resolveTypeBinding();
return makeDesc(type);
}
} else if(marker=='(') { //probably call
ASTNode callNode=lastNodeContaining(pos);
if(callNode==null) return null;
return getParameterType(callNode, 0);
} else if(marker=='{') { //possibly array init
ASTNode initNode=lastNodeContaining(pos);
if(initNode==null) return null;
return getArrayInitType(initNode);
} else if(marker==',') { //may be call or array init
//walk back to try and find an opening brace, counting the numbr of commas
int idx=0;
int bscope=0, cscope=0;
while(pos>=0) {
marker=fSource.charAt(pos);
if(marker=='(') {
if(cscope==0) {
if(bscope==0) break;
bscope--;
}
} else if(marker==')') {
if(cscope==0) bscope++;
} else if(marker=='{') {
if(bscope==0) {
if(cscope==0) break;
cscope--;
}
} else if(marker=='}') {
if(bscope==0) cscope++;
} else if(marker==',') {
if(bscope==0 && cscope==0) idx++;
}
pos--;
}
if(pos<0) return null;
ASTNode node=lastNodeContaining(pos);
if(node==null) return null;
if(marker=='(')
return getParameterType(node, idx);
else if(marker=='{')
return getArrayInitType(node);
} else if(marker=='n') { //"return"?
if(pos<5) return null;
if(!fSource.regionMatches(pos-5, "return", 0, 6)) return null;
ASTNode method=lastNodeOfType(ASTNode.METHOD_DECLARATION);
if(!(method instanceof MethodDeclaration)) return null;
IMethodBinding methodBinding = ((MethodDeclaration)method).resolveBinding();
if(methodBinding==null) return null;
return makeDesc(methodBinding.getReturnType());
}
return null;
}
private VarDesc getArrayInitType(ASTNode initNode) {
if(initNode.getNodeType()==ASTNode.ARRAY_INITIALIZER) {
ITypeBinding binding=((ArrayInitializer)initNode).resolveTypeBinding();
if(binding==null) return null;
//the binding represents an array type, so peel off one dimension
return makeDesc(binding.getComponentType());
}
return null;
}
private VarDesc getParameterType(ASTNode callNode, int argId) {
IMethodBinding binding=null;
if(callNode.getNodeType()==ASTNode.METHOD_INVOCATION) {
binding = ((MethodInvocation)callNode).resolveMethodBinding();
} else if(callNode.getNodeType()==ASTNode.CLASS_INSTANCE_CREATION) {
binding = ((ClassInstanceCreation)callNode).resolveConstructorBinding();
} else if(callNode.getNodeType()==ASTNode.CONSTRUCTOR_INVOCATION) {
binding = ((ConstructorInvocation)callNode).resolveConstructorBinding();
} else if(callNode.getNodeType()==ASTNode.SUPER_CONSTRUCTOR_INVOCATION) {
binding = ((SuperConstructorInvocation)callNode).resolveConstructorBinding();
} else if(callNode.getNodeType()==ASTNode.SUPER_METHOD_INVOCATION) {
binding = ((SuperMethodInvocation)callNode).resolveMethodBinding();
}
if(binding==null) return null;
ITypeBinding[] params = binding.getParameterTypes();
if(argId>=params.length) return null;
return makeDesc(params[argId]);
}
public ASTNode getLastContainingStatement() {
if(stack.isEmpty()) return null;
for(int i=stack.size()-1;i>=0;i--) {
ASTNode node=stack.get(i).node;
if(node instanceof Statement) {
if(node.getNodeType()==ASTNode.BLOCK) return null;
if(statementIsComplete(node) && !nodeContainsOffset(node, fOffset)) return null;
return node;
}
}
return null;
}
private ASTNode getLastNode() {
if(stack.isEmpty()) return null;
return stack.get(stack.size()-1).node;
}
public int getNewDeclarationOffset() {
if(stack.size()<2) return -1;
ASTNode lastNonBlock=getLastNode();
if(lastNonBlock.getNodeType()==ASTNode.BLOCK) return fOffset;
for(int i=stack.size()-2;i>=0;i--) {
ASTNode node=stack.get(i).node;
if(node.getNodeType()==ASTNode.BLOCK) {
if(lastNonBlock==null) return -1;
return lastNonBlock.getStartPosition();
}
lastNonBlock=node;
}
return -1;
}
public int getNewMethodOffset() {
if(stack.size()<2) return -1;
//first just try to find the method we're in and report its end
for(int i=stack.size()-1;i>=0;i--) {
ASTNode node=stack.get(i).node;
if(node.getNodeType()==ASTNode.METHOD_DECLARATION) {
return node.getStartPosition()+node.getLength()-1;
}
}
//failing that, try to find a containing type declaration
for(int i=stack.size()-1;i>=0;i--) {
ASTNode node=stack.get(i).node;
List<BodyDeclaration> declarations=null;
if(node.getNodeType()==ASTNode.TYPE_DECLARATION) {
declarations=((TypeDeclaration)node).bodyDeclarations();
} else if(node.getNodeType()==ASTNode.ANONYMOUS_CLASS_DECLARATION) {
declarations=((AnonymousClassDeclaration)node).bodyDeclarations();
}
//then pick the first body declaration that gets past our offset (or simply the last if all come before)
if(declarations!=null && !declarations.isEmpty()) {
BodyDeclaration last=null;
for(BodyDeclaration decl: declarations) {
last=decl;
if(decl.getStartPosition()+decl.getLength()>=fOffset)
break;
}
if(last!=null)
return last.getStartPosition()+last.getLength()-1;
}
}
return -1;
}
public List<VarDesc> getDeclarations() {
List<VarDesc> vars=new ArrayList<VarDesc>();
boolean doLocals=true;
boolean doMemberFields=true;
boolean inLastType=true;
for(int i=stack.size()-1;i>=0;i--) {
StackEntry entry = stack.get(i);
for(int j=entry.vars.size()-1;j>=0;j--) {
VarDesc desc=entry.vars.get(j);
switch(desc.kind) {
case VarDesc.LOCAL:
if(doLocals)
vars.add(desc);
break;
case VarDesc.MEMBER:
if(doMemberFields)
vars.add(desc);
break;
case VarDesc.STATIC:
vars.add(desc);
break;
}
}
ASTNode node=entry.node;
switch(node.getNodeType()) {
case ASTNode.METHOD_DECLARATION: {
doLocals=false;
break;
}
case ASTNode.ANONYMOUS_CLASS_DECLARATION: {
if(inLastType) {
AnonymousClassDeclaration decl=(AnonymousClassDeclaration) node;
if(decl.getParent().getNodeType()==ASTNode.CLASS_INSTANCE_CREATION) {
ClassInstanceCreation cic=(ClassInstanceCreation) decl.getParent();
vars.add(makeDesc(cic.getType(),0,VarDesc.SPECIAL,"this"));
}
}
doLocals=false;
inLastType=false;
break;
}
case ASTNode.TYPE_DECLARATION: {
TypeDeclaration decl=(TypeDeclaration) node;
if(inLastType || doMemberFields) {
Type type=null;
type=decl.getSuperclassType();
if(type==null && !decl.superInterfaceTypes().isEmpty()) {
type=((List<Type>)decl.superInterfaceTypes()).get(0);
}
if(type!=null) {
if(inLastType) {
vars.add(makeDesc(type,0,VarDesc.SPECIAL,"this"));
} else if(doMemberFields) {
vars.add(makeDesc(type,0,VarDesc.SPECIAL,decl.getName().getIdentifier()+".this"));
}
}
}
if(hasStaticMod(decl.modifiers()))
doMemberFields=false;
doLocals=false;
inLastType=false;
}
}
}
return vars;
}
private ASTNode lastNodeOfType(int type) {
for(int i=stack.size()-1;i>=0;i--) {
ASTNode node = stack.get(i).node;
if(node.getNodeType()==type)
return node;
}
return null;
}
private ASTNode lastNodeContaining(int offset) {
for(int i=stack.size()-1;i>=0;i--) {
ASTNode node = stack.get(i).node;
if(nodeContainsOffset(node,offset) && node.getNodeType()!=ASTNode.SIMPLE_NAME)
return node;
}
return null;
}
private void push(ASTNode node) {
assert stack.size()==level;
stack.add(new StackEntry(node));
}
private VarDesc makeDesc(VariableDeclarationFragment frag) {
if(frag==null) return null;
String name=frag.getName().getIdentifier();
ASTNode parent=frag.getParent();
switch(parent.getNodeType()) {
case ASTNode.VARIABLE_DECLARATION_STATEMENT:
return makeDesc(
((VariableDeclarationStatement)parent).getType(),
frag.getExtraDimensions(),
VarDesc.LOCAL,name
);
case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
return makeDesc(
((VariableDeclarationExpression)parent).getType(),
frag.getExtraDimensions(),
VarDesc.LOCAL,name
);
case ASTNode.FIELD_DECLARATION: {
FieldDeclaration decl=(FieldDeclaration) parent;
int kind=hasStaticMod(decl.modifiers())?VarDesc.STATIC:VarDesc.MEMBER;
return makeDesc(
decl.getType(),
frag.getExtraDimensions(),
kind,name
);
}
}
return null;
}
private VarDesc makeDesc(SingleVariableDeclaration svd) {
if(svd==null) return null;
return makeDesc(
svd.getType(),
svd.getExtraDimensions(),
VarDesc.LOCAL,
svd.getName().getIdentifier()
);
}
private VarDesc makeDesc(Type type, int xtraDim, int kind, String name) {
while(type.isArrayType()) {
type=((ArrayType)type).getComponentType();
xtraDim++;
}
return new VarDesc(type,xtraDim,kind,name);
}
private VarDesc makeDesc(ITypeBinding type) {
if(type==null) return null;
return new VarDesc(type);
}
private void add(VariableDeclarationFragment frag) {
add(makeDesc(frag));
// fMonitor.workedTotal(frag.getStartPosition());
}
private void add(SingleVariableDeclaration svd) {
add(makeDesc(svd));
// fMonitor.workedTotal(svd.getStartPosition());
}
private void add(VarDesc var) {
List<VarDesc> varList=stack.get(level-1).vars;
varList.add(var);
}
private void addFrags(List<VariableDeclarationFragment> frags) {
for(VariableDeclarationFragment frag: frags) {
add(frag);
}
}
private boolean statementIsComplete(ASTNode stmt) {
if(fSource==null) return true;
int endpos=stmt.getStartPosition()+stmt.getLength()-1;
return fSource.charAt(endpos)==';';
}
private void addFragsIfPast(ASTNode container, List<VariableDeclarationFragment> frags) {
if(frags.isEmpty()) return;
if(fSource==null) return;
if(!statementIsComplete(container)) return;
if(nodeContainsOffset(container, fOffset)) return;
addFrags(frags);
}
private static boolean hasStaticMod(List<IExtendedModifier> modifiers) {
for(IExtendedModifier mod: modifiers) {
if(mod.isModifier())
if(((Modifier)mod).isStatic())
return true;
}
return false;
}
private boolean inNode(ASTNode node) {
return nodeContainsOffset(node,fOffset) || node==getLastNode();
}
private boolean nodeContainsOffset(ASTNode node, int offset) {
return (offset>=node.getStartPosition() && offset<node.getStartPosition()+node.getLength());
}
private boolean nodeisPastOffset(ASTNode node, int offset) {
return (offset<node.getStartPosition());
}
private void expand(List<ASTNode> children, boolean stopWhenPassed) {
if(children.isEmpty()) return;
for(int i=0;i<children.size();i++) {
boolean added=false;
ASTNode child=children.get(i);
if(nodeisPastOffset(child,fOffset)) {
if(stopWhenPassed) break;
} else {
if(i==children.size()-1 || nodeisPastOffset(children.get(i+1),fOffset)) {
//even if the node does not contain the offset, it's the only one that possibly could
//so we push it on the stack
push(child);
added=true;
}
}
if(added) level++;
visitASTNode(child);
if(added) level--;
}
}
private List<ASTNode> list(Object... children) {
List<ASTNode> ret=new ArrayList<ASTNode>();
for(int i=0;i<children.length;i++) {
if(children[i]==null) {
} else if(children[i] instanceof ASTNode) {
ret.add((ASTNode)children[i]);
} else if(children[i] instanceof List) {
ret.addAll((List<ASTNode>)children[i]);
}
}
return ret;
}
/** the "common case" node handler */
private void cc(ASTNode node, List<ASTNode> children) {
if(!inNode(node)) return;
expand(children,true);
}
/* nodes that require some special handling go first */
public void visit(TypeDeclaration node) {
if(!inNode(node)) return;
expand(node.bodyDeclarations(),false); //continue processing all fields
}
public void visit(AnonymousClassDeclaration node) {
if(!inNode(node)) return;
expand(node.bodyDeclarations(),false); //continue processing all fields
}
public void visit(FieldDeclaration node) {
if(inNode(node)) {
addFragsIfPast(node,node.fragments());
expand(node.fragments(),true);
} else {
addFrags(node.fragments());
}
}
public void visit(MethodDeclaration node) {
if(!inNode(node)) return;
for(SingleVariableDeclaration svd: (List<SingleVariableDeclaration>)node.parameters()) {
add(svd);
}
expand(list(node.getBody()),true);
}
public void visit(VariableDeclarationStatement node) {
if(inNode(node)) {
addFragsIfPast(node,node.fragments());
expand(node.fragments(),true);
} else {
addFrags(node.fragments());
}
}
public void visit(VariableDeclarationExpression node) {
if(inNode(node)) {
addFragsIfPast(node,node.fragments());
expand(node.fragments(),true);
} else {
addFrags(node.fragments());
}
}
public void visit(EnhancedForStatement node) {
if(!inNode(node)) return;
add(node.getParameter());
expand(list(node.getParameter(),node.getExpression(),node.getBody()),true);
}
public void visit(CatchClause node) {
if(!inNode(node)) return;
add(node.getException());
expand(list(node.getBody()),true);
}
/* then we have nodes that fit the common case, we just need to specify how to get the children */
public void visit(CompilationUnit node) {
cc(node,node.types());
}
public void visit(EnumDeclaration node) {
cc(node,list(node.bodyDeclarations()));
}
public void visit(VariableDeclarationFragment node) {
cc(node,list(node.getInitializer()));
}
public void visit(ClassInstanceCreation node) {
cc(node,list(node.arguments(),node.getAnonymousClassDeclaration()));
}
public void visit(Block node) {
cc(node,node.statements());
}
public void visit(Initializer node) {
cc(node,list(node.getBody()));
}
public void visit(TypeDeclarationStatement node) {
cc(node,list(node.getDeclaration()));
}
public void visit(ForStatement node) {
cc(node,list(node.initializers(),node.getExpression(),node.updaters(),node.getBody()));
}
public void visit(DoStatement node) {
cc(node,list(node.getBody(),node.getExpression()));
}
public void visit(ExpressionStatement node) {
cc(node,list(node.getExpression()));
}
public void visit(IfStatement node) {
cc(node,list(node.getExpression(),node.getThenStatement(),node.getElseStatement()));
}
public void visit(LabeledStatement node) {
cc(node,list(node.getBody()));
}
public void visit(SwitchStatement node) {
cc(node,list(node.getExpression(),node.statements()));
}
public void visit(SynchronizedStatement node) {
cc(node,list(node.getExpression(),node.getBody()));
}
public void visit(TryStatement node) {
cc(node,list(node.getBody(),node.catchClauses(),node.getFinally()));
}
public void visit(WhileStatement node) {
cc(node,list(node.getExpression(),node.getBody()));
}
public void visit(Assignment node) {
cc(node,list(node.getLeftHandSide(),node.getRightHandSide()));
}
public void visit(MethodInvocation node) {
cc(node,list(node.getExpression(),node.arguments()));
}
public void visit(SingleVariableDeclaration node) { //should be handled by parent, but just in case...
cc(node,list(node.getInitializer()));
}
public void visit(ArrayAccess node) {
cc(node,list(node.getArray(),node.getIndex()));
}
public void visit(ArrayCreation node) {
cc(node,list(node.dimensions(),node.getInitializer()));
}
public void visit(ArrayInitializer node) {
cc(node,list(node.expressions()));
}
public void visit(AssertStatement node) {
cc(node,list(node.getExpression(),node.getMessage()));
}
public void visit(CastExpression node) {
cc(node,list(node.getExpression()));
}
public void visit(ConditionalExpression node) {
cc(node,list(node.getExpression(),node.getThenExpression(),node.getElseExpression()));
}
public void visit(ConstructorInvocation node) {
cc(node,list(node.arguments()));
}
public void visit(EnumConstantDeclaration node) {
cc(node,list(node.arguments(),node.getAnonymousClassDeclaration()));
}
public void visit(FieldAccess node) {
cc(node,list(node.getExpression()));
}
public void visit(InfixExpression node) {
cc(node,list(node.getLeftOperand(),node.getRightOperand(),node.extendedOperands()));
}
public void visit(InstanceofExpression node) {
cc(node,list(node.getLeftOperand()));
}
public void visit(ParenthesizedExpression node) {
cc(node,list(node.getExpression()));
}
public void visit(PostfixExpression node) {
cc(node,list(node.getOperand()));
}
public void visit(PrefixExpression node) {
cc(node,list(node.getOperand()));
}
public void visit(ReturnStatement node) {
cc(node,list(node.getExpression()));
}
public void visit(SuperConstructorInvocation node) {
cc(node,list(node.getExpression(),node.arguments()));
}
public void visit(SuperMethodInvocation node) {
cc(node,list(node.arguments()));
}
public void visit(SwitchCase node) {
cc(node,list(node.getExpression()));
}
public void visit(ThrowStatement node) {
cc(node,list(node.getExpression()));
}
/* finally we have useless nodes */
public void visit(AnnotationTypeDeclaration node) {} //skip
public void visit(AnnotationTypeMemberDeclaration node) {} //skip
public void visit(ArrayType node) {} //skip
public void visit(BlockComment node) {} //skip
public void visit(BooleanLiteral node) {} //skip
public void visit(BreakStatement node) {} //skip
public void visit(CharacterLiteral node) {} //skip
public void visit(ContinueStatement node) {} //skip
public void visit(EmptyStatement node) {} //skip
public void visit(ImportDeclaration node) {} //skip
public void visit(Javadoc node) {} //skip
public void visit(LineComment node) {} //skip
public void visit(MarkerAnnotation node) {} //skip
public void visit(MemberRef node) {} //skip
public void visit(MemberValuePair node) {} //skip
public void visit(MethodRef node) {} //skip
public void visit(MethodRefParameter node) {} //skip
public void visit(Modifier node) {} //skip
public void visit(NormalAnnotation node) {} //skip
public void visit(NullLiteral node) {} //skip
public void visit(NumberLiteral node) {} //skip
public void visit(PackageDeclaration node) {} //skip
public void visit(ParameterizedType node) {} //skip
public void visit(PrimitiveType node) {} //skip
public void visit(QualifiedName node) {} //skip
public void visit(QualifiedType node) {} //skip
public void visit(SimpleName node) {} //skip
public void visit(SimpleType node) {} //skip
public void visit(SingleMemberAnnotation node) {} //skip
public void visit(StringLiteral node) {} //skip
public void visit(SuperFieldAccess node) {} //skip
public void visit(TagElement node) {} //skip
public void visit(TextElement node) {} //skip
public void visit(ThisExpression node) {} //skip
public void visit(TypeLiteral node) {} //skip
public void visit(TypeParameter node) {} //skip
public void visit(WildcardType node) {} //skip
}