From c927d12a09b360bbd32250c331722fa010de50c0 Mon Sep 17 00:00:00 2001 From: bdanglot Date: Wed, 6 Jul 2016 15:29:38 +0200 Subject: [PATCH 1/4] refactor: JDTTreeBuilder, split into multiple classes with one static Helper --- .../spoon/support/compiler/jdt/ASTPair.java | 37 + .../support/compiler/jdt/BuilderContext.java | 176 +++ .../compiler/jdt/HelperJDTTreeBuilder.java | 306 +++++ .../support/compiler/jdt/JDTTreeBuilder.java | 1202 +---------------- .../support/compiler/jdt/ParentExiter.java | 1 - .../compiler/jdt/ReferenceBuilder.java | 681 ++++++++++ 6 files changed, 1249 insertions(+), 1154 deletions(-) create mode 100644 src/main/java/spoon/support/compiler/jdt/ASTPair.java create mode 100644 src/main/java/spoon/support/compiler/jdt/BuilderContext.java create mode 100644 src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java create mode 100644 src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java diff --git a/src/main/java/spoon/support/compiler/jdt/ASTPair.java b/src/main/java/spoon/support/compiler/jdt/ASTPair.java new file mode 100644 index 00000000000..af56553abc2 --- /dev/null +++ b/src/main/java/spoon/support/compiler/jdt/ASTPair.java @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2006-2016 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.compiler.jdt; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import spoon.reflect.declaration.CtElement; + +public class ASTPair { + public CtElement element; + + public ASTNode node; + + public ASTPair(CtElement element, ASTNode node) { + super(); + this.element = element; + this.node = node; + } + + @Override + public String toString() { + return element.getClass().getSimpleName() + "-" + node.getClass().getSimpleName(); + } +} diff --git a/src/main/java/spoon/support/compiler/jdt/BuilderContext.java b/src/main/java/spoon/support/compiler/jdt/BuilderContext.java new file mode 100644 index 00000000000..2a0099be665 --- /dev/null +++ b/src/main/java/spoon/support/compiler/jdt/BuilderContext.java @@ -0,0 +1,176 @@ +/** + * Copyright (C) 2006-2016 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.compiler.jdt; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtStatementList; +import spoon.reflect.code.CtTargetedExpression; +import spoon.reflect.code.CtTry; +import spoon.reflect.cu.CompilationUnit; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtNamedElement; +import spoon.reflect.declaration.CtTypedElement; +import spoon.reflect.factory.CoreFactory; +import spoon.reflect.reference.CtTypeReference; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.List; + +import static spoon.reflect.ModelElementContainerDefaultCapacities.CASTS_CONTAINER_DEFAULT_CAPACITY; + +public class BuilderContext { + + Deque annotationValueName = new ArrayDeque<>(); + + Deque arguments = new ArrayDeque<>(); + + List> casts = new ArrayList<>(CASTS_CONTAINER_DEFAULT_CAPACITY); + + CompilationUnitDeclaration compilationunitdeclaration; + + Deque finallyzer = new ArrayDeque<>(); + + boolean forinit = false; + + boolean forupdate = false; + + boolean assigned = false; + + Deque label = new ArrayDeque<>(); + + boolean selector = false; + + boolean isGenericTypeExplicit = true; + + boolean isLambdaParameterImplicitlyTyped = true; + + boolean ignoreComputeImports = false; + + boolean isTypeParameter = false; + + /** + * Stack of all parents elements + */ + Deque stack = new ArrayDeque<>(); + + Deque> target = new ArrayDeque<>(); + + private final JDTTreeBuilder jdtTreeBuilder; + + BuilderContext(JDTTreeBuilder jdtTreeBuilder) { + this.jdtTreeBuilder = jdtTreeBuilder; + } + + @SuppressWarnings("unchecked") + void enter(CtElement e, ASTNode node) { + stack.push(new ASTPair(e, node)); + // aststack.push(node); + if (compilationunitdeclaration != null) { + CoreFactory cf = this.jdtTreeBuilder.factory.Core(); + int sourceStartDeclaration = node.sourceStart; + int sourceStartSource = node.sourceStart; + int sourceEnd = node.sourceEnd; + if (node instanceof AbstractVariableDeclaration) { + sourceStartDeclaration = ((AbstractVariableDeclaration) node).declarationSourceStart; + sourceEnd = ((AbstractVariableDeclaration) node).declarationSourceEnd; + } else if (node instanceof TypeDeclaration) { + sourceStartDeclaration = ((TypeDeclaration) node).declarationSourceStart; + sourceEnd = ((TypeDeclaration) node).declarationSourceEnd; + } else if ((e instanceof CtStatementList) && (node instanceof AbstractMethodDeclaration)) { + sourceStartDeclaration = ((AbstractMethodDeclaration) node).bodyStart - 1; + sourceEnd = ((AbstractMethodDeclaration) node).bodyEnd + 1; + } else if ((node instanceof AbstractMethodDeclaration)) { + if (((AbstractMethodDeclaration) node).bodyStart == 0) { + sourceStartDeclaration = -1; + sourceStartSource = -1; + sourceEnd = -1; + } else { + sourceStartDeclaration = ((AbstractMethodDeclaration) node).declarationSourceStart; + sourceEnd = ((AbstractMethodDeclaration) node).declarationSourceEnd; + } + } + if ((node instanceof Expression)) { + if (((Expression) node).statementEnd > 0) { + sourceEnd = ((Expression) node).statementEnd; + } + } + if (!(e instanceof CtNamedElement)) { + sourceStartSource = sourceStartDeclaration; + } + CompilationUnit cu = this.jdtTreeBuilder.factory.CompilationUnit().create(new String(compilationunitdeclaration.getFileName())); + e.setPosition(cf.createSourcePosition(cu, sourceStartDeclaration, sourceStartSource, sourceEnd, compilationunitdeclaration.compilationResult.lineSeparatorPositions)); + } + ASTPair pair = stack.peek(); + CtElement current = pair.element; + + if (current instanceof CtExpression) { + while (!casts.isEmpty()) { + ((CtExpression) current).addTypeCast(casts.remove(0)); + } + } + if (current instanceof CtStatement && !this.label.isEmpty()) { + ((CtStatement) current).setLabel(this.label.pop()); + } + + try { + if (e instanceof CtTypedElement && node instanceof Expression) { + if (((CtTypedElement) e).getType() == null) { + ((CtTypedElement) e).setType(this.jdtTreeBuilder.references.getTypeReference(((Expression) node).resolvedType)); + } + } + } catch (UnsupportedOperationException ignore) { + // For some element, we throw an UnsupportedOperationException when we call setType(). + } + + } + + void exit(ASTNode node) { + ASTPair pair = stack.pop(); + if (pair.node != node) { + throw new RuntimeException("Inconsistent Stack " + node + "\n" + pair.node); + } + CtElement current = pair.element; + if (!stack.isEmpty()) { + this.jdtTreeBuilder.exiter.child = current; + this.jdtTreeBuilder.exiter.scan(stack.peek().element); + } + } + + boolean isArgument(CtElement e) { + return arguments.size() > 0 && arguments.peek() == e; + } + + void popArgument(CtElement e) { + if (arguments.pop() != e) { + throw new RuntimeException("Unconsistant stack"); + } + } + + void pushArgument(CtElement e) { + arguments.push(e); + } + +} diff --git a/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java new file mode 100644 index 00000000000..0f633bbf178 --- /dev/null +++ b/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java @@ -0,0 +1,306 @@ +/** + * Copyright (C) 2006-2016 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.compiler.jdt; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ImportReference; +import org.eclipse.jdt.internal.compiler.ast.OperatorIds; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; +import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; +import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import spoon.reflect.code.BinaryOperatorKind; +import spoon.reflect.code.UnaryOperatorKind; +import spoon.reflect.declaration.CtAnnotatedElementType; +import spoon.reflect.declaration.CtAnnotation; +import spoon.reflect.declaration.CtType; +import spoon.reflect.declaration.CtTypedElement; +import spoon.reflect.declaration.ModifierKind; + +import java.util.EnumSet; +import java.util.Set; + +public class HelperJDTTreeBuilder { + + static UnaryOperatorKind getUnaryOperator(int op) { + switch (op) { + case OperatorIds.PLUS: + return UnaryOperatorKind.POS; + case OperatorIds.MINUS: + return UnaryOperatorKind.NEG; + case OperatorIds.NOT: + return UnaryOperatorKind.NOT; + case OperatorIds.TWIDDLE: + return UnaryOperatorKind.COMPL; + } + return null; + } + + static Set getModifiers(int mod) { + Set ret = EnumSet.noneOf(ModifierKind.class); + if ((mod & ClassFileConstants.AccPublic) != 0) { + ret.add(ModifierKind.PUBLIC); + } + if ((mod & ClassFileConstants.AccPrivate) != 0) { + ret.add(ModifierKind.PRIVATE); + } + if ((mod & ClassFileConstants.AccProtected) != 0) { + ret.add(ModifierKind.PROTECTED); + } + if ((mod & ClassFileConstants.AccStatic) != 0) { + ret.add(ModifierKind.STATIC); + } + if ((mod & ClassFileConstants.AccFinal) != 0) { + ret.add(ModifierKind.FINAL); + } + if ((mod & ClassFileConstants.AccSynchronized) != 0) { + ret.add(ModifierKind.SYNCHRONIZED); + } + if ((mod & ClassFileConstants.AccVolatile) != 0) { + ret.add(ModifierKind.VOLATILE); + } + if ((mod & ClassFileConstants.AccTransient) != 0) { + ret.add(ModifierKind.TRANSIENT); + } + if ((mod & ClassFileConstants.AccAbstract) != 0) { + ret.add(ModifierKind.ABSTRACT); + } + if ((mod & ClassFileConstants.AccStrictfp) != 0) { + ret.add(ModifierKind.STRICTFP); + } + if ((mod & ClassFileConstants.AccNative) != 0) { + ret.add(ModifierKind.NATIVE); + } + return ret; + } + + static BinaryOperatorKind getBinaryOperatorKind(int bits) { + // switch ((bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) { + switch (bits) { + case OperatorIds.EQUAL_EQUAL: + return BinaryOperatorKind.EQ; + case OperatorIds.LESS_EQUAL: + return BinaryOperatorKind.LE; + case OperatorIds.GREATER_EQUAL: + return BinaryOperatorKind.GE; + case OperatorIds.NOT_EQUAL: + return BinaryOperatorKind.NE; + case OperatorIds.LEFT_SHIFT: + return BinaryOperatorKind.SL; + case OperatorIds.RIGHT_SHIFT: + return BinaryOperatorKind.SR; + case OperatorIds.UNSIGNED_RIGHT_SHIFT: + return BinaryOperatorKind.USR; + case OperatorIds.OR_OR: + return BinaryOperatorKind.OR; + case OperatorIds.AND_AND: + return BinaryOperatorKind.AND; + case OperatorIds.PLUS: + return BinaryOperatorKind.PLUS; + case OperatorIds.MINUS: + return BinaryOperatorKind.MINUS; + case OperatorIds.NOT: + return BinaryOperatorKind.NE; + case OperatorIds.REMAINDER: + return BinaryOperatorKind.MOD; + case OperatorIds.XOR: + return BinaryOperatorKind.BITXOR; + case OperatorIds.AND: + return BinaryOperatorKind.BITAND; + case OperatorIds.MULTIPLY: + return BinaryOperatorKind.MUL; + case OperatorIds.OR: + return BinaryOperatorKind.BITOR; + case OperatorIds.DIVIDE: + return BinaryOperatorKind.DIV; + case OperatorIds.GREATER: + return BinaryOperatorKind.GT; + case OperatorIds.LESS: + return BinaryOperatorKind.LT; + case OperatorIds.QUESTIONCOLON: + throw new RuntimeException("Unknown operator"); + case OperatorIds.EQUAL: + return BinaryOperatorKind.EQ; + } + return null; + } + + /** + * Searches a type from an entry-point according to a simple name. + * + * @param type Entry-point to search. + * @param simpleName Expected type name. + * @return type binding. + */ + static TypeBinding searchTypeBinding(ReferenceBinding type, String simpleName) { + if (simpleName == null || type == null) { + return null; + } + + if (type.memberTypes() != null) { + for (ReferenceBinding memberType : type.memberTypes()) { + if (simpleName.equals(CharOperation.charToString(memberType.sourceName()))) { + return memberType; + } + } + } + + return searchTypeBinding(type.superclass(), simpleName); + } + + /** + * Searches a type in the project. + * + * @param qualifiedName Qualified name of the expected type. + * @return type binding. + */ + static TypeBinding searchTypeBinding(String qualifiedName, TreeBuilderCompiler treeBuilderCompiler) { + if (qualifiedName == null) { + return null; + } + for (CompilationUnitDeclaration unitsToProcess : treeBuilderCompiler.unitsToProcess) { + for (TypeDeclaration type : unitsToProcess.types) { + if (qualifiedName.equals(CharOperation.toString(type.binding.compoundName))) { + return type.binding; + } + if (type.memberTypes != null) { + for (TypeDeclaration memberType : type.memberTypes) { + if (qualifiedName.equals(CharOperation.toString(memberType.binding.compoundName))) { + return type.binding; + } + } + } + } + } + return null; + } + + static String computeAnonymousName(SourceTypeBinding binding) { + final String poolName = String.valueOf(binding.constantPoolName()); + final int lastIndexSeparator = poolName.lastIndexOf(CtType.INNERTTYPE_SEPARATOR); + return poolName.substring(lastIndexSeparator + 1, poolName.length()); + } + + static String createTypeName(char[][] typeName) { + String s = ""; + for (int i = 0; i < typeName.length - 1; i++) { + s += new String(typeName[i]) + "."; + } + s += new String(typeName[typeName.length - 1]); + return s; + } + + + /** + * Checks to know if a name is a package or not. + * + * @param packageName Package name. + * @return boolean + */ + static boolean isPackage(char[][] packageName, TreeBuilderCompiler treeBuilderCompiler) { + for (CompilationUnitDeclaration unit : treeBuilderCompiler.unitsToProcess) { + final char[][] tokens = unit.currentPackage.tokens; + if (packageName.length > tokens.length) { + continue; + } + boolean isFound = true; + for (int i = 0; i < packageName.length; i++) { + char[] chars = packageName[i]; + if (!CharOperation.equals(chars, tokens[i])) { + isFound = false; + break; + } + } + if (isFound) { + return true; + } + } + return false; + } + + /** + * Checks if a type is specified in imports. + * + * @param typeName Type name. + * @return qualified name of the expected type. + */ + static String hasTypeInImports(String typeName, BuilderContext context) { + if (typeName == null) { + return null; + } else if (context.compilationunitdeclaration.imports == null) { + return null; + } + for (ImportReference anImport : context.compilationunitdeclaration.imports) { + final String importType = CharOperation.charToString(anImport.getImportName()[anImport.getImportName().length - 1]); + if (importType != null && importType.equals(typeName)) { + return CharOperation.toString(anImport.getImportName()); + } + } + return null; + } + + /** + * Check if the annotation is declared with the given element type. + * + * @param a An annotation. + * @param elementType Type of the annotation. + * @return true if the annotation is compitble with the given element type. + */ + private static boolean hasAnnotationWithType(Annotation a, CtAnnotatedElementType elementType) { + if (a.resolvedType == null) { + return false; + } + for (AnnotationBinding annotation : a.resolvedType.getAnnotations()) { + if (!"Target".equals(CharOperation.charToString(annotation.getAnnotationType().sourceName()))) { + continue; + } + Object value = annotation.getElementValuePairs()[0].value; + if (value == null || !value.getClass().isArray()) { + continue; + } + Object[] fields = (Object[]) value; + for (Object field : fields) { + if (field instanceof FieldBinding && elementType.name().equals(CharOperation.charToString(((FieldBinding) field).name))) { + return true; + } + } + } + return false; + } + + /** + * When an annotation is specified on a method, a local declaration or an argument, JDT doesn't know + * if the annotation is specified on the type or on the element. Due to this method, if the annotation + * is compatible with types, we substitute the annotation from the element to the type of this element. + * + * @param typedElement Element annotated. + * @param a Annotation of the element. + * @param elementType Type of the annotation. + */ + static void substituteAnnotation(CtTypedElement typedElement, Annotation a, CtAnnotatedElementType elementType) { + if (HelperJDTTreeBuilder.hasAnnotationWithType(a, elementType)) { + CtAnnotation targetAnnotation = typedElement.getAnnotations().get(typedElement.getAnnotations().size() - 1); + typedElement.removeAnnotation(targetAnnotation); + typedElement.getType().addAnnotation(targetAnnotation); + } + } +} diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index b243af47840..1b465f73f94 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -21,8 +21,6 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression; import org.eclipse.jdt.internal.compiler.ast.ASTNode; -import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; -import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration; @@ -41,7 +39,6 @@ import org.eclipse.jdt.internal.compiler.ast.CastExpression; import org.eclipse.jdt.internal.compiler.ast.CharLiteral; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; @@ -59,7 +56,6 @@ import org.eclipse.jdt.internal.compiler.ast.ForStatement; import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; import org.eclipse.jdt.internal.compiler.ast.IfStatement; -import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression; import org.eclipse.jdt.internal.compiler.ast.IntLiteral; @@ -107,35 +103,21 @@ import org.eclipse.jdt.internal.compiler.ast.WhileStatement; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; -import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; -import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; -import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; -import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; -import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding; -import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; -import org.eclipse.jdt.internal.compiler.lookup.IntersectionTypeBinding18; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; -import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; -import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; -import org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; -import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; -import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; -import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; @@ -169,12 +151,9 @@ import spoon.reflect.code.CtNewArray; import spoon.reflect.code.CtOperatorAssignment; import spoon.reflect.code.CtReturn; -import spoon.reflect.code.CtStatement; -import spoon.reflect.code.CtStatementList; import spoon.reflect.code.CtSuperAccess; import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSynchronized; -import spoon.reflect.code.CtTargetedExpression; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -189,25 +168,18 @@ import spoon.reflect.declaration.CtAnonymousExecutable; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtConstructor; -import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtField; import spoon.reflect.declaration.CtMethod; -import spoon.reflect.declaration.CtNamedElement; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtType; -import spoon.reflect.declaration.CtTypedElement; import spoon.reflect.declaration.ModifierKind; -import spoon.reflect.factory.CoreFactory; import spoon.reflect.factory.Factory; -import spoon.reflect.internal.CtCircularTypeReference; import spoon.reflect.reference.CtArrayTypeReference; -import spoon.reflect.reference.CtCatchVariableReference; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtFieldReference; import spoon.reflect.reference.CtLocalVariableReference; import spoon.reflect.reference.CtPackageReference; -import spoon.reflect.reference.CtParameterReference; import spoon.reflect.reference.CtReference; import spoon.reflect.reference.CtTypeParameterReference; import spoon.reflect.reference.CtTypeReference; @@ -215,328 +187,66 @@ import spoon.reflect.visitor.EarlyTerminatingScanner; import spoon.support.reflect.reference.CtUnboundVariableReferenceImpl; -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Deque; -import java.util.EnumSet; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.TreeMap; import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static spoon.reflect.ModelElementContainerDefaultCapacities.CASTS_CONTAINER_DEFAULT_CAPACITY; /** * A visitor for iterating through the parse tree. */ public class JDTTreeBuilder extends ASTVisitor { - private static final Logger LOGGER = Logger.getLogger(JDTTreeBuilder.class); - boolean defaultValue; - - public class ASTPair { - public CtElement element; - - public ASTNode node; - - public ASTPair(CtElement element, ASTNode node) { - super(); - this.element = element; - this.node = node; - } - - @Override - public String toString() { - return element.getClass().getSimpleName() + "-" + node.getClass().getSimpleName(); - } - } - - public class BuilderContext { - Deque annotationValueName = new ArrayDeque<>(); - - Deque arguments = new ArrayDeque<>(); - - List> casts = new ArrayList<>(CASTS_CONTAINER_DEFAULT_CAPACITY); - - CompilationUnitDeclaration compilationunitdeclaration; - - List> createdTypes = new ArrayList<>(); - - Deque finallyzer = new ArrayDeque<>(); - - boolean forinit = false; - - boolean forupdate = false; - - boolean assigned = false; - - Deque label = new ArrayDeque<>(); - - boolean selector = false; - - boolean isGenericTypeExplicit = true; - - boolean isLambdaParameterImplicitlyTyped = true; - - boolean ignoreComputeImports = false; - - boolean isTypeParameter = false; - - /** - * Stack of all parents elements - */ - Deque stack = new ArrayDeque<>(); - - Deque> target = new ArrayDeque<>(); - - public void addCreatedType(CtType type) { - createdTypes.add(type); - } - - @SuppressWarnings("unchecked") - void enter(CtElement e, ASTNode node) { - stack.push(new ASTPair(e, node)); - // aststack.push(node); - if (compilationunitdeclaration != null) { - CoreFactory cf = factory.Core(); - int sourceStartDeclaration = node.sourceStart; - int sourceStartSource = node.sourceStart; - int sourceEnd = node.sourceEnd; - if (node instanceof AbstractVariableDeclaration) { - sourceStartDeclaration = ((AbstractVariableDeclaration) node).declarationSourceStart; - sourceEnd = ((AbstractVariableDeclaration) node).declarationSourceEnd; - } else if (node instanceof TypeDeclaration) { - sourceStartDeclaration = ((TypeDeclaration) node).declarationSourceStart; - sourceEnd = ((TypeDeclaration) node).declarationSourceEnd; - } else if ((e instanceof CtStatementList) && (node instanceof AbstractMethodDeclaration)) { - sourceStartDeclaration = ((AbstractMethodDeclaration) node).bodyStart - 1; - sourceEnd = ((AbstractMethodDeclaration) node).bodyEnd + 1; - } else if ((node instanceof AbstractMethodDeclaration)) { - if (((AbstractMethodDeclaration) node).bodyStart == 0) { - sourceStartDeclaration = -1; - sourceStartSource = -1; - sourceEnd = -1; - } else { - sourceStartDeclaration = ((AbstractMethodDeclaration) node).declarationSourceStart; - sourceEnd = ((AbstractMethodDeclaration) node).declarationSourceEnd; - } - } - if ((node instanceof Expression)) { - if (((Expression) node).statementEnd > 0) { - sourceEnd = ((Expression) node).statementEnd; - } - } - if (!(e instanceof CtNamedElement)) { - sourceStartSource = sourceStartDeclaration; - } - CompilationUnit cu = factory.CompilationUnit().create(new String(compilationunitdeclaration.getFileName())); - e.setPosition(cf.createSourcePosition(cu, sourceStartDeclaration, sourceStartSource, sourceEnd, compilationunitdeclaration.compilationResult.lineSeparatorPositions)); - } - ASTPair pair = stack.peek(); - CtElement current = pair.element; - - if (current instanceof CtExpression) { - while (!casts.isEmpty()) { - ((CtExpression) current).addTypeCast(casts.remove(0)); - } - } - if (current instanceof CtStatement && !context.label.isEmpty()) { - ((CtStatement) current).setLabel(context.label.pop()); - } - - try { - if (e instanceof CtTypedElement && node instanceof Expression) { - if (((CtTypedElement) e).getType() == null) { - ((CtTypedElement) e).setType(references.getTypeReference(((Expression) node).resolvedType)); - } - } - } catch (UnsupportedOperationException ignore) { - // For some element, we throw an UnsupportedOperationException when we call setType(). - } - - } - - void exit(ASTNode node) { - ASTPair pair = stack.pop(); - if (pair.node != node) { - throw new RuntimeException("Inconsistent Stack " + node + "\n" + pair.node); - } - CtElement current = pair.element; - if (!stack.isEmpty()) { - exiter.child = current; - exiter.scan(stack.peek().element); - } - } + BuilderContext context = new BuilderContext(this); - public List> getCreatedTypes() { - return createdTypes; - } - - public boolean isArgument(CtElement e) { - return arguments.size() > 0 && arguments.peek() == e; - } - - private void popArgument(CtElement e) { - if (arguments.pop() != e) { - throw new RuntimeException("Unconsistant stack"); - } - } - - private void pushArgument(CtElement e) { - arguments.push(e); - } - } + ParentExiter exiter = new ParentExiter(this); - private String createTypeName(char[][] typeName) { - String s = ""; - for (int i = 0; i < typeName.length - 1; i++) { - s += new String(typeName[i]) + "."; - } - s += new String(typeName[typeName.length - 1]); - return s; - } + Factory factory; - /** - * Checks if a type is specified in imports. - * - * @param typeName - * Type name. - * @return qualified name of the expected type. - */ - private String hasTypeInImports(String typeName) { - if (typeName == null) { - return null; - } else if (context.compilationunitdeclaration.imports == null) { - return null; - } - for (ImportReference anImport : context.compilationunitdeclaration.imports) { - final String importType = CharOperation.charToString(anImport.getImportName()[anImport.getImportName().length - 1]); - if (importType != null && importType.equals(typeName)) { - return CharOperation.toString(anImport.getImportName()); - } - } - return null; - } + ReferenceBuilder references = new ReferenceBuilder(this); - /** - * Checks to know if a name is a package or not. - * - * @param packageName - * Package name. - * @return boolean - */ - private boolean isPackage(char[][] packageName) { - for (CompilationUnitDeclaration unit : ((TreeBuilderCompiler) context.compilationunitdeclaration.scope.environment.typeRequestor).unitsToProcess) { - final char[][] tokens = unit.currentPackage.tokens; - if (packageName.length > tokens.length) { - continue; - } - boolean isFound = true; - for (int i = 0; i < packageName.length; i++) { - char[] chars = packageName[i]; - if (!CharOperation.equals(chars, tokens[i])) { - isFound = false; - break; - } - } - if (isFound) { - return true; - } - } - return false; - } - - /** - * Searches a type in the project. - * - * @param qualifiedName - * Qualified name of the expected type. - * @return type binding. - */ - private TypeBinding searchTypeBinding(String qualifiedName) { - if (qualifiedName == null) { - return null; - } - for (CompilationUnitDeclaration unitsToProcess : ((TreeBuilderCompiler) context.compilationunitdeclaration.scope.environment.typeRequestor).unitsToProcess) { - for (TypeDeclaration type : unitsToProcess.types) { - if (qualifiedName.equals(CharOperation.toString(type.binding.compoundName))) { - return type.binding; - } - if (type.memberTypes != null) { - for (TypeDeclaration memberType : type.memberTypes) { - if (qualifiedName.equals(CharOperation.toString(memberType.binding.compoundName))) { - return type.binding; - } - } - } - } - } - return null; - } + public boolean template = false; - /** - * Searches a type from an entry-point according to a simple name. - * - * @param type - * Entry-point to search. - * @param simpleName - * Expected type name. - * @return type binding. - */ - private TypeBinding searchTypeBinding(ReferenceBinding type, String simpleName) { - if (simpleName == null || type == null) { - return null; - } + private static final Logger LOGGER = Logger.getLogger(JDTTreeBuilder.class); - if (type.memberTypes() != null) { - for (ReferenceBinding memberType : type.memberTypes()) { - if (simpleName.equals(CharOperation.charToString(memberType.sourceName()))) { - return memberType; - } - } - } + boolean defaultValue; - return searchTypeBinding(type.superclass(), simpleName); + public JDTTreeBuilder(Factory factory) { + super(); + this.factory = factory; + LOGGER.setLevel(factory.getEnvironment().getLevel()); } /** * Builds a type reference from a qualified name when a type specified in the name isn't available. * - * @param tokens - * Qualified name. - * @param receiverType - * Last type in the qualified name. - * @param enclosingType - * Enclosing type of the type name. - * @param listener - * Listener to know if we must build the type reference. + * @param tokens Qualified name. + * @param receiverType Last type in the qualified name. + * @param enclosingType Enclosing type of the type name. + * @param listener Listener to know if we must build the type reference. * @return a type reference. */ private CtTypeReference getQualifiedTypeReference(char[][] tokens, TypeBinding receiverType, ReferenceBinding enclosingType, OnAccessListener listener) { - if (enclosingType != null && Collections.disjoint(Arrays.asList(ModifierKind.PUBLIC, ModifierKind.PROTECTED), getModifiers(enclosingType.modifiers))) { + if (enclosingType != null && Collections.disjoint(Arrays.asList(ModifierKind.PUBLIC, ModifierKind.PROTECTED), HelperJDTTreeBuilder.getModifiers(enclosingType.modifiers))) { String access = ""; int i = 0; for (; i < tokens.length; i++) { final char[][] qualified = Arrays.copyOfRange(tokens, 0, i + 1); - if (!isPackage(qualified)) { + if (!HelperJDTTreeBuilder.isPackage(qualified, ((TreeBuilderCompiler) context.compilationunitdeclaration.scope.environment.typeRequestor))) { access = CharOperation.toString(qualified); break; } } if (!access.contains(CtPackage.PACKAGE_SEPARATOR)) { - access = hasTypeInImports(access); + access = HelperJDTTreeBuilder.hasTypeInImports(access, this.context); } - final TypeBinding accessBinding = searchTypeBinding(access); + final TypeBinding accessBinding = HelperJDTTreeBuilder.searchTypeBinding(access, ((TreeBuilderCompiler) context.compilationunitdeclaration.scope.environment.typeRequestor)); if (accessBinding != null && listener.onAccess(tokens, i)) { - final TypeBinding superClassBinding = searchTypeBinding(accessBinding.superclass(), CharOperation.charToString(tokens[i + 1])); + final TypeBinding superClassBinding = HelperJDTTreeBuilder.searchTypeBinding(accessBinding.superclass(), CharOperation.charToString(tokens[i + 1])); if (superClassBinding != null) { - return references.getTypeReference(superClassBinding.clone(accessBinding)); + return references.getTypeReference(superClassBinding.clone(accessBinding)); } else { return references.getTypeReference(receiverType); } @@ -551,609 +261,10 @@ interface OnAccessListener { boolean onAccess(char[][] tokens, int index); } - public class ReferenceBuilder { - - Map> basestypes = new TreeMap<>(); - - Set typevars = new TreeSet<>(); - - boolean bounds = false; - - boolean isImplicit = false; - - public CtTypeReference getBoundedTypeReference(TypeBinding binding) { - bounds = true; - CtTypeReference ref = getTypeReference(binding); - bounds = false; - return ref; - } - - /** - * Try to get the declaring reference (package or type) from imports of the current - * compilation unit declaration (current class). This method returns a CtReference - * which can be a CtTypeReference if it retrieves the information in an static import, - * a CtPackageReference if it retrieves the information in an standard import, otherwise - * it returns null. - * - * @param expectedName - * Name expected in imports. - * @return CtReference which can be a CtTypeReference, a CtPackageReference or null. - */ - public CtReference getDeclaringReferenceFromImports(char[] expectedName) { - if (context.compilationunitdeclaration != null && context.compilationunitdeclaration.imports != null) { - for (ImportReference anImport : context.compilationunitdeclaration.imports) { - if (CharOperation.equals(anImport.getImportName()[anImport.getImportName().length - 1], expectedName)) { - if (anImport.isStatic()) { - int indexDeclaring = 2; - if ((anImport.bits & ASTNode.OnDemand) != 0) { - // With .* - indexDeclaring = 1; - } - char[][] packageName = CharOperation.subarray(anImport.getImportName(), 0, anImport.getImportName().length - indexDeclaring); - char[][] className = CharOperation.subarray(anImport.getImportName(), anImport.getImportName().length - indexDeclaring, anImport.getImportName().length - (indexDeclaring - 1)); - PackageBinding aPackage; - if (packageName.length != 0) { - aPackage = context.compilationunitdeclaration.scope.environment.createPackage(packageName); - } else { - aPackage = null; - } - final MissingTypeBinding declaringType = context.compilationunitdeclaration.scope.environment.createMissingType(aPackage, className); - context.ignoreComputeImports = true; - final CtTypeReference typeReference = getTypeReference(declaringType); - context.ignoreComputeImports = false; - return typeReference; - } else { - char[][] chars = CharOperation.subarray(anImport.getImportName(), 0, anImport.getImportName().length - 1); - Binding someBinding = context.compilationunitdeclaration.scope.findImport(chars, false, false); - PackageBinding packageBinding; - if (someBinding != null && someBinding.isValidBinding() && someBinding instanceof PackageBinding) { - packageBinding = (PackageBinding) someBinding; - } else { - packageBinding = context.compilationunitdeclaration.scope.environment.createPackage(chars); - if (packageBinding == null) { - // Big crisis here. We are already in noclasspath mode but JDT doesn't support always - // creation of a package in this mode. So, if we are in this brace, we make the job of JDT... - packageBinding = new PackageBinding(chars, null, context.compilationunitdeclaration.scope.environment); - } - } - return getPackageReference(packageBinding); - } - } - } - } - return null; - } - - @SuppressWarnings("unchecked") - public CtExecutableReference getExecutableReference(MethodBinding exec) { - if (exec == null) { - return null; - } - - final CtExecutableReference ref = factory.Core().createExecutableReference(); - ref.setSimpleName(new String(exec.selector)); - ref.setType(getTypeReference(exec.returnType)); - - if (exec instanceof ProblemMethodBinding) { - if (exec.declaringClass != null && Arrays.asList(exec.declaringClass.methods()).contains(exec)) { - ref.setDeclaringType(getTypeReference(exec.declaringClass)); - } else { - final CtReference declaringType = getDeclaringReferenceFromImports(exec.constantPoolName()); - if (declaringType instanceof CtTypeReference) { - ref.setDeclaringType((CtTypeReference) declaringType); - } - } - if (exec.isConstructor()) { - // super() invocation have a good declaring class. - ref.setDeclaringType(getTypeReference(exec.declaringClass)); - } - ref.setStatic(true); - } else { - ref.setDeclaringType(getTypeReference(exec.declaringClass)); - ref.setStatic(exec.isStatic()); - } - - if (exec.declaringClass instanceof ParameterizedTypeBinding) { - ref.setDeclaringType(getTypeReference(exec.declaringClass.actualType())); - } - - // original() method returns a result not null when the current method is generic. - if (exec.original() != null) { - final List> parameters = new ArrayList<>(exec.original().parameters.length); - for (TypeBinding b : exec.original().parameters) { - parameters.add(getTypeReference(b)); - } - ref.setParameters(parameters); - } else if (exec.parameters != null) { - // This is a method without a generic argument. - final List> parameters = new ArrayList<>(); - for (TypeBinding b : exec.parameters) { - parameters.add(getTypeReference(b)); - } - ref.setParameters(parameters); - } - - return ref; - } - - public CtPackageReference getPackageReference(PackageBinding reference) { - String name = new String(reference.shortReadableName()); - if (name.length() == 0) { - return factory.Package().topLevel(); - } - CtPackageReference ref = factory.Core().createPackageReference(); - ref.setSimpleName(name); - return ref; - } - - final Map bindingCache = new HashMap<>(); - - public CtTypeReference getTypeReference(TypeBinding binding, TypeReference ref) { - CtTypeReference ctRef = getTypeReference(binding); - if (ctRef != null && isCorrectTypeReference(ref)) { - insertGenericTypesInNoClasspathFromJDTInSpoon(ref, ctRef); - return ctRef; - } - return getTypeReference(ref); - } - - public CtTypeReference getTypeParameterReference(TypeBinding binding, TypeReference ref) { - CtTypeReference ctRef = getTypeReference(binding); - if (ctRef != null && isCorrectTypeReference(ref)) { - if (!(ctRef instanceof CtTypeParameterReference)) { - CtTypeParameterReference typeParameterRef = factory.Core().createTypeParameterReference(); - typeParameterRef.setSimpleName(ctRef.getSimpleName()); - typeParameterRef.setDeclaringType(ctRef.getDeclaringType()); - typeParameterRef.setPackage(ctRef.getPackage()); - typeParameterRef.setActualTypeArguments(ctRef.getActualTypeArguments()); - ctRef = typeParameterRef; - } - insertGenericTypesInNoClasspathFromJDTInSpoon(ref, ctRef); - return ctRef; - } - return getTypeParameterReference(CharOperation.toString(ref.getParameterizedTypeName())); - } - - /** - * In no classpath, the model of the super interface isn't always correct. - */ - private boolean isCorrectTypeReference(TypeReference ref) { - if (ref.resolvedType == null) { - return false; - } - if (!(ref.resolvedType instanceof ProblemReferenceBinding)) { - return true; - } - final String[] compoundName = CharOperation.charArrayToStringArray(((ProblemReferenceBinding) ref.resolvedType).compoundName); - final String[] typeName = CharOperation.charArrayToStringArray(ref.getTypeName()); - if (compoundName.length == 0 || typeName.length == 0) { - return false; - } - return compoundName[compoundName.length - 1].equals(typeName[typeName.length - 1]); - } - - private void insertGenericTypesInNoClasspathFromJDTInSpoon(TypeReference original, CtTypeReference type) { - if (original.resolvedType instanceof ProblemReferenceBinding && original.getTypeArguments() != null) { - for (TypeReference[] typeReferences : original.getTypeArguments()) { - for (TypeReference typeReference : typeReferences) { - type.addActualTypeArgument(references.getTypeReference(typeReference.resolvedType)); - } - } - } - } - - /** - * JDT doesn't return a correct AST with the resolved type of the reference. - * This method try to build a correct Spoon AST from the name of the JDT - * reference, thanks to the parsing of the string, the name parameterized from - * the JDT reference and java convention. - * Returns a complete Spoon AST when the name is correct, otherwise a spoon type - * reference with a name that correspond to the name of the JDT type reference. - */ - public CtTypeReference getTypeReference(TypeReference ref) { - CtTypeReference res = null; - CtTypeReference inner = null; - final String[] namesParameterized = CharOperation.charArrayToStringArray(ref.getParameterizedTypeName()); - int index = namesParameterized.length - 1; - for (; index >= 0; index--) { - // Start at the end to get the class name first. - CtTypeReference main = getTypeReference(namesParameterized[index]); - if (main == null) { - break; - } - if (res == null) { - res = (CtTypeReference) main; - } else { - inner.setDeclaringType((CtTypeReference) main); - } - inner = main; - } - if (res == null) { - return factory.Type().createReference(CharOperation.toString(ref.getParameterizedTypeName())); - } - CtPackageReference packageReference = index >= 0 - ? factory.Package().getOrCreate(concatSubArray(namesParameterized, index)).getReference() - : factory.Package().topLevel(); - inner.setPackage(packageReference); - return res; - } - - private String concatSubArray(String[] a, int endIndex) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < endIndex; i++) { - sb.append(a[i]).append('.'); - } - sb.append(a[endIndex]); - return sb.toString(); - } - - /** - * Try to build a CtTypeReference from a simple name with specified generic types but - * returns null if the name doesn't correspond to a type (not start by an upper case). - */ - public CtTypeReference getTypeReference(String name) { - CtTypeReference main = null; - if (name.matches(".*(<.+>)")) { - Pattern pattern = Pattern.compile("([^<]+)<(.+)>"); - Matcher m = pattern.matcher(name); - if (name.startsWith("?")) { - main = (CtTypeReference) factory.Core().createTypeParameterReference(); - } else { - main = factory.Core().createTypeReference(); - } - if (m.find()) { - main.setSimpleName(m.group(1)); - final String[] split = m.group(2).split(","); - for (String parameter : split) { - ((CtTypeReference) main).addActualTypeArgument(getTypeParameterReference(parameter.trim())); - } - } - } else if (Character.isUpperCase(name.charAt(0))) { - main = factory.Core().createTypeReference(); - main.setSimpleName(name); - } else if (name.startsWith("?")) { - return (CtTypeReference) factory.Type().createTypeParameterReference(name); - } - return main; - } - - /** - * Try to build a CtTypeParameterReference from a single name with specified generic types but - * keep in mind that if you give wrong data in the strong, reference will be wrong. - */ - public CtTypeParameterReference getTypeParameterReference(String name) { - CtTypeParameterReference param = factory.Core().createTypeParameterReference(); - if (name.contains("extends") || name.contains("super")) { - String[] split = name.contains("extends") ? name.split("extends") : name.split("super"); - param.setSimpleName(split[0].trim()); - param.setBoundingType(getTypeReference(split[split.length - 1].trim())); - } else if (name.matches(".*(<.+>)")) { - Pattern pattern = Pattern.compile("([^<]+)<(.+)>"); - Matcher m = pattern.matcher(name); - if (m.find()) { - param.setSimpleName(m.group(1)); - final String[] split = m.group(2).split(","); - for (String parameter : split) { - param.addActualTypeArgument(getTypeParameterReference(parameter.trim())); - } - } - } else { - param.setSimpleName(name); - } - return param; - } - - @SuppressWarnings("unchecked") - public CtTypeReference getTypeReference(TypeBinding binding) { - if (binding == null) { - return null; - } - - CtTypeReference ref = null; - - if (binding instanceof RawTypeBinding) { - ref = getTypeReference(((ParameterizedTypeBinding) binding).genericType()); - } else if (binding instanceof ParameterizedTypeBinding) { - if (binding.actualType() != null && binding.actualType() instanceof LocalTypeBinding) { - // When we define a nested class in a method and when the enclosing class of this method - // is a parameterized type binding, JDT give a ParameterizedTypeBinding for the nested class - // and hide the real class in actualType(). - ref = getTypeReference(binding.actualType()); - } else { - ref = factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - if (binding.isAnonymousType()) { - ref.setSimpleName(""); - } else { - ref.setSimpleName(String.valueOf(binding.sourceName())); - if (binding.enclosingType() != null) { - ref.setDeclaringType(getTypeReference(binding.enclosingType())); - } else { - ref.setPackage(getPackageReference(binding.getPackage())); - } - } - } - - if (((ParameterizedTypeBinding) binding).arguments != null) { - for (TypeBinding b : ((ParameterizedTypeBinding) binding).arguments) { - if (!JDTTreeBuilder.this.context.isGenericTypeExplicit) { - isImplicit = true; - } - if (bindingCache.containsKey(b)) { - ref.addActualTypeArgument(getCtCircularTypeReference(b)); - } else { - ref.addActualTypeArgument(getTypeReference(b)); - } - isImplicit = false; - } - } - } else if (binding instanceof MissingTypeBinding) { - ref = factory.Core().createTypeReference(); - ref.setSimpleName(new String(binding.sourceName())); - ref.setPackage(getPackageReference(binding.getPackage())); - if (!context.ignoreComputeImports) { - final CtReference declaring = references.getDeclaringReferenceFromImports(binding.sourceName()); - if (declaring instanceof CtPackageReference) { - ref.setPackage((CtPackageReference) declaring); - } else if (declaring instanceof CtTypeReference) { - ref.setDeclaringType((CtTypeReference) declaring); - } - } - } else if (binding instanceof BinaryTypeBinding) { - ref = factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - if (binding.enclosingType() != null) { - ref.setDeclaringType(getTypeReference(binding.enclosingType())); - } else { - ref.setPackage(getPackageReference(binding.getPackage())); - } - ref.setSimpleName(new String(binding.sourceName())); - } else if (binding instanceof TypeVariableBinding) { - boolean oldBounds = bounds; - ref = factory.Core().createTypeParameterReference(); - ref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - if (binding instanceof CaptureBinding) { - ref.setSimpleName("?"); - bounds = true; - } else { - ref.setSimpleName(new String(binding.sourceName())); - } - TypeVariableBinding b = (TypeVariableBinding) binding; - if (bounds) { - if (b instanceof CaptureBinding && ((CaptureBinding) b).wildcard != null) { - bounds = oldBounds; - return getTypeReference(((CaptureBinding) b).wildcard); - } else if (b.superclass != null && b.firstBound == b.superclass) { - bounds = false; - bindingCache.put(binding, ref); - ((CtTypeParameterReference) ref).setBoundingType(getTypeReference(b.superclass)); - bounds = oldBounds; - } - } - if (bounds && b.superInterfaces != null && b.superInterfaces != Binding.NO_SUPERINTERFACES) { - bounds = false; - bindingCache.put(binding, ref); - Set> bounds = new TreeSet<>(); - if (((CtTypeParameterReference) ref).getBoundingType() != null) { - bounds.add(((CtTypeParameterReference) ref).getBoundingType()); - } - for (ReferenceBinding superInterface : b.superInterfaces) { - bounds.add(getTypeReference(superInterface)); - } - ((CtTypeParameterReference) ref).setBoundingType(factory.Type().createIntersectionTypeReferenceWithBounds(bounds)); - } - if (binding instanceof CaptureBinding) { - bounds = false; - } - } else if (binding instanceof BaseTypeBinding) { - String name = new String(binding.sourceName()); - if (!JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped) { - ref = factory.Core().createTypeReference(); - ref.setImplicit(true); - ref.setSimpleName(name); - } else { - ref = basestypes.get(name); - if (ref == null) { - ref = factory.Core().createTypeReference(); - ref.setSimpleName(name); - basestypes.put(name, ref); - } else { - ref = ref == null ? ref : ref.clone(); - } - } - } else if (binding instanceof WildcardBinding) { - ref = factory.Core().createTypeParameterReference(); - ref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - ref.setSimpleName("?"); - if (((WildcardBinding) binding).boundKind == Wildcard.SUPER && ref instanceof CtTypeParameterReference) { - ((CtTypeParameterReference) ref).setUpper(false); - } - - if (((WildcardBinding) binding).bound != null && ref instanceof CtTypeParameterReference) { - if (bindingCache.containsKey(((WildcardBinding) binding).bound)) { - final CtCircularTypeReference circularRef = getCtCircularTypeReference(((WildcardBinding) binding).bound); - ((CtTypeParameterReference) ref).setBoundingType(circularRef); - } else { - ((CtTypeParameterReference) ref).setBoundingType(getTypeReference(((WildcardBinding) binding).bound)); - } - } - } else if (binding instanceof LocalTypeBinding) { - ref = factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - if (binding.isAnonymousType()) { - ref.setSimpleName(computeAnonymousName((SourceTypeBinding) binding)); - ref.setDeclaringType(getTypeReference((binding.enclosingType()))); - } else { - ref.setSimpleName(new String(binding.sourceName())); - if (((LocalTypeBinding) binding).enclosingMethod == null && binding.enclosingType() != null && binding.enclosingType() instanceof LocalTypeBinding) { - ref.setDeclaringType(getTypeReference(binding.enclosingType())); - } else if (binding.enclosingMethod() != null) { - ref.setSimpleName(computeAnonymousName((SourceTypeBinding) binding)); - ref.setDeclaringType(getTypeReference(binding.enclosingType())); - } - } - } else if (binding instanceof SourceTypeBinding) { - ref = factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - if (binding.isAnonymousType()) { - ref.setSimpleName(computeAnonymousName((SourceTypeBinding) binding)); - ref.setDeclaringType(getTypeReference((binding.enclosingType()))); - } else { - ref.setSimpleName(new String(binding.sourceName())); - if (binding.enclosingType() != null) { - ref.setDeclaringType(getTypeReference(binding.enclosingType())); - } else { - ref.setPackage(getPackageReference(binding.getPackage())); - } - // if(((SourceTypeBinding) binding).typeVariables!=null && - // ((SourceTypeBinding) binding).typeVariables.length>0){ - // for (TypeBinding b : ((SourceTypeBinding) - // binding).typeVariables) { - // ref.getActualTypeArguments().add(getTypeReference(b)); - // } - // } - } - } else if (binding instanceof ArrayBinding) { - CtArrayTypeReference arrayref; - arrayref = factory.Core().createArrayTypeReference(); - arrayref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - ref = arrayref; - for (int i = 1; i < binding.dimensions(); i++) { - CtArrayTypeReference tmp = factory.Core().createArrayTypeReference(); - arrayref.setComponentType(tmp); - arrayref = tmp; - } - arrayref.setComponentType(getTypeReference(binding.leafComponentType())); - } else if (binding instanceof ProblemReferenceBinding || binding instanceof PolyTypeBinding) { - // Spoon is able to analyze also without the classpath - ref = factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !JDTTreeBuilder.this.context.isLambdaParameterImplicitlyTyped); - ref.setSimpleName(new String(binding.readableName())); - final CtReference declaring = references.getDeclaringReferenceFromImports(binding.sourceName()); - setPackageOrDeclaringType(ref, declaring); - } else if (binding instanceof SpoonReferenceBinding) { - ref = factory.Core().createTypeReference(); - ref.setSimpleName(new String(binding.sourceName())); - ref.setDeclaringType(getTypeReference(binding.enclosingType())); - } else if (binding instanceof IntersectionTypeBinding18) { - Set> bounds = new TreeSet<>(); - for (ReferenceBinding superInterface : binding.getIntersectingTypes()) { - bounds.add(getTypeReference(superInterface)); - } - ref = factory.Type().createIntersectionTypeReferenceWithBounds(bounds); - } else { - throw new RuntimeException("Unknown TypeBinding: " + binding.getClass() + " " + binding); - } - bindingCache.remove(binding); - return (CtTypeReference) ref; - } - - private CtCircularTypeReference getCtCircularTypeReference(TypeBinding b) { - final CtCircularTypeReference circularRef = factory.Internal().createCircularTypeReference(); - final CtTypeReference originalRef = bindingCache.get(b).clone(); - circularRef.setPackage(originalRef.getPackage()); - circularRef.setSimpleName(originalRef.getSimpleName()); - circularRef.setDeclaringType(originalRef.getDeclaringType()); - circularRef.setActualTypeArguments(originalRef.getActualTypeArguments()); - circularRef.setAnnotations(originalRef.getAnnotations()); - return circularRef; - } - - @SuppressWarnings("unchecked") - public CtVariableReference getVariableReference(MethodBinding methbin) { - CtFieldReference ref = factory.Core().createFieldReference(); - ref.setSimpleName(new String(methbin.selector)); - ref.setType((CtTypeReference) getTypeReference(methbin.returnType)); - - if (methbin.declaringClass != null) { - ref.setDeclaringType(getTypeReference(methbin.declaringClass)); - } else { - ref.setDeclaringType(ref.getType()); - } - return ref; - } - - @SuppressWarnings("unchecked") - public CtFieldReference getVariableReference(FieldBinding varbin) { - CtFieldReference ref = factory.Core().createFieldReference(); - if (varbin == null) { - return ref; - } - ref.setSimpleName(new String(varbin.name)); - ref.setType((CtTypeReference) getTypeReference(varbin.type)); - - if (varbin.declaringClass != null) { - ref.setDeclaringType(getTypeReference(varbin.declaringClass)); - } else { - ref.setDeclaringType(ref.getType()); - } - ref.setFinal(varbin.isFinal()); - ref.setStatic((varbin.modifiers & ClassFileConstants.AccStatic) != 0); - return ref; - } - - @SuppressWarnings("unchecked") - public CtVariableReference getVariableReference(VariableBinding varbin) { - - if (varbin instanceof FieldBinding) { - return getVariableReference((FieldBinding) varbin); - } else if (varbin instanceof LocalVariableBinding) { - final LocalVariableBinding localVariableBinding = (LocalVariableBinding) varbin; - if (localVariableBinding.declaration instanceof Argument && localVariableBinding.declaringScope instanceof MethodScope) { - CtParameterReference ref = factory.Core().createParameterReference(); - ref.setSimpleName(new String(varbin.name)); - ref.setType((CtTypeReference) getTypeReference(varbin.type)); - final ReferenceContext referenceContext = localVariableBinding.declaringScope.referenceContext(); - if (referenceContext instanceof LambdaExpression) { - ref.setDeclaringExecutable(getExecutableReference(((LambdaExpression) referenceContext).binding)); - } else { - ref.setDeclaringExecutable(getExecutableReference(((AbstractMethodDeclaration) referenceContext).binding)); - } - return ref; - } else if (localVariableBinding.declaration.binding instanceof CatchParameterBinding) { - CtCatchVariableReference ref = factory.Core().createCatchVariableReference(); - ref.setSimpleName(new String(varbin.name)); - CtTypeReference ref2 = getTypeReference(varbin.type); - ref.setType(ref2); - ref.setDeclaration((CtCatchVariable) getCatchVariableDeclaration(ref.getSimpleName())); - return ref; - } else { - CtLocalVariableReference ref = factory.Core().createLocalVariableReference(); - ref.setSimpleName(new String(varbin.name)); - CtTypeReference ref2 = getTypeReference(varbin.type); - ref.setType(ref2); - ref.setDeclaration((CtLocalVariable) getLocalVariableDeclaration(ref.getSimpleName())); - return ref; - } - } else { - // unknown VariableBinding, the caller must do something - return null; - } - } - - public CtVariableReference getVariableReference(ProblemBinding binding) { - CtFieldReference ref = factory.Core().createFieldReference(); - if (binding == null) { - return ref; - } - ref.setSimpleName(new String(binding.name)); - ref.setType((CtTypeReference) getTypeReference(binding.searchType)); - return ref; - } - - public List> getBoundedTypesReferences(TypeBinding[] genericTypeArguments) { - List> res = new ArrayList<>(genericTypeArguments.length); - for (TypeBinding tb : genericTypeArguments) { - res.add(getBoundedTypeReference(tb)); - } - return res; - } - } - /** * Sets {@code declaring} as inner of {@code ref}, as either the package or the declaring type */ - private void setPackageOrDeclaringType(CtTypeReference ref, CtReference declaring) { + /*private*/ void setPackageOrDeclaringType(CtTypeReference ref, CtReference declaring) { if (declaring instanceof CtPackageReference) { ref.setPackage((CtPackageReference) declaring); } else if (declaring instanceof CtTypeReference) { @@ -1166,89 +277,6 @@ private void setPackageOrDeclaringType(CtTypeReference ref, CtReference decla } } - public static Set getModifiers(int mod) { - Set ret = EnumSet.noneOf(ModifierKind.class); - if ((mod & ClassFileConstants.AccPublic) != 0) { - ret.add(ModifierKind.PUBLIC); - } - if ((mod & ClassFileConstants.AccPrivate) != 0) { - ret.add(ModifierKind.PRIVATE); - } - if ((mod & ClassFileConstants.AccProtected) != 0) { - ret.add(ModifierKind.PROTECTED); - } - if ((mod & ClassFileConstants.AccStatic) != 0) { - ret.add(ModifierKind.STATIC); - } - if ((mod & ClassFileConstants.AccFinal) != 0) { - ret.add(ModifierKind.FINAL); - } - if ((mod & ClassFileConstants.AccSynchronized) != 0) { - ret.add(ModifierKind.SYNCHRONIZED); - } - if ((mod & ClassFileConstants.AccVolatile) != 0) { - ret.add(ModifierKind.VOLATILE); - } - if ((mod & ClassFileConstants.AccTransient) != 0) { - ret.add(ModifierKind.TRANSIENT); - } - if ((mod & ClassFileConstants.AccAbstract) != 0) { - ret.add(ModifierKind.ABSTRACT); - } - if ((mod & ClassFileConstants.AccStrictfp) != 0) { - ret.add(ModifierKind.STRICTFP); - } - if ((mod & ClassFileConstants.AccNative) != 0) { - ret.add(ModifierKind.NATIVE); - } - return ret; - } - - /** - * Search the line number corresponding to a specific position - */ - public static final int searchLineNumber(int[] startLineIndexes, int position) { - if (startLineIndexes == null) { - return 1; - } - int length = startLineIndexes.length; - if (length == 0) { - return 1; - } - int g = 0, d = length - 1; - int m = 0, start; - while (g <= d) { - m = (g + d) / 2; - if (position < (start = startLineIndexes[m])) { - d = m - 1; - } else if (position > start) { - g = m + 1; - } else { - return m + 1; - } - } - if (position < startLineIndexes[m]) { - return m + 1; - } - return m + 2; - } - - BuilderContext context = new BuilderContext(); - - ParentExiter exiter = new ParentExiter(this); - - Factory factory; - - ReferenceBuilder references = new ReferenceBuilder(); - - public boolean template = false; - - public JDTTreeBuilder(Factory factory) { - super(); - this.factory = factory; - LOGGER.setLevel(factory.getEnvironment().getLevel()); - } - private CtTypeReference buildTypeReferenceInternal(CtTypeReference typeReference, TypeReference type, Scope scope) { if (type == null) { return null; @@ -1293,12 +321,9 @@ private CtTypeReference buildTypeReferenceInternal(CtTypeReference typ /** * Builds a type reference from a {@link TypeReference}. * - * @param type - * Type from JDT. - * @param scope - * Scope of the parent element. - * @param - * Type of the type reference. + * @param type Type from JDT. + * @param scope Scope of the parent element. + * @param Type of the type reference. * @return a type reference. */ private CtTypeReference buildTypeReference(TypeReference type, Scope scope) { @@ -1311,10 +336,8 @@ private CtTypeReference buildTypeReference(TypeReference type, Scope scop /** * Builds a type parameter reference from a {@link TypeReference} * - * @param type - * Type from JDT. - * @param scope - * Scope of the parent element. + * @param type Type from JDT. + * @param scope Scope of the parent element. * @return a type parameter reference. */ private CtTypeParameterReference buildTypeParameterReference(TypeReference type, Scope scope) { @@ -1376,7 +399,7 @@ CtType createType(TypeDeclaration typeDeclaration) { if ((resolvedType instanceof MemberTypeBinding || resolvedType instanceof BinaryTypeBinding) && resolvedType.enclosingType() != null && typeDeclaration.enclosingType.superclass != null - && Collections.disjoint(modifiers, getModifiers(resolvedType.enclosingType().modifiers))) { + && Collections.disjoint(modifiers, HelperJDTTreeBuilder.getModifiers(resolvedType.enclosingType().modifiers))) { typeDeclaration.superclass.resolvedType = new SpoonReferenceBinding(typeDeclaration.superclass.resolvedType.sourceName(), (ReferenceBinding) typeDeclaration.enclosingType.superclass.resolvedType); } @@ -1384,10 +407,8 @@ CtType createType(TypeDeclaration typeDeclaration) { if (typeDeclaration.superclass != null) { ((CtClass) type).setSuperclass(buildTypeReference(typeDeclaration.superclass, typeDeclaration.scope)); } - } - if (type instanceof CtClass) { if (typeDeclaration.binding.isAnonymousType() || (typeDeclaration.binding instanceof LocalTypeBinding && typeDeclaration.binding.enclosingMethod() != null)) { - type.setSimpleName(computeAnonymousName(typeDeclaration.binding)); + type.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName(typeDeclaration.binding)); } else { type.setSimpleName(new String(typeDeclaration.name)); } @@ -1396,7 +417,7 @@ CtType createType(TypeDeclaration typeDeclaration) { } // Setting modifiers - type.setModifiers(getModifiers(typeDeclaration.modifiers)); + type.setModifiers(HelperJDTTreeBuilder.getModifiers(typeDeclaration.modifiers)); return type; } @@ -1415,62 +436,6 @@ public ReferenceBinding enclosingType() { } } - private String computeAnonymousName(SourceTypeBinding binding) { - final String poolName = String.valueOf(binding.constantPoolName()); - final int lastIndexSeparator = poolName.lastIndexOf(CtType.INNERTTYPE_SEPARATOR); - return poolName.substring(lastIndexSeparator + 1, poolName.length()); - } - - /** - * When an annotation is specified on a method, a local declaration or an argument, JDT doesn't know - * if the annotation is specified on the type or on the element. Due to this method, if the annotation - * is compatible with types, we substitute the annotation from the element to the type of this element. - * - * @param typedElement - * Element annotated. - * @param a - * Annotation of the element. - * @param elementType - * Type of the annotation. - */ - private void substituteAnnotation(CtTypedElement typedElement, Annotation a, CtAnnotatedElementType elementType) { - if (hasAnnotationWithType(a, elementType)) { - CtAnnotation targetAnnotation = typedElement.getAnnotations().get(typedElement.getAnnotations().size() - 1); - typedElement.removeAnnotation(targetAnnotation); - typedElement.getType().addAnnotation(targetAnnotation); - } - } - - /** - * Check if the annotation is declared with the given element type. - * - * @param a - * An annotation. - * @param elementType - * Type of the annotation. - * @return true if the annotation is compitble with the given element type. - */ - private boolean hasAnnotationWithType(Annotation a, CtAnnotatedElementType elementType) { - if (a.resolvedType == null) { - return false; - } - for (AnnotationBinding annotation : a.resolvedType.getAnnotations()) { - if (!"Target".equals(CharOperation.charToString(annotation.getAnnotationType().sourceName()))) { - continue; - } - Object value = annotation.getElementValuePairs()[0].value; - if (value == null || !value.getClass().isArray()) { - continue; - } - Object[] fields = (Object[]) value; - for (Object field : fields) { - if (field instanceof FieldBinding && elementType.name().equals(CharOperation.charToString(((FieldBinding) field).name))) { - return true; - } - } - } - return false; - } @Override public void endVisit(AllocationExpression allocationExpression, BlockScope scope) { @@ -1946,61 +911,6 @@ public void endVisit(WhileStatement whileStatement, BlockScope scope) { context.exit(whileStatement); } - BinaryOperatorKind getBinaryOperatorKind(int bits) { - // switch ((bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) { - switch (bits) { - case OperatorIds.EQUAL_EQUAL: - return BinaryOperatorKind.EQ; - case OperatorIds.LESS_EQUAL: - return BinaryOperatorKind.LE; - case OperatorIds.GREATER_EQUAL: - return BinaryOperatorKind.GE; - case OperatorIds.NOT_EQUAL: - return BinaryOperatorKind.NE; - case OperatorIds.LEFT_SHIFT: - return BinaryOperatorKind.SL; - case OperatorIds.RIGHT_SHIFT: - return BinaryOperatorKind.SR; - case OperatorIds.UNSIGNED_RIGHT_SHIFT: - return BinaryOperatorKind.USR; - case OperatorIds.OR_OR: - return BinaryOperatorKind.OR; - case OperatorIds.AND_AND: - return BinaryOperatorKind.AND; - case OperatorIds.PLUS: - return BinaryOperatorKind.PLUS; - case OperatorIds.MINUS: - return BinaryOperatorKind.MINUS; - case OperatorIds.NOT: - return BinaryOperatorKind.NE; - case OperatorIds.REMAINDER: - return BinaryOperatorKind.MOD; - case OperatorIds.XOR: - return BinaryOperatorKind.BITXOR; - case OperatorIds.AND: - return BinaryOperatorKind.BITAND; - case OperatorIds.MULTIPLY: - return BinaryOperatorKind.MUL; - case OperatorIds.OR: - return BinaryOperatorKind.BITOR; - case OperatorIds.DIVIDE: - return BinaryOperatorKind.DIV; - case OperatorIds.GREATER: - return BinaryOperatorKind.GT; - case OperatorIds.LESS: - return BinaryOperatorKind.LT; - case OperatorIds.QUESTIONCOLON: - throw new RuntimeException("Unknown operator"); - case OperatorIds.EQUAL: - return BinaryOperatorKind.EQ; - } - return null; - } - - public List> getCreatedTypes() { - return context.getCreatedTypes(); - } - protected CtLocalVariable getLocalVariableDeclaration(final String name) { for (ASTPair astPair : context.stack) { // TODO check if the variable is visible from here @@ -2054,20 +964,6 @@ public void visitCtCatchVariable(CtCatchVariable catchVariable) { return null; } - UnaryOperatorKind getUnaryOperator(int op) { - switch (op) { - case OperatorIds.PLUS: - return UnaryOperatorKind.POS; - case OperatorIds.MINUS: - return UnaryOperatorKind.NEG; - case OperatorIds.NOT: - return UnaryOperatorKind.NOT; - case OperatorIds.TWIDDLE: - return UnaryOperatorKind.COMPL; - } - return null; - } - @Override public boolean visit(ReferenceExpression referenceExpression, BlockScope blockScope) { CtExecutableReferenceExpression executableRef = createExecutableReferenceExpression(referenceExpression); @@ -2197,7 +1093,7 @@ private > T buildCommonPartForCtNewClassAndC @Override public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(getBinaryOperatorKind((and_and_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((and_and_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, and_and_Expression); return true; // do nothing by default, keep traversing } @@ -2213,7 +1109,7 @@ public boolean visit(AnnotationMethodDeclaration annotationTypeDeclaration, Clas if (annotationTypeDeclaration.annotations != null) { for (Annotation a : annotationTypeDeclaration.annotations) { a.traverse(this, annotationTypeDeclaration.scope); - substituteAnnotation(f, a, CtAnnotatedElementType.TYPE_USE); + HelperJDTTreeBuilder.substituteAnnotation(f, a, CtAnnotatedElementType.TYPE_USE); } } @@ -2230,7 +1126,7 @@ public boolean visit(Argument argument, BlockScope scope) { CtParameter p = factory.Core().createParameter(); p.setSimpleName(new String(argument.name)); p.setVarArgs(argument.isVarArgs()); - p.setModifiers(getModifiers(argument.modifiers)); + p.setModifiers(HelperJDTTreeBuilder.getModifiers(argument.modifiers)); if (argument.binding != null && argument.binding.type != null) { context.isLambdaParameterImplicitlyTyped = argument.type != null; if (argument.binding.type instanceof WildcardBinding) { @@ -2265,7 +1161,7 @@ public boolean onAccess(char[][] tokens, int index) { if (argument.annotations != null) { for (Annotation a : argument.annotations) { a.traverse(this, scope); - substituteAnnotation(p, a, CtAnnotatedElementType.TYPE_USE); + HelperJDTTreeBuilder.substituteAnnotation(p, a, CtAnnotatedElementType.TYPE_USE); } } @@ -2398,7 +1294,7 @@ public boolean visit(Assignment assignment, BlockScope scope) { @Override public boolean visit(BinaryExpression binaryExpression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(getBinaryOperatorKind((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, binaryExpression); return true; } @@ -2458,7 +1354,7 @@ public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) { @Override public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) { CtOperatorAssignment a = factory.Core().createOperatorAssignment(); - a.setKind(getBinaryOperatorKind(compoundAssignment.operator)); + a.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind(compoundAssignment.operator)); context.enter(a, compoundAssignment); context.arguments.push(a); context.assigned = true; @@ -2484,7 +1380,7 @@ public boolean visit(ConditionalExpression conditionalExpression, BlockScope sco @Override public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { CtConstructor c = factory.Core().createConstructor(); - c.setModifiers(getModifiers(constructorDeclaration.modifiers)); + c.setModifiers(HelperJDTTreeBuilder.getModifiers(constructorDeclaration.modifiers)); context.enter(c, constructorDeclaration); @@ -2610,7 +1506,7 @@ public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) { @Override public boolean visit(EqualExpression equalExpression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(getBinaryOperatorKind((equalExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((equalExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, equalExpression); return true; // do nothing by default, keep traversing } @@ -2683,7 +1579,7 @@ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { } } field.setSimpleName(new String(fieldDeclaration.name)); - field.setModifiers(getModifiers(fieldDeclaration.modifiers)); + field.setModifiers(HelperJDTTreeBuilder.getModifiers(fieldDeclaration.modifiers)); if (fieldDeclaration.annotations != null) { int annotationsLength = fieldDeclaration.annotations.length; @@ -2830,7 +1726,7 @@ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { CtLocalVariable v = factory.Core().createLocalVariable(); v.setSimpleName(new String(localDeclaration.name)); v.setType(buildTypeReference(localDeclaration.type, scope)); - v.setModifiers(getModifiers(localDeclaration.modifiers)); + v.setModifiers(HelperJDTTreeBuilder.getModifiers(localDeclaration.modifiers)); context.enter(v, localDeclaration); if (localDeclaration.initialization != null) { @@ -2842,7 +1738,7 @@ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { if (localDeclaration.annotations != null) { for (Annotation a : localDeclaration.annotations) { a.traverse(this, scope); - substituteAnnotation(v, a, CtAnnotatedElementType.TYPE_USE); + HelperJDTTreeBuilder.substituteAnnotation(v, a, CtAnnotatedElementType.TYPE_USE); } } @@ -3024,7 +1920,7 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { CtMethod m = factory.Core().createMethod(); m.setSimpleName(new String(methodDeclaration.selector)); m.setType(buildTypeReference(methodDeclaration.returnType, scope)); - m.setModifiers(getModifiers(methodDeclaration.modifiers)); + m.setModifiers(HelperJDTTreeBuilder.getModifiers(methodDeclaration.modifiers)); m.setDefaultMethod(methodDeclaration.isDefaultMethod()); context.enter(m, methodDeclaration); @@ -3045,7 +1941,7 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { if (methodDeclaration.annotations != null) { for (Annotation a : methodDeclaration.annotations) { a.traverse(this, methodDeclaration.scope); - substituteAnnotation(m, a, CtAnnotatedElementType.TYPE_USE); + HelperJDTTreeBuilder.substituteAnnotation(m, a, CtAnnotatedElementType.TYPE_USE); } } @@ -3081,7 +1977,7 @@ public boolean visit(NullLiteral nullLiteral, BlockScope scope) { @Override public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(getBinaryOperatorKind((or_or_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((or_or_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, or_or_Expression); return true; } @@ -3312,7 +2208,7 @@ public boolean onAccess(char[][] tokens, int index) { final CtTypeAccess ta = factory.Code().createTypeAccessWithoutCloningReference(typeReference); context.enter(ta, qualifiedNameReference); return false; - } else if (context.stack.peek().element instanceof CtAssignment && context.assigned) { + } else if (context.stack.peek().element instanceof CtAssignment && context.assigned) { va = factory.Core().createFieldWrite(); } else { va = factory.Core().createFieldRead(); @@ -3328,7 +2224,7 @@ public boolean onAccess(char[][] tokens, int index) { ((CtFieldAccess) va).setTarget(factory.Code().createTypeAccess(declaringRef)); } // In no classpath mode and with qualified name, the binding don't have a good name. - va.getVariable().setSimpleName(createTypeName(CharOperation.subarray(qualifiedNameReference.tokens, qualifiedNameReference.tokens.length - 1, qualifiedNameReference.tokens.length))); + va.getVariable().setSimpleName(HelperJDTTreeBuilder.createTypeName(CharOperation.subarray(qualifiedNameReference.tokens, qualifiedNameReference.tokens.length - 1, qualifiedNameReference.tokens.length))); context.enter(va, qualifiedNameReference); return false; } else { @@ -3674,7 +2570,7 @@ private CtCatch createCtCatch(Argument jdtCatch, CtTypeReference r) { context.enter(var, jdtCatch); var.setSimpleName(new String(jdtCatch.name)); var.setType(r); - for (ModifierKind modifier : getModifiers(jdtCatch.modifiers)) { + for (ModifierKind modifier : HelperJDTTreeBuilder.getModifiers(jdtCatch.modifiers)) { var.addModifier(modifier); } context.exit(jdtCatch); @@ -3691,7 +2587,7 @@ private CtCatch createCtCatchJava7(Argument jdtCatch, CtTypeReference for (CtTypeReference ref : refs) { var.addMultiType(ref); } - for (ModifierKind modifier : getModifiers(jdtCatch.modifiers)) { + for (ModifierKind modifier : HelperJDTTreeBuilder.getModifiers(jdtCatch.modifiers)) { var.addModifier(modifier); } context.exit(jdtCatch); @@ -3798,7 +2694,7 @@ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope @Override public boolean visit(UnaryExpression unaryExpression, BlockScope scope) { CtUnaryOperator op = factory.Core().createUnaryOperator(); - op.setKind(getUnaryOperator((unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(HelperJDTTreeBuilder.getUnaryOperator((unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, unaryExpression); return true; } diff --git a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java index 5932b5ea83b..713fa81180f 100644 --- a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java +++ b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java @@ -462,7 +462,6 @@ public void visitCtPackage(CtPackage ctPackage) { ctPackage.getTypes().remove(child); } ctPackage.getTypes().add((CtType) child); - this.jdtTreeBuilder.context.addCreatedType((CtType) child); if (child.getPosition() != null && child.getPosition().getCompilationUnit() != null) { child.getPosition().getCompilationUnit().getDeclaredTypes().add((CtType) child); } diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java new file mode 100644 index 00000000000..b94163def58 --- /dev/null +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -0,0 +1,681 @@ +/** + * Copyright (C) 2006-2016 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.compiler.jdt; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Argument; +import org.eclipse.jdt.internal.compiler.ast.ImportReference; +import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.ast.Wildcard; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; +import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; +import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.Binding; +import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding; +import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding; +import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; +import org.eclipse.jdt.internal.compiler.lookup.IntersectionTypeBinding18; +import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; +import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding; +import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; +import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; +import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; +import spoon.reflect.code.CtCatchVariable; +import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.internal.CtCircularTypeReference; +import spoon.reflect.reference.CtArrayTypeReference; +import spoon.reflect.reference.CtCatchVariableReference; +import spoon.reflect.reference.CtExecutableReference; +import spoon.reflect.reference.CtFieldReference; +import spoon.reflect.reference.CtLocalVariableReference; +import spoon.reflect.reference.CtPackageReference; +import spoon.reflect.reference.CtParameterReference; +import spoon.reflect.reference.CtReference; +import spoon.reflect.reference.CtTypeParameterReference; +import spoon.reflect.reference.CtTypeReference; +import spoon.reflect.reference.CtVariableReference; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ReferenceBuilder { + + Map> basestypes = new TreeMap<>(); + + boolean bounds = false; + + boolean isImplicit = false; + + private final JDTTreeBuilder jdtTreeBuilder; + + public ReferenceBuilder(JDTTreeBuilder jdtTreeBuilder) { + this.jdtTreeBuilder = jdtTreeBuilder; + } + + public CtTypeReference getBoundedTypeReference(TypeBinding binding) { + bounds = true; + CtTypeReference ref = getTypeReference(binding); + bounds = false; + return ref; + } + + /** + * Try to get the declaring reference (package or type) from imports of the current + * compilation unit declaration (current class). This method returns a CtReference + * which can be a CtTypeReference if it retrieves the information in an static import, + * a CtPackageReference if it retrieves the information in an standard import, otherwise + * it returns null. + * + * @param expectedName Name expected in imports. + * @return CtReference which can be a CtTypeReference, a CtPackageReference or null. + */ + public CtReference getDeclaringReferenceFromImports(char[] expectedName) { + if (this.jdtTreeBuilder.context.compilationunitdeclaration != null && this.jdtTreeBuilder.context.compilationunitdeclaration.imports != null) { + for (ImportReference anImport : this.jdtTreeBuilder.context.compilationunitdeclaration.imports) { + if (CharOperation.equals(anImport.getImportName()[anImport.getImportName().length - 1], expectedName)) { + if (anImport.isStatic()) { + int indexDeclaring = 2; + if ((anImport.bits & ASTNode.OnDemand) != 0) { + // With .* + indexDeclaring = 1; + } + char[][] packageName = CharOperation.subarray(anImport.getImportName(), 0, anImport.getImportName().length - indexDeclaring); + char[][] className = CharOperation.subarray(anImport.getImportName(), anImport.getImportName().length - indexDeclaring, anImport.getImportName().length - (indexDeclaring - 1)); + PackageBinding aPackage; + if (packageName.length != 0) { + aPackage = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment.createPackage(packageName); + } else { + aPackage = null; + } + final MissingTypeBinding declaringType = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment.createMissingType(aPackage, className); + this.jdtTreeBuilder.context.ignoreComputeImports = true; + final CtTypeReference typeReference = getTypeReference(declaringType); + this.jdtTreeBuilder.context.ignoreComputeImports = false; + return typeReference; + } else { + char[][] chars = CharOperation.subarray(anImport.getImportName(), 0, anImport.getImportName().length - 1); + Binding someBinding = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.findImport(chars, false, false); + PackageBinding packageBinding; + if (someBinding != null && someBinding.isValidBinding() && someBinding instanceof PackageBinding) { + packageBinding = (PackageBinding) someBinding; + } else { + packageBinding = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment.createPackage(chars); + if (packageBinding == null) { + // Big crisis here. We are already in noclasspath mode but JDT doesn't support always + // creation of a package in this mode. So, if we are in this brace, we make the job of JDT... + packageBinding = new PackageBinding(chars, null, this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment); + } + } + return getPackageReference(packageBinding); + } + } + } + } + return null; + } + + @SuppressWarnings("unchecked") + public CtExecutableReference getExecutableReference(MethodBinding exec) { + if (exec == null) { + return null; + } + + final CtExecutableReference ref = this.jdtTreeBuilder.factory.Core().createExecutableReference(); + ref.setSimpleName(new String(exec.selector)); + ref.setType(getTypeReference(exec.returnType)); + + if (exec instanceof ProblemMethodBinding) { + if (exec.declaringClass != null && Arrays.asList(exec.declaringClass.methods()).contains(exec)) { + ref.setDeclaringType(getTypeReference(exec.declaringClass)); + } else { + final CtReference declaringType = getDeclaringReferenceFromImports(exec.constantPoolName()); + if (declaringType instanceof CtTypeReference) { + ref.setDeclaringType((CtTypeReference) declaringType); + } + } + if (exec.isConstructor()) { + // super() invocation have a good declaring class. + ref.setDeclaringType(getTypeReference(exec.declaringClass)); + } + ref.setStatic(true); + } else { + ref.setDeclaringType(getTypeReference(exec.declaringClass)); + ref.setStatic(exec.isStatic()); + } + + if (exec.declaringClass instanceof ParameterizedTypeBinding) { + ref.setDeclaringType(getTypeReference(exec.declaringClass.actualType())); + } + + // original() method returns a result not null when the current method is generic. + if (exec.original() != null) { + final List> parameters = new ArrayList<>(exec.original().parameters.length); + for (TypeBinding b : exec.original().parameters) { + parameters.add(getTypeReference(b)); + } + ref.setParameters(parameters); + } else if (exec.parameters != null) { + // This is a method without a generic argument. + final List> parameters = new ArrayList<>(); + for (TypeBinding b : exec.parameters) { + parameters.add(getTypeReference(b)); + } + ref.setParameters(parameters); + } + + return ref; + } + + public CtPackageReference getPackageReference(PackageBinding reference) { + String name = new String(reference.shortReadableName()); + if (name.length() == 0) { + return this.jdtTreeBuilder.factory.Package().topLevel(); + } + CtPackageReference ref = this.jdtTreeBuilder.factory.Core().createPackageReference(); + ref.setSimpleName(name); + return ref; + } + + final Map bindingCache = new HashMap<>(); + + public CtTypeReference getTypeReference(TypeBinding binding, TypeReference ref) { + CtTypeReference ctRef = getTypeReference(binding); + if (ctRef != null && isCorrectTypeReference(ref)) { + insertGenericTypesInNoClasspathFromJDTInSpoon(ref, ctRef); + return ctRef; + } + return getTypeReference(ref); + } + + public CtTypeReference getTypeParameterReference(TypeBinding binding, TypeReference ref) { + CtTypeReference ctRef = getTypeReference(binding); + if (ctRef != null && isCorrectTypeReference(ref)) { + if (!(ctRef instanceof CtTypeParameterReference)) { + CtTypeParameterReference typeParameterRef = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + typeParameterRef.setSimpleName(ctRef.getSimpleName()); + typeParameterRef.setDeclaringType(ctRef.getDeclaringType()); + typeParameterRef.setPackage(ctRef.getPackage()); + typeParameterRef.setActualTypeArguments(ctRef.getActualTypeArguments()); + ctRef = typeParameterRef; + } + insertGenericTypesInNoClasspathFromJDTInSpoon(ref, ctRef); + return ctRef; + } + return getTypeParameterReference(CharOperation.toString(ref.getParameterizedTypeName())); + } + + /** + * In no classpath, the model of the super interface isn't always correct. + */ + private boolean isCorrectTypeReference(TypeReference ref) { + if (ref.resolvedType == null) { + return false; + } + if (!(ref.resolvedType instanceof ProblemReferenceBinding)) { + return true; + } + final String[] compoundName = CharOperation.charArrayToStringArray(((ProblemReferenceBinding) ref.resolvedType).compoundName); + final String[] typeName = CharOperation.charArrayToStringArray(ref.getTypeName()); + if (compoundName.length == 0 || typeName.length == 0) { + return false; + } + return compoundName[compoundName.length - 1].equals(typeName[typeName.length - 1]); + } + + private void insertGenericTypesInNoClasspathFromJDTInSpoon(TypeReference original, CtTypeReference type) { + if (original.resolvedType instanceof ProblemReferenceBinding && original.getTypeArguments() != null) { + for (TypeReference[] typeReferences : original.getTypeArguments()) { + for (TypeReference typeReference : typeReferences) { + type.addActualTypeArgument(this.getTypeReference(typeReference.resolvedType)); + } + } + } + } + + /** + * JDT doesn't return a correct AST with the resolved type of the reference. + * This method try to build a correct Spoon AST from the name of the JDT + * reference, thanks to the parsing of the string, the name parameterized from + * the JDT reference and java convention. + * Returns a complete Spoon AST when the name is correct, otherwise a spoon type + * reference with a name that correspond to the name of the JDT type reference. + */ + public CtTypeReference getTypeReference(TypeReference ref) { + CtTypeReference res = null; + CtTypeReference inner = null; + final String[] namesParameterized = CharOperation.charArrayToStringArray(ref.getParameterizedTypeName()); + int index = namesParameterized.length - 1; + for (; index >= 0; index--) { + // Start at the end to get the class name first. + CtTypeReference main = getTypeReference(namesParameterized[index]); + if (main == null) { + break; + } + if (res == null) { + res = (CtTypeReference) main; + } else { + inner.setDeclaringType((CtTypeReference) main); + } + inner = main; + } + if (res == null) { + return this.jdtTreeBuilder.factory.Type().createReference(CharOperation.toString(ref.getParameterizedTypeName())); + } + CtPackageReference packageReference = index >= 0 + ? this.jdtTreeBuilder.factory.Package().getOrCreate(concatSubArray(namesParameterized, index)).getReference() + : this.jdtTreeBuilder.factory.Package().topLevel(); + inner.setPackage(packageReference); + return res; + } + + private String concatSubArray(String[] a, int endIndex) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < endIndex; i++) { + sb.append(a[i]).append('.'); + } + sb.append(a[endIndex]); + return sb.toString(); + } + + /** + * Try to build a CtTypeReference from a simple name with specified generic types but + * returns null if the name doesn't correspond to a type (not start by an upper case). + */ + public CtTypeReference getTypeReference(String name) { + CtTypeReference main = null; + if (name.matches(".*(<.+>)")) { + Pattern pattern = Pattern.compile("([^<]+)<(.+)>"); + Matcher m = pattern.matcher(name); + if (name.startsWith("?")) { + main = (CtTypeReference) this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + } else { + main = this.jdtTreeBuilder.factory.Core().createTypeReference(); + } + if (m.find()) { + main.setSimpleName(m.group(1)); + final String[] split = m.group(2).split(","); + for (String parameter : split) { + ((CtTypeReference) main).addActualTypeArgument(getTypeParameterReference(parameter.trim())); + } + } + } else if (Character.isUpperCase(name.charAt(0))) { + main = this.jdtTreeBuilder.factory.Core().createTypeReference(); + main.setSimpleName(name); + } else if (name.startsWith("?")) { + return (CtTypeReference) this.jdtTreeBuilder.factory.Type().createTypeParameterReference(name); + } + return main; + } + + /** + * Try to build a CtTypeParameterReference from a single name with specified generic types but + * keep in mind that if you give wrong data in the strong, reference will be wrong. + */ + public CtTypeParameterReference getTypeParameterReference(String name) { + CtTypeParameterReference param = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + if (name.contains("extends") || name.contains("super")) { + String[] split = name.contains("extends") ? name.split("extends") : name.split("super"); + param.setSimpleName(split[0].trim()); + param.setBoundingType(getTypeReference(split[split.length - 1].trim())); + } else if (name.matches(".*(<.+>)")) { + Pattern pattern = Pattern.compile("([^<]+)<(.+)>"); + Matcher m = pattern.matcher(name); + if (m.find()) { + param.setSimpleName(m.group(1)); + final String[] split = m.group(2).split(","); + for (String parameter : split) { + param.addActualTypeArgument(getTypeParameterReference(parameter.trim())); + } + } + } else { + param.setSimpleName(name); + } + return param; + } + + @SuppressWarnings("unchecked") + public CtTypeReference getTypeReference(TypeBinding binding) { + if (binding == null) { + return null; + } + + CtTypeReference ref = null; + + if (binding instanceof RawTypeBinding) { + ref = getTypeReference(((ParameterizedTypeBinding) binding).genericType()); + } else if (binding instanceof ParameterizedTypeBinding) { + if (binding.actualType() != null && binding.actualType() instanceof LocalTypeBinding) { + // When we define a nested class in a method and when the enclosing class of this method + // is a parameterized type binding, JDT give a ParameterizedTypeBinding for the nested class + // and hide the real class in actualType(). + ref = getTypeReference(binding.actualType()); + } else { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + if (binding.isAnonymousType()) { + ref.setSimpleName(""); + } else { + ref.setSimpleName(String.valueOf(binding.sourceName())); + if (binding.enclosingType() != null) { + ref.setDeclaringType(getTypeReference(binding.enclosingType())); + } else { + ref.setPackage(getPackageReference(binding.getPackage())); + } + } + } + + if (((ParameterizedTypeBinding) binding).arguments != null) { + for (TypeBinding b : ((ParameterizedTypeBinding) binding).arguments) { + if (!this.jdtTreeBuilder.context.isGenericTypeExplicit) { + isImplicit = true; + } + if (bindingCache.containsKey(b)) { + ref.addActualTypeArgument(getCtCircularTypeReference(b)); + } else { + ref.addActualTypeArgument(getTypeReference(b)); + } + isImplicit = false; + } + } + } else if (binding instanceof MissingTypeBinding) { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setSimpleName(new String(binding.sourceName())); + ref.setPackage(getPackageReference(binding.getPackage())); + if (!this.jdtTreeBuilder.context.ignoreComputeImports) { + final CtReference declaring = this.getDeclaringReferenceFromImports(binding.sourceName()); + if (declaring instanceof CtPackageReference) { + ref.setPackage((CtPackageReference) declaring); + } else if (declaring instanceof CtTypeReference) { + ref.setDeclaringType((CtTypeReference) declaring); + } + } + } else if (binding instanceof BinaryTypeBinding) { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + if (binding.enclosingType() != null) { + ref.setDeclaringType(getTypeReference(binding.enclosingType())); + } else { + ref.setPackage(getPackageReference(binding.getPackage())); + } + ref.setSimpleName(new String(binding.sourceName())); + } else if (binding instanceof TypeVariableBinding) { + boolean oldBounds = bounds; + ref = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + if (binding instanceof CaptureBinding) { + ref.setSimpleName("?"); + bounds = true; + } else { + ref.setSimpleName(new String(binding.sourceName())); + } + TypeVariableBinding b = (TypeVariableBinding) binding; + if (bounds) { + if (b instanceof CaptureBinding && ((CaptureBinding) b).wildcard != null) { + bounds = oldBounds; + return getTypeReference(((CaptureBinding) b).wildcard); + } else if (b.superclass != null && b.firstBound == b.superclass) { + bounds = false; + bindingCache.put(binding, ref); + ((CtTypeParameterReference) ref).setBoundingType(getTypeReference(b.superclass)); + bounds = oldBounds; + } + } + if (bounds && b.superInterfaces != null && b.superInterfaces != Binding.NO_SUPERINTERFACES) { + bounds = false; + bindingCache.put(binding, ref); + Set> bounds = new TreeSet<>(); + if (((CtTypeParameterReference) ref).getBoundingType() != null) { + bounds.add(((CtTypeParameterReference) ref).getBoundingType()); + } + for (ReferenceBinding superInterface : b.superInterfaces) { + bounds.add(getTypeReference(superInterface)); + } + ((CtTypeParameterReference) ref).setBoundingType(this.jdtTreeBuilder.factory.Type().createIntersectionTypeReferenceWithBounds(bounds)); + } + if (binding instanceof CaptureBinding) { + bounds = false; + } + } else if (binding instanceof BaseTypeBinding) { + String name = new String(binding.sourceName()); + if (!this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped) { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setImplicit(true); + ref.setSimpleName(name); + } else { + ref = basestypes.get(name); + if (ref == null) { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setSimpleName(name); + basestypes.put(name, ref); + } else { + ref = ref == null ? ref : ref.clone(); + } + } + } else if (binding instanceof WildcardBinding) { + ref = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref.setSimpleName("?"); + if (((WildcardBinding) binding).boundKind == Wildcard.SUPER && ref instanceof CtTypeParameterReference) { + ((CtTypeParameterReference) ref).setUpper(false); + } + + if (((WildcardBinding) binding).bound != null && ref instanceof CtTypeParameterReference) { + if (bindingCache.containsKey(((WildcardBinding) binding).bound)) { + final CtCircularTypeReference circularRef = getCtCircularTypeReference(((WildcardBinding) binding).bound); + ((CtTypeParameterReference) ref).setBoundingType(circularRef); + } else { + ((CtTypeParameterReference) ref).setBoundingType(getTypeReference(((WildcardBinding) binding).bound)); + } + } + } else if (binding instanceof LocalTypeBinding) { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + if (binding.isAnonymousType()) { + ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); + ref.setDeclaringType(getTypeReference((binding.enclosingType()))); + } else { + ref.setSimpleName(new String(binding.sourceName())); + if (((LocalTypeBinding) binding).enclosingMethod == null && binding.enclosingType() != null && binding.enclosingType() instanceof LocalTypeBinding) { + ref.setDeclaringType(getTypeReference(binding.enclosingType())); + } else if (binding.enclosingMethod() != null) { + ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); + ref.setDeclaringType(getTypeReference(binding.enclosingType())); + } + } + } else if (binding instanceof SourceTypeBinding) { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + if (binding.isAnonymousType()) { + ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); + ref.setDeclaringType(getTypeReference((binding.enclosingType()))); + } else { + ref.setSimpleName(new String(binding.sourceName())); + if (binding.enclosingType() != null) { + ref.setDeclaringType(getTypeReference(binding.enclosingType())); + } else { + ref.setPackage(getPackageReference(binding.getPackage())); + } + // if(((SourceTypeBinding) binding).typeVariables!=null && + // ((SourceTypeBinding) binding).typeVariables.length>0){ + // for (TypeBinding b : ((SourceTypeBinding) + // binding).typeVariables) { + // ref.getActualTypeArguments().add(getTypeReference(b)); + // } + // } + } + } else if (binding instanceof ArrayBinding) { + CtArrayTypeReference arrayref; + arrayref = this.jdtTreeBuilder.factory.Core().createArrayTypeReference(); + arrayref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = arrayref; + for (int i = 1; i < binding.dimensions(); i++) { + CtArrayTypeReference tmp = this.jdtTreeBuilder.factory.Core().createArrayTypeReference(); + arrayref.setComponentType(tmp); + arrayref = tmp; + } + arrayref.setComponentType(getTypeReference(binding.leafComponentType())); + } else if (binding instanceof ProblemReferenceBinding || binding instanceof PolyTypeBinding) { + // Spoon is able to analyze also without the classpath + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref.setSimpleName(new String(binding.readableName())); + final CtReference declaring = this.getDeclaringReferenceFromImports(binding.sourceName()); + this.jdtTreeBuilder.setPackageOrDeclaringType(ref, declaring); + } else if (binding instanceof JDTTreeBuilder.SpoonReferenceBinding) { + ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref.setSimpleName(new String(binding.sourceName())); + ref.setDeclaringType(getTypeReference(binding.enclosingType())); + } else if (binding instanceof IntersectionTypeBinding18) { + Set> bounds = new TreeSet<>(); + for (ReferenceBinding superInterface : binding.getIntersectingTypes()) { + bounds.add(getTypeReference(superInterface)); + } + ref = this.jdtTreeBuilder.factory.Type().createIntersectionTypeReferenceWithBounds(bounds); + } else { + throw new RuntimeException("Unknown TypeBinding: " + binding.getClass() + " " + binding); + } + bindingCache.remove(binding); + return (CtTypeReference) ref; + } + + private CtCircularTypeReference getCtCircularTypeReference(TypeBinding b) { + final CtCircularTypeReference circularRef = this.jdtTreeBuilder.factory.Internal().createCircularTypeReference(); + final CtTypeReference originalRef = bindingCache.get(b).clone(); + circularRef.setPackage(originalRef.getPackage()); + circularRef.setSimpleName(originalRef.getSimpleName()); + circularRef.setDeclaringType(originalRef.getDeclaringType()); + circularRef.setActualTypeArguments(originalRef.getActualTypeArguments()); + circularRef.setAnnotations(originalRef.getAnnotations()); + return circularRef; + } + + @SuppressWarnings("unchecked") + public CtVariableReference getVariableReference(MethodBinding methbin) { + CtFieldReference ref = this.jdtTreeBuilder.factory.Core().createFieldReference(); + ref.setSimpleName(new String(methbin.selector)); + ref.setType((CtTypeReference) getTypeReference(methbin.returnType)); + + if (methbin.declaringClass != null) { + ref.setDeclaringType(getTypeReference(methbin.declaringClass)); + } else { + ref.setDeclaringType(ref.getType()); + } + return ref; + } + + @SuppressWarnings("unchecked") + public CtFieldReference getVariableReference(FieldBinding varbin) { + CtFieldReference ref = this.jdtTreeBuilder.factory.Core().createFieldReference(); + if (varbin == null) { + return ref; + } + ref.setSimpleName(new String(varbin.name)); + ref.setType((CtTypeReference) getTypeReference(varbin.type)); + + if (varbin.declaringClass != null) { + ref.setDeclaringType(getTypeReference(varbin.declaringClass)); + } else { + ref.setDeclaringType(ref.getType()); + } + ref.setFinal(varbin.isFinal()); + ref.setStatic((varbin.modifiers & ClassFileConstants.AccStatic) != 0); + return ref; + } + + @SuppressWarnings("unchecked") + public CtVariableReference getVariableReference(VariableBinding varbin) { + + if (varbin instanceof FieldBinding) { + return getVariableReference((FieldBinding) varbin); + } else if (varbin instanceof LocalVariableBinding) { + final LocalVariableBinding localVariableBinding = (LocalVariableBinding) varbin; + if (localVariableBinding.declaration instanceof Argument && localVariableBinding.declaringScope instanceof MethodScope) { + CtParameterReference ref = this.jdtTreeBuilder.factory.Core().createParameterReference(); + ref.setSimpleName(new String(varbin.name)); + ref.setType((CtTypeReference) getTypeReference(varbin.type)); + final ReferenceContext referenceContext = localVariableBinding.declaringScope.referenceContext(); + if (referenceContext instanceof LambdaExpression) { + ref.setDeclaringExecutable(getExecutableReference(((LambdaExpression) referenceContext).binding)); + } else { + ref.setDeclaringExecutable(getExecutableReference(((AbstractMethodDeclaration) referenceContext).binding)); + } + return ref; + } else if (localVariableBinding.declaration.binding instanceof CatchParameterBinding) { + CtCatchVariableReference ref = this.jdtTreeBuilder.factory.Core().createCatchVariableReference(); + ref.setSimpleName(new String(varbin.name)); + CtTypeReference ref2 = getTypeReference(varbin.type); + ref.setType(ref2); + ref.setDeclaration((CtCatchVariable) this.jdtTreeBuilder.getCatchVariableDeclaration(ref.getSimpleName())); + return ref; + } else { + CtLocalVariableReference ref = this.jdtTreeBuilder.factory.Core().createLocalVariableReference(); + ref.setSimpleName(new String(varbin.name)); + CtTypeReference ref2 = getTypeReference(varbin.type); + ref.setType(ref2); + ref.setDeclaration((CtLocalVariable) this.jdtTreeBuilder.getLocalVariableDeclaration(ref.getSimpleName())); + return ref; + } + } else { + // unknown VariableBinding, the caller must do something + return null; + } + } + + public CtVariableReference getVariableReference(ProblemBinding binding) { + CtFieldReference ref = this.jdtTreeBuilder.factory.Core().createFieldReference(); + if (binding == null) { + return ref; + } + ref.setSimpleName(new String(binding.name)); + ref.setType((CtTypeReference) getTypeReference(binding.searchType)); + return ref; + } + + public List> getBoundedTypesReferences(TypeBinding[] genericTypeArguments) { + List> res = new ArrayList<>(genericTypeArguments.length); + for (TypeBinding tb : genericTypeArguments) { + res.add(getBoundedTypeReference(tb)); + } + return res; + } +} From 3def23655003dc884904a8a46a88080687ec3502 Mon Sep 17 00:00:00 2001 From: bdanglot Date: Thu, 7 Jul 2016 17:10:56 +0200 Subject: [PATCH 2/4] PositionBuilder done --- ...uilderContext.java => ContextBuilder.java} | 52 +--- .../compiler/jdt/HelperJDTTreeBuilder.java | 2 +- .../support/compiler/jdt/JDTTreeBuilder.java | 261 ++++++++--------- .../support/compiler/jdt/ParentExiter.java | 43 +-- .../support/compiler/jdt/PositionBuilder.java | 83 ++++++ .../compiler/jdt/ReferenceBuilder.java | 262 +++++++++++++----- .../spoon/test/position/PositionTest.java | 39 +++ .../test/position/testclasses/FooField.java | 6 + .../DefaultPrettyPrinterTest.java | 2 +- 9 files changed, 460 insertions(+), 290 deletions(-) rename src/main/java/spoon/support/compiler/jdt/{BuilderContext.java => ContextBuilder.java} (60%) create mode 100644 src/main/java/spoon/support/compiler/jdt/PositionBuilder.java diff --git a/src/main/java/spoon/support/compiler/jdt/BuilderContext.java b/src/main/java/spoon/support/compiler/jdt/ContextBuilder.java similarity index 60% rename from src/main/java/spoon/support/compiler/jdt/BuilderContext.java rename to src/main/java/spoon/support/compiler/jdt/ContextBuilder.java index 2a0099be665..f4cc3c657d9 100644 --- a/src/main/java/spoon/support/compiler/jdt/BuilderContext.java +++ b/src/main/java/spoon/support/compiler/jdt/ContextBuilder.java @@ -17,21 +17,14 @@ package spoon.support.compiler.jdt; import org.eclipse.jdt.internal.compiler.ast.ASTNode; -import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; -import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.Expression; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtStatement; -import spoon.reflect.code.CtStatementList; import spoon.reflect.code.CtTargetedExpression; import spoon.reflect.code.CtTry; -import spoon.reflect.cu.CompilationUnit; import spoon.reflect.declaration.CtElement; -import spoon.reflect.declaration.CtNamedElement; import spoon.reflect.declaration.CtTypedElement; -import spoon.reflect.factory.CoreFactory; import spoon.reflect.reference.CtTypeReference; import java.util.ArrayDeque; @@ -41,7 +34,7 @@ import static spoon.reflect.ModelElementContainerDefaultCapacities.CASTS_CONTAINER_DEFAULT_CAPACITY; -public class BuilderContext { +public class ContextBuilder { Deque annotationValueName = new ArrayDeque<>(); @@ -80,7 +73,7 @@ public class BuilderContext { private final JDTTreeBuilder jdtTreeBuilder; - BuilderContext(JDTTreeBuilder jdtTreeBuilder) { + ContextBuilder(JDTTreeBuilder jdtTreeBuilder) { this.jdtTreeBuilder = jdtTreeBuilder; } @@ -89,40 +82,9 @@ void enter(CtElement e, ASTNode node) { stack.push(new ASTPair(e, node)); // aststack.push(node); if (compilationunitdeclaration != null) { - CoreFactory cf = this.jdtTreeBuilder.factory.Core(); - int sourceStartDeclaration = node.sourceStart; - int sourceStartSource = node.sourceStart; - int sourceEnd = node.sourceEnd; - if (node instanceof AbstractVariableDeclaration) { - sourceStartDeclaration = ((AbstractVariableDeclaration) node).declarationSourceStart; - sourceEnd = ((AbstractVariableDeclaration) node).declarationSourceEnd; - } else if (node instanceof TypeDeclaration) { - sourceStartDeclaration = ((TypeDeclaration) node).declarationSourceStart; - sourceEnd = ((TypeDeclaration) node).declarationSourceEnd; - } else if ((e instanceof CtStatementList) && (node instanceof AbstractMethodDeclaration)) { - sourceStartDeclaration = ((AbstractMethodDeclaration) node).bodyStart - 1; - sourceEnd = ((AbstractMethodDeclaration) node).bodyEnd + 1; - } else if ((node instanceof AbstractMethodDeclaration)) { - if (((AbstractMethodDeclaration) node).bodyStart == 0) { - sourceStartDeclaration = -1; - sourceStartSource = -1; - sourceEnd = -1; - } else { - sourceStartDeclaration = ((AbstractMethodDeclaration) node).declarationSourceStart; - sourceEnd = ((AbstractMethodDeclaration) node).declarationSourceEnd; - } - } - if ((node instanceof Expression)) { - if (((Expression) node).statementEnd > 0) { - sourceEnd = ((Expression) node).statementEnd; - } - } - if (!(e instanceof CtNamedElement)) { - sourceStartSource = sourceStartDeclaration; - } - CompilationUnit cu = this.jdtTreeBuilder.factory.CompilationUnit().create(new String(compilationunitdeclaration.getFileName())); - e.setPosition(cf.createSourcePosition(cu, sourceStartDeclaration, sourceStartSource, sourceEnd, compilationunitdeclaration.compilationResult.lineSeparatorPositions)); + e.setPosition(this.jdtTreeBuilder.getPosition().buildPositionCtElement(e, node)); } + ASTPair pair = stack.peek(); CtElement current = pair.element; @@ -138,7 +100,7 @@ void enter(CtElement e, ASTNode node) { try { if (e instanceof CtTypedElement && node instanceof Expression) { if (((CtTypedElement) e).getType() == null) { - ((CtTypedElement) e).setType(this.jdtTreeBuilder.references.getTypeReference(((Expression) node).resolvedType)); + ((CtTypedElement) e).setType(this.jdtTreeBuilder.getReferences().getTypeReference(((Expression) node).resolvedType)); } } } catch (UnsupportedOperationException ignore) { @@ -154,8 +116,8 @@ void exit(ASTNode node) { } CtElement current = pair.element; if (!stack.isEmpty()) { - this.jdtTreeBuilder.exiter.child = current; - this.jdtTreeBuilder.exiter.scan(stack.peek().element); + this.jdtTreeBuilder.getExiter().setChild(current); + this.jdtTreeBuilder.getExiter().scan(stack.peek().element); } } diff --git a/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java index 0f633bbf178..9819328b9e0 100644 --- a/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java @@ -243,7 +243,7 @@ static boolean isPackage(char[][] packageName, TreeBuilderCompiler treeBuilderCo * @param typeName Type name. * @return qualified name of the expected type. */ - static String hasTypeInImports(String typeName, BuilderContext context) { + static String hasTypeInImports(String typeName, ContextBuilder context) { if (typeName == null) { return null; } else if (context.compilationunitdeclaration.imports == null) { diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index 1b465f73f94..163bdb95ee9 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -101,7 +101,6 @@ import org.eclipse.jdt.internal.compiler.ast.UnaryExpression; import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.ast.WhileStatement; -import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; @@ -119,7 +118,6 @@ import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; -import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; import spoon.reflect.code.BinaryOperatorKind; @@ -162,7 +160,6 @@ import spoon.reflect.code.CtVariableAccess; import spoon.reflect.code.CtWhile; import spoon.reflect.code.UnaryOperatorKind; -import spoon.reflect.cu.CompilationUnit; import spoon.reflect.declaration.CtAnnotatedElementType; import spoon.reflect.declaration.CtAnnotation; import spoon.reflect.declaration.CtAnonymousExecutable; @@ -199,64 +196,54 @@ */ public class JDTTreeBuilder extends ASTVisitor { - BuilderContext context = new BuilderContext(this); + private final PositionBuilder position; - ParentExiter exiter = new ParentExiter(this); + private final ContextBuilder context; - Factory factory; + private final ParentExiter exiter; - ReferenceBuilder references = new ReferenceBuilder(this); + private final ReferenceBuilder references; + + private final Factory factory; public boolean template = false; - private static final Logger LOGGER = Logger.getLogger(JDTTreeBuilder.class); + boolean skipTypeInAnnotation = false; boolean defaultValue; + private static final Logger LOGGER = Logger.getLogger(JDTTreeBuilder.class); + + public PositionBuilder getPosition() { + return position; + } + + public ContextBuilder getContext() { + return context; + } + + public ParentExiter getExiter() { + return exiter; + } + + public ReferenceBuilder getReferences() { + return references; + } + + public Factory getFactory() { + return factory; + } + public JDTTreeBuilder(Factory factory) { super(); this.factory = factory; + this.position = new PositionBuilder(this); + this.context = new ContextBuilder(this); + this.exiter = new ParentExiter(this); + this.references = new ReferenceBuilder(this); LOGGER.setLevel(factory.getEnvironment().getLevel()); } - /** - * Builds a type reference from a qualified name when a type specified in the name isn't available. - * - * @param tokens Qualified name. - * @param receiverType Last type in the qualified name. - * @param enclosingType Enclosing type of the type name. - * @param listener Listener to know if we must build the type reference. - * @return a type reference. - */ - private CtTypeReference getQualifiedTypeReference(char[][] tokens, TypeBinding receiverType, ReferenceBinding enclosingType, OnAccessListener listener) { - if (enclosingType != null && Collections.disjoint(Arrays.asList(ModifierKind.PUBLIC, ModifierKind.PROTECTED), HelperJDTTreeBuilder.getModifiers(enclosingType.modifiers))) { - String access = ""; - int i = 0; - for (; i < tokens.length; i++) { - final char[][] qualified = Arrays.copyOfRange(tokens, 0, i + 1); - if (!HelperJDTTreeBuilder.isPackage(qualified, ((TreeBuilderCompiler) context.compilationunitdeclaration.scope.environment.typeRequestor))) { - access = CharOperation.toString(qualified); - break; - } - } - if (!access.contains(CtPackage.PACKAGE_SEPARATOR)) { - access = HelperJDTTreeBuilder.hasTypeInImports(access, this.context); - } - final TypeBinding accessBinding = HelperJDTTreeBuilder.searchTypeBinding(access, ((TreeBuilderCompiler) context.compilationunitdeclaration.scope.environment.typeRequestor)); - if (accessBinding != null && listener.onAccess(tokens, i)) { - final TypeBinding superClassBinding = HelperJDTTreeBuilder.searchTypeBinding(accessBinding.superclass(), CharOperation.charToString(tokens[i + 1])); - if (superClassBinding != null) { - return references.getTypeReference(superClassBinding.clone(accessBinding)); - } else { - return references.getTypeReference(receiverType); - } - } else { - return references.getTypeReference(receiverType); - } - } - return null; - } - interface OnAccessListener { boolean onAccess(char[][] tokens, int index); } @@ -264,7 +251,7 @@ interface OnAccessListener { /** * Sets {@code declaring} as inner of {@code ref}, as either the package or the declaring type */ - /*private*/ void setPackageOrDeclaringType(CtTypeReference ref, CtReference declaring) { + void setPackageOrDeclaringType(CtTypeReference ref, CtReference declaring) { if (declaring instanceof CtPackageReference) { ref.setPackage((CtPackageReference) declaring); } else if (declaring instanceof CtTypeReference) { @@ -277,76 +264,6 @@ interface OnAccessListener { } } - private CtTypeReference buildTypeReferenceInternal(CtTypeReference typeReference, TypeReference type, Scope scope) { - if (type == null) { - return null; - } - CtTypeReference currentReference = typeReference; - - for (int position = type.getTypeName().length - 1; position >= 0; position--) { - if (currentReference == null) { - break; - } - context.enter(currentReference, type); - if (type.annotations != null && type.annotations.length - 1 <= position && type.annotations[position] != null && type.annotations[position].length > 0) { - for (Annotation annotation : type.annotations[position]) { - if (scope instanceof ClassScope) { - annotation.traverse(this, (ClassScope) scope); - } else if (scope instanceof BlockScope) { - annotation.traverse(this, (BlockScope) scope); - } else { - annotation.traverse(this, (BlockScope) null); - } - } - } - if (type.getTypeArguments() != null && type.getTypeArguments().length - 1 <= position && type.getTypeArguments()[position] != null && type.getTypeArguments()[position].length > 0) { - currentReference.getActualTypeArguments().clear(); - for (TypeReference typeArgument : type.getTypeArguments()[position]) { - if (typeArgument instanceof Wildcard || typeArgument.resolvedType instanceof WildcardBinding || typeArgument.resolvedType instanceof TypeVariableBinding) { - currentReference.addActualTypeArgument(buildTypeParameterReference(typeArgument, scope)); - } else { - currentReference.addActualTypeArgument(buildTypeReference(typeArgument, scope)); - } - } - } - if (type instanceof Wildcard && typeReference instanceof CtTypeParameterReference) { - ((CtTypeParameterReference) typeReference).setBoundingType(buildTypeReference(((Wildcard) type).bound, scope)); - } - context.exit(type); - currentReference = currentReference.getDeclaringType(); - } - return typeReference; - } - - /** - * Builds a type reference from a {@link TypeReference}. - * - * @param type Type from JDT. - * @param scope Scope of the parent element. - * @param Type of the type reference. - * @return a type reference. - */ - private CtTypeReference buildTypeReference(TypeReference type, Scope scope) { - if (type == null) { - return null; - } - return buildTypeReferenceInternal(references.getTypeReference(type.resolvedType, type), type, scope); - } - - /** - * Builds a type parameter reference from a {@link TypeReference} - * - * @param type Type from JDT. - * @param scope Scope of the parent element. - * @return a type parameter reference. - */ - private CtTypeParameterReference buildTypeParameterReference(TypeReference type, Scope scope) { - if (type == null) { - return null; - } - return (CtTypeParameterReference) this.buildTypeReferenceInternal(references.getTypeParameterReference(type.resolvedType, type), type, scope); - } - private void createExpression(StringLiteralConcatenation literal, BlockScope scope, List rst) { if (rst.isEmpty()) { return; @@ -382,7 +299,7 @@ CtType createType(TypeDeclaration typeDeclaration) { if (typeDeclaration.superInterfaces != null) { for (TypeReference ref : typeDeclaration.superInterfaces) { - final CtTypeReference superInterface = buildTypeReference(ref, null); + final CtTypeReference superInterface = this.references.buildTypeReference(ref, null); type.addSuperInterface(superInterface); } } @@ -405,7 +322,7 @@ CtType createType(TypeDeclaration typeDeclaration) { } } if (typeDeclaration.superclass != null) { - ((CtClass) type).setSuperclass(buildTypeReference(typeDeclaration.superclass, typeDeclaration.scope)); + ((CtClass) type).setSuperclass(this.references.buildTypeReference(typeDeclaration.superclass, typeDeclaration.scope)); } if (typeDeclaration.binding.isAnonymousType() || (typeDeclaration.binding instanceof LocalTypeBinding && typeDeclaration.binding.enclosingMethod() != null)) { type.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName(typeDeclaration.binding)); @@ -911,6 +828,8 @@ public void endVisit(WhileStatement whileStatement, BlockScope scope) { context.exit(whileStatement); } + + //TODO protected CtLocalVariable getLocalVariableDeclaration(final String name) { for (ASTPair astPair : context.stack) { // TODO check if the variable is visible from here @@ -1062,7 +981,7 @@ private > T buildCommonPartForCtNewClassAndC } } } - constructorCall.getExecutable().setType(buildTypeReference(allocationExpression.type, scope)); + constructorCall.getExecutable().setType(this.references.buildTypeReference(allocationExpression.type, scope)); context.isGenericTypeExplicit = true; } else if (allocationExpression.expectedType() != null) { constructorCall.getExecutable().setType(references.getTypeReference(allocationExpression.expectedType())); @@ -1070,7 +989,7 @@ private > T buildCommonPartForCtNewClassAndC if (allocationExpression.typeArguments != null) { for (TypeReference typeArgument : allocationExpression.typeArguments) { - constructorCall.addActualTypeArgument(buildTypeReference(typeArgument, scope)); + constructorCall.addActualTypeArgument(this.references.buildTypeReference(typeArgument, scope)); } } @@ -1104,7 +1023,7 @@ public boolean visit(AnnotationMethodDeclaration annotationTypeDeclaration, Clas f.setSimpleName(new String(annotationTypeDeclaration.selector)); context.enter(f, annotationTypeDeclaration); - f.setType(buildTypeReference(annotationTypeDeclaration.returnType, classScope)); + f.setType(this.references.buildTypeReference(annotationTypeDeclaration.returnType, classScope)); if (annotationTypeDeclaration.annotations != null) { for (Annotation a : annotationTypeDeclaration.annotations) { @@ -1142,7 +1061,7 @@ public boolean visit(Argument argument, BlockScope scope) { final TypeBinding receiverType = argument.type != null ? argument.type.resolvedType : null; if (receiverType != null && argument.type instanceof QualifiedTypeReference) { final QualifiedTypeReference qualifiedNameReference = (QualifiedTypeReference) argument.type; - final CtTypeReference ref = getQualifiedTypeReference(qualifiedNameReference.tokens, receiverType, receiverType.enclosingType(), new OnAccessListener() { + final CtTypeReference ref = this.references.getQualifiedTypeReference(qualifiedNameReference.tokens, receiverType, receiverType.enclosingType(), new OnAccessListener() { @Override public boolean onAccess(char[][] tokens, int index) { return true; @@ -1180,7 +1099,7 @@ public boolean visit(ArrayAllocationExpression arrayAllocationExpression, BlockS typeReference = references.getTypeReference(arrayAllocationExpression.type); } final CtArrayTypeReference arrayType = factory.Type().createArrayReference(typeReference, arrayAllocationExpression.dimensions.length); - arrayType.getArrayType().setAnnotations(buildTypeReference(arrayAllocationExpression.type, scope).getAnnotations()); + arrayType.getArrayType().setAnnotations(this.references.buildTypeReference(arrayAllocationExpression.type, scope).getAnnotations()); array.setType(arrayType); context.pushArgument(array); @@ -1231,7 +1150,7 @@ public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) { context.enter(typeAccess, arrayTypeReference); final CtArrayTypeReference arrayType = (CtArrayTypeReference) references.getTypeReference(arrayTypeReference.resolvedType); - arrayType.getArrayType().setAnnotations(buildTypeReference(arrayTypeReference, scope).getAnnotations()); + arrayType.getArrayType().setAnnotations(this.references.buildTypeReference(arrayTypeReference, scope).getAnnotations()); typeAccess.setAccessedType(arrayType); return true; @@ -1249,7 +1168,7 @@ public boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, Bl context.enter(typeAccess, arrayQualifiedTypeReference); final CtArrayTypeReference arrayType = (CtArrayTypeReference) references.getTypeReference(arrayQualifiedTypeReference.resolvedType); - arrayType.getArrayType().setAnnotations(buildTypeReference(arrayQualifiedTypeReference, scope).getAnnotations()); + arrayType.getArrayType().setAnnotations(this.references.buildTypeReference(arrayQualifiedTypeReference, scope).getAnnotations()); typeAccess.setAccessedType(arrayType); return true; @@ -1331,7 +1250,7 @@ public boolean visit(CaseStatement caseStatement, BlockScope scope) { @Override public boolean visit(CastExpression castExpression, BlockScope scope) { - context.casts.add(buildTypeReference(castExpression.type, scope)); + context.casts.add(this.references.buildTypeReference(castExpression.type, scope)); castExpression.expression.traverse(this, scope); return false; } @@ -1405,7 +1324,7 @@ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope s // Cast scope to BlockScope because some members values with potential // type annotations don't override traverse method with ClassScope. // Thanks JDT... - CtTypeReference throwType = buildTypeReference(r, (BlockScope) null); + CtTypeReference throwType = this.references.buildTypeReference(r, (BlockScope) null); c.addThrownType(throwType); } } @@ -1452,7 +1371,7 @@ public boolean visitTypeParameter(TypeParameter typeParameter, Scope scope) { typeParameterRef.setSimpleName(CharOperation.charToString(typeParameter.name)); // Extends of the generic type. - typeParameterRef.setBoundingType(buildTypeReference(typeParameter.type, (BlockScope) null)); + typeParameterRef.setBoundingType(this.references.buildTypeReference(typeParameter.type, (BlockScope) null)); // Annotations. if (typeParameter.annotations != null) { @@ -1470,7 +1389,7 @@ public boolean visitTypeParameter(TypeParameter typeParameter, Scope scope) { final Set> bounds = new TreeSet<>(); bounds.add(typeParameterRef.getBoundingType()); for (int i = 0; i < length; ++i) { - bounds.add(buildTypeReference(typeParameter.bounds[i], (BlockScope) null)); + bounds.add(this.references.buildTypeReference(typeParameter.bounds[i], (BlockScope) null)); } typeParameterRef.setBoundingType(factory.Type().createIntersectionTypeReferenceWithBounds(bounds)); } @@ -1570,7 +1489,7 @@ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { if (fieldDeclaration.type != null) { field = factory.Core().createField(); context.enter(field, fieldDeclaration); - field.setType(buildTypeReference(fieldDeclaration.type, scope)); + field.setType(this.references.buildTypeReference(fieldDeclaration.type, scope)); } else { field = factory.Core().createEnumValue(); context.enter(field, fieldDeclaration); @@ -1725,7 +1644,7 @@ public boolean visit(LabeledStatement labeledStatement, BlockScope scope) { public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { CtLocalVariable v = factory.Core().createLocalVariable(); v.setSimpleName(new String(localDeclaration.name)); - v.setType(buildTypeReference(localDeclaration.type, scope)); + v.setType(this.references.buildTypeReference(localDeclaration.type, scope)); v.setModifiers(HelperJDTTreeBuilder.getModifiers(localDeclaration.modifiers)); context.enter(v, localDeclaration); @@ -1919,7 +1838,7 @@ public boolean visit(MessageSend messageSend, BlockScope scope) { public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { CtMethod m = factory.Core().createMethod(); m.setSimpleName(new String(methodDeclaration.selector)); - m.setType(buildTypeReference(methodDeclaration.returnType, scope)); + m.setType(this.references.buildTypeReference(methodDeclaration.returnType, scope)); m.setModifiers(HelperJDTTreeBuilder.getModifiers(methodDeclaration.modifiers)); m.setDefaultMethod(methodDeclaration.isDefaultMethod()); @@ -1927,7 +1846,7 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { if (methodDeclaration.thrownExceptions != null) { for (TypeReference r : methodDeclaration.thrownExceptions) { - CtTypeReference throwType = buildTypeReference(r, scope); + CtTypeReference throwType = this.references.buildTypeReference(r, scope); m.addThrownType(throwType); } } @@ -2071,6 +1990,12 @@ public boolean visit(QualifiedAllocationExpression qualifiedAllocationExpression @Override public boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope scope) { long[] positions = qualifiedNameReference.sourcePositions; + + int sourceStart = qualifiedNameReference.sourceStart(); + int sourceEnd = qualifiedNameReference.sourceEnd(); + if (qualifiedNameReference.indexOfFirstFieldBinding < positions.length) { + sourceEnd = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding] >>> 32) - 2; + } if (qualifiedNameReference.binding instanceof FieldBinding) { CtFieldAccess fa; if (context.stack.peek().element instanceof CtAssignment @@ -2082,12 +2007,15 @@ public boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope s } CtFieldReference ref = references.getVariableReference(qualifiedNameReference.fieldBinding()); + + ref.setPosition(this.position.buildPosition(sourceStart, sourceEnd)); + // Only set the declaring type if we are in a static context. See // StaticAccessTest#testReferences test to have an example about that. if (ref.isStatic()) { final TypeBinding receiverType = qualifiedNameReference.actualReceiverType; if (receiverType != null) { - final CtTypeReference qualifiedRef = getQualifiedTypeReference(qualifiedNameReference.tokens, receiverType, qualifiedNameReference.fieldBinding().declaringClass.enclosingType(), new OnAccessListener() { + final CtTypeReference qualifiedRef = this.references.getQualifiedTypeReference(qualifiedNameReference.tokens, receiverType, qualifiedNameReference.fieldBinding().declaringClass.enclosingType(), new OnAccessListener() { @Override public boolean onAccess(char[][] tokens, int index) { return !CharOperation.equals(tokens[index + 1], tokens[tokens.length - 1]); @@ -2099,7 +2027,19 @@ public boolean onAccess(char[][] tokens, int index) { ref.setDeclaringType(references.getTypeReference(receiverType)); } } - fa.setTarget(factory.Code().createTypeAccess(ref.getDeclaringType())); + CtTypeAccess typeAccess = factory.Code().createTypeAccess(ref.getDeclaringType()); + + if (qualifiedNameReference.indexOfFirstFieldBinding > 1) { + // the array sourcePositions contains the position of each element of the qualifiedNameReference + // the last element contains the position of the field + sourceStart = qualifiedNameReference.sourceStart(); + sourceEnd = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding - 1] >>> 32) - 2; + typeAccess.setPosition(this.position.buildPosition(sourceStart, sourceEnd)); + } else { + typeAccess.setImplicit(true); + } + + fa.setTarget(typeAccess); } else if (!ref.isStatic() && !ref.getDeclaringType().isAnonymous()) { final CtTypeReference type = references.getTypeReference(qualifiedNameReference.actualReceiverType); final CtThisAccess thisAccess = factory.Code().createThisAccess(type); @@ -2113,15 +2053,22 @@ public boolean onAccess(char[][] tokens, int index) { && !((FieldBinding) qualifiedNameReference.binding).declaringClass.isAnonymousType() && qualifiedNameReference.tokens.length - 1 == ((FieldBinding) qualifiedNameReference.binding).declaringClass.compoundName.length && CharOperation.equals(CharOperation.subarray(qualifiedNameReference.tokens, 0, qualifiedNameReference.tokens.length - 1), ((FieldBinding) qualifiedNameReference.binding).declaringClass.compoundName)) { - // We get the binding information when we specify the complete fully qualified name of the delcaring class. + // We get the binding information when we specify the complete fully qualified name of the declaring class. final ReferenceBinding declaringClass = ((FieldBinding) qualifiedNameReference.binding).declaringClass; final CtTypeReference typeReference = references.getTypeReference(declaringClass); - fa.setTarget(factory.Code().createCodeSnippetExpression(typeReference.toString())); + final CtTypeAccess typeAccess = factory.Code().createTypeAccess(typeReference); + + sourceStart = qualifiedNameReference.sourceStart(); + sourceEnd = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding - 1] >>> 32) - 2; + typeAccess.setPosition(this.position.buildPosition(sourceStart, sourceEnd)); + + fa.setTarget(typeAccess); } if (qualifiedNameReference.otherBindings != null) { int i = 0; //positions index; - int sourceStart = (int) (positions[0] >>> 32); + fa.setPosition(ref.getPosition()); + sourceStart = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding - 1] >>> 32); for (FieldBinding b : qualifiedNameReference.otherBindings) { CtFieldAccess other; if (qualifiedNameReference.otherBindings.length == i + 1 && context.stack.peek().element instanceof CtAssignment && context.assigned) { @@ -2142,15 +2089,18 @@ public boolean onAccess(char[][] tokens, int index) { other.setType(ref2); } - //set source position of fa; - CompilationUnit cu = factory.CompilationUnit().create(new String(context.compilationunitdeclaration.getFileName())); - int sourceEnd = (int) (positions[i]); - final int[] lineSeparatorPositions = context.compilationunitdeclaration.compilationResult.lineSeparatorPositions; - fa.setPosition(factory.Core().createSourcePosition(cu, sourceStart, sourceStart, sourceEnd, lineSeparatorPositions)); + //set source position of fa + if (i + qualifiedNameReference.indexOfFirstFieldBinding >= qualifiedNameReference.otherBindings.length) { + sourceEnd = qualifiedNameReference.sourceEnd(); + } else { + sourceEnd = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding + i + 1] >>> 32) - 2; + } + other.setPosition(this.position.buildPosition(sourceStart, sourceEnd)); fa = other; i++; } } + fa.setPosition(this.position.buildPosition(qualifiedNameReference.sourceStart(), qualifiedNameReference.sourceEnd())); context.enter(fa, qualifiedNameReference); return true; } else if (qualifiedNameReference.binding instanceof VariableBinding) { @@ -2162,11 +2112,18 @@ public boolean onAccess(char[][] tokens, int index) { } else { va = factory.Core().createVariableRead(); } - va.setVariable(references.getVariableReference((VariableBinding) qualifiedNameReference.binding)); + + CtVariableReference varRef = references.getVariableReference((VariableBinding) qualifiedNameReference.binding); + varRef.setPosition(this.position.buildPosition(sourceStart, sourceEnd)); + + va.setVariable(varRef); va.setType(va.getVariable().getType() == null ? null : va.getVariable().getType().clone()); if (qualifiedNameReference.otherBindings != null) { int i = 0; //positions index; - int sourceStart = (int) (positions[0] >>> 32); + + va.setPosition(varRef.getPosition()); + sourceStart = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding - 1] >>> 32); + for (FieldBinding b : qualifiedNameReference.otherBindings) { CtFieldAccess other; if (qualifiedNameReference.otherBindings.length == i + 1 && context.stack.peek().element instanceof CtAssignment) { @@ -2185,14 +2142,17 @@ public boolean onAccess(char[][] tokens, int index) { other.setType(ref); } //set source position of va; - CompilationUnit cu = factory.CompilationUnit().create(new String(context.compilationunitdeclaration.getFileName())); - int sourceEnd = (int) (positions[i]); - final int[] lineSeparatorPositions = context.compilationunitdeclaration.compilationResult.lineSeparatorPositions; - va.setPosition(factory.Core().createSourcePosition(cu, sourceStart, sourceStart, sourceEnd, lineSeparatorPositions)); + if (i + qualifiedNameReference.indexOfFirstFieldBinding >= qualifiedNameReference.otherBindings.length) { + sourceEnd = qualifiedNameReference.sourceEnd(); + } else { + sourceEnd = (int) (positions[qualifiedNameReference.indexOfFirstFieldBinding + 1 + i] >>> 32) - 2; + } + other.setPosition(this.position.buildPosition(sourceStart, sourceEnd)); va = other; i++; } } + va.setPosition(this.position.buildPosition(qualifiedNameReference.sourceStart(), qualifiedNameReference.sourceEnd())); context.enter(va, qualifiedNameReference); return false; } else if (qualifiedNameReference.binding instanceof TypeBinding) { @@ -2260,7 +2220,6 @@ public boolean visit(ReturnStatement returnStatement, BlockScope scope) { return true; } - boolean skipTypeInAnnotation = false; @Override public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) { diff --git a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java index 713fa81180f..b34cbcff733 100644 --- a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java +++ b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java @@ -77,6 +77,8 @@ public class ParentExiter extends CtInheritanceScanner { private final JDTTreeBuilder jdtTreeBuilder; + private CtElement child; + /** * @param jdtTreeBuilder */ @@ -84,11 +86,13 @@ public class ParentExiter extends CtInheritanceScanner { this.jdtTreeBuilder = jdtTreeBuilder; } - CtElement child; + public void setChild(CtElement child) { + this.child = child; + } @Override public void scanCtElement(CtElement e) { - if (child instanceof CtAnnotation && this.jdtTreeBuilder.context.annotationValueName.isEmpty()) { + if (child instanceof CtAnnotation && this.jdtTreeBuilder.getContext().annotationValueName.isEmpty()) { e.addAnnotation((CtAnnotation) child); return; } @@ -108,7 +112,7 @@ public void scanCtExecutable(CtExecutable e) { @Override public void scanCtFormalTypeDeclarer(CtFormalTypeDeclarer e) { - if (this.jdtTreeBuilder.context.isTypeParameter && child instanceof CtTypeParameterReference) { + if (this.jdtTreeBuilder.getContext().isTypeParameter && child instanceof CtTypeParameterReference) { e.addFormalTypeParameter((CtTypeParameterReference) child); } return; @@ -124,7 +128,7 @@ public void scanCtLoop(CtLoop loop) { @Override public > void scanCtTargetedExpression(CtTargetedExpression targetedExpression) { - if (!this.jdtTreeBuilder.context.target.isEmpty() && this.jdtTreeBuilder.context.target.peek() == targetedExpression && child instanceof CtExpression) { + if (!this.jdtTreeBuilder.getContext().target.isEmpty() && this.jdtTreeBuilder.getContext().target.peek() == targetedExpression && child instanceof CtExpression) { targetedExpression.setTarget((E) child); return; } @@ -156,7 +160,7 @@ public void scanCtType(CtType type) { @Override public void scanCtVariable(CtVariable v) { - if (child instanceof CtExpression && !this.jdtTreeBuilder.context.arguments.isEmpty() && this.jdtTreeBuilder.context.arguments.peek() == v) { + if (child instanceof CtExpression && !this.jdtTreeBuilder.getContext().arguments.isEmpty() && this.jdtTreeBuilder.getContext().arguments.peek() == v) { v.setDefaultExpression((CtExpression) child); return; } @@ -166,7 +170,7 @@ public void scanCtVariable(CtVariable v) { @Override public void visitCtAnnotation(CtAnnotation annotation) { if (child instanceof CtExpression) { - annotation.addValue(this.jdtTreeBuilder.context.annotationValueName.peek(), child); + annotation.addValue(this.jdtTreeBuilder.getContext().annotationValueName.peek(), child); } super.visitCtAnnotation(annotation); } @@ -196,7 +200,7 @@ public void visitCtArrayWrite(CtArrayWrite arrayWrite) { private > boolean visitArrayAccess(CtArrayAccess arrayAccess) { if (child instanceof CtExpression) { - if (this.jdtTreeBuilder.context.arguments.size() > 0 && this.jdtTreeBuilder.context.arguments.peek() == arrayAccess) { + if (this.jdtTreeBuilder.getContext().arguments.size() > 0 && this.jdtTreeBuilder.getContext().arguments.peek() == arrayAccess) { arrayAccess.setIndexExpression((CtExpression) child); return false; } else if (arrayAccess.getTarget() == null) { @@ -210,7 +214,7 @@ private > boolean visitArrayAccess(CtArrayAccess void visitCtAssert(CtAssert asserted) { if (child instanceof CtExpression) { - if (!this.jdtTreeBuilder.context.arguments.isEmpty() && this.jdtTreeBuilder.context.arguments.peek() == asserted) { + if (!this.jdtTreeBuilder.getContext().arguments.isEmpty() && this.jdtTreeBuilder.getContext().arguments.peek() == asserted) { asserted.setExpression((CtExpression) child); return; } else { @@ -260,7 +264,7 @@ public void visitCtBlock(CtBlock block) { @Override public void visitCtCase(CtCase caseStatement) { - if (this.jdtTreeBuilder.context.selector && caseStatement.getCaseExpression() == null && child instanceof CtExpression) { + if (this.jdtTreeBuilder.getContext().selector && caseStatement.getCaseExpression() == null && child instanceof CtExpression) { caseStatement.setCaseExpression((CtExpression) child); return; } else if (child instanceof CtStatement) { @@ -331,15 +335,15 @@ public void visitCtField(CtField f) { @Override public void visitCtFor(CtFor forLoop) { - if (this.jdtTreeBuilder.context.forinit && child instanceof CtStatement) { + if (this.jdtTreeBuilder.getContext().forinit && child instanceof CtStatement) { forLoop.addForInit((CtStatement) child); return; } - if (!this.jdtTreeBuilder.context.forupdate && forLoop.getExpression() == null && child instanceof CtExpression) { + if (!this.jdtTreeBuilder.getContext().forupdate && forLoop.getExpression() == null && child instanceof CtExpression) { forLoop.setExpression((CtExpression) child); return; } - if (this.jdtTreeBuilder.context.forupdate && child instanceof CtStatement) { + if (this.jdtTreeBuilder.getContext().forupdate && child instanceof CtStatement) { forLoop.addForUpdate((CtStatement) child); return; } @@ -381,7 +385,7 @@ public void visitCtIf(CtIf ifElement) { @Override public void visitCtInvocation(CtInvocation invocation) { if (child instanceof CtExpression) { - if (this.jdtTreeBuilder.context.isArgument(invocation)) { + if (this.jdtTreeBuilder.getContext().isArgument(invocation)) { invocation.addArgument((CtExpression) child); return; } else { @@ -395,7 +399,7 @@ public void visitCtInvocation(CtInvocation invocation) { @Override public void visitCtNewArray(CtNewArray newArray) { if (child instanceof CtExpression) { - if (this.jdtTreeBuilder.context.isArgument(newArray)) { + if (this.jdtTreeBuilder.getContext().isArgument(newArray)) { newArray.addDimensionExpression((CtExpression) child); return; } else { @@ -407,7 +411,7 @@ public void visitCtNewArray(CtNewArray newArray) { @Override public void visitCtConstructorCall(CtConstructorCall ctConstructorCall) { - if (this.jdtTreeBuilder.context.isArgument(ctConstructorCall) && child instanceof CtExpression) { + if (this.jdtTreeBuilder.getContext().isArgument(ctConstructorCall) && child instanceof CtExpression) { ctConstructorCall.addArgument((CtExpression) child); return; } @@ -416,12 +420,12 @@ public void visitCtConstructorCall(CtConstructorCall ctConstructorCall) { @Override public void visitCtNewClass(CtNewClass newClass) { - if (this.jdtTreeBuilder.context.isArgument(newClass) && child instanceof CtExpression) { + if (this.jdtTreeBuilder.getContext().isArgument(newClass) && child instanceof CtExpression) { newClass.addArgument((CtExpression) child); return; } else if (child instanceof CtClass) { newClass.setAnonymousClass((CtClass) child); - final QualifiedAllocationExpression node = (QualifiedAllocationExpression) jdtTreeBuilder.context.stack.peek().node; + final QualifiedAllocationExpression node = (QualifiedAllocationExpression) jdtTreeBuilder.getContext().stack.peek().node; final ReferenceBinding[] referenceBindings = node.resolvedType == null ? null : node.resolvedType.superInterfaces(); if (referenceBindings != null && referenceBindings.length > 0) { ((CtClass) child).addSuperInterface(newClass.getType().clone()); @@ -517,7 +521,7 @@ public void visitCtThrow(CtThrow throwStatement) { @Override public void visitCtTry(CtTry tryBlock) { if (child instanceof CtBlock) { - if (!this.jdtTreeBuilder.context.finallyzer.isEmpty() && this.jdtTreeBuilder.context.finallyzer.peek() == tryBlock) { + if (!this.jdtTreeBuilder.getContext().finallyzer.isEmpty() && this.jdtTreeBuilder.getContext().finallyzer.peek() == tryBlock) { tryBlock.setFinalizer((CtBlock) child); } else { tryBlock.setBody((CtBlock) child); @@ -533,7 +537,7 @@ public void visitCtTry(CtTry tryBlock) { @Override public void visitCtTryWithResource(CtTryWithResource tryWithResource) { if (child instanceof CtBlock) { - if (!this.jdtTreeBuilder.context.finallyzer.isEmpty() && this.jdtTreeBuilder.context.finallyzer.peek() == tryWithResource) { + if (!this.jdtTreeBuilder.getContext().finallyzer.isEmpty() && this.jdtTreeBuilder.getContext().finallyzer.peek() == tryWithResource) { tryWithResource.setFinalizer((CtBlock) child); } else { tryWithResource.setBody((CtBlock) child); @@ -568,4 +572,5 @@ public void visitCtWhile(CtWhile whileLoop) { } super.visitCtWhile(whileLoop); } + } diff --git a/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java new file mode 100644 index 00000000000..80780d235ad --- /dev/null +++ b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2006-2016 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.compiler.jdt; + +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; +import spoon.reflect.code.CtStatementList; +import spoon.reflect.cu.CompilationUnit; +import spoon.reflect.cu.SourcePosition; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtNamedElement; +import spoon.reflect.factory.CoreFactory; + +/** + * Created by bdanglot on 07/07/16. + */ +public class PositionBuilder { + + private final JDTTreeBuilder jdtTreeBuilder; + + public PositionBuilder(JDTTreeBuilder jdtTreeBuilder) { + this.jdtTreeBuilder = jdtTreeBuilder; + } + + SourcePosition buildPosition(int sourceStart, int sourceEnd) { + CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().create(new String(this.jdtTreeBuilder.getContext().compilationunitdeclaration.getFileName())); + final int[] lineSeparatorPositions = this.jdtTreeBuilder.getContext().compilationunitdeclaration.compilationResult.lineSeparatorPositions; + return this.jdtTreeBuilder.getFactory().Core().createSourcePosition(cu, sourceStart, sourceStart, sourceEnd, lineSeparatorPositions); + } + + SourcePosition buildPositionCtElement(CtElement e, ASTNode node) { + CoreFactory cf = this.jdtTreeBuilder.getFactory().Core(); + int sourceStartDeclaration = node.sourceStart; + int sourceStartSource = node.sourceStart; + int sourceEnd = node.sourceEnd; + if (node instanceof AbstractVariableDeclaration) { + sourceStartDeclaration = ((AbstractVariableDeclaration) node).declarationSourceStart; + sourceEnd = ((AbstractVariableDeclaration) node).declarationSourceEnd; + } else if (node instanceof TypeDeclaration) { + sourceStartDeclaration = ((TypeDeclaration) node).declarationSourceStart; + sourceEnd = ((TypeDeclaration) node).declarationSourceEnd; + } else if ((e instanceof CtStatementList) && (node instanceof AbstractMethodDeclaration)) { + sourceStartDeclaration = ((AbstractMethodDeclaration) node).bodyStart - 1; + sourceEnd = ((AbstractMethodDeclaration) node).bodyEnd + 1; + } else if ((node instanceof AbstractMethodDeclaration)) { + if (((AbstractMethodDeclaration) node).bodyStart == 0) { + sourceStartDeclaration = -1; + sourceStartSource = -1; + sourceEnd = -1; + } else { + sourceStartDeclaration = ((AbstractMethodDeclaration) node).declarationSourceStart; + sourceEnd = ((AbstractMethodDeclaration) node).declarationSourceEnd; + } + } + if ((node instanceof Expression)) { + if (((Expression) node).statementEnd > 0) { + sourceEnd = ((Expression) node).statementEnd; + } + } + if (!(e instanceof CtNamedElement)) { + sourceStartSource = sourceStartDeclaration; + } + CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().create(new String(this.jdtTreeBuilder.getContext().compilationunitdeclaration.getFileName())); + return cf.createSourcePosition(cu, sourceStartDeclaration, sourceStartSource, sourceEnd, this.jdtTreeBuilder.getContext().compilationunitdeclaration.compilationResult.lineSeparatorPositions); + } +} diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java index b94163def58..b3af906b791 100644 --- a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; @@ -30,8 +31,10 @@ import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; +import org.eclipse.jdt.internal.compiler.lookup.BlockScope; import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding; import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.IntersectionTypeBinding18; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; @@ -47,6 +50,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; @@ -54,6 +58,8 @@ import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; import spoon.reflect.code.CtCatchVariable; import spoon.reflect.code.CtLocalVariable; +import spoon.reflect.declaration.CtPackage; +import spoon.reflect.declaration.ModifierKind; import spoon.reflect.internal.CtCircularTypeReference; import spoon.reflect.reference.CtArrayTypeReference; import spoon.reflect.reference.CtCatchVariableReference; @@ -69,6 +75,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -80,25 +87,134 @@ public class ReferenceBuilder { - Map> basestypes = new TreeMap<>(); + private Map> basestypes = new TreeMap<>(); - boolean bounds = false; + private boolean bounds = false; - boolean isImplicit = false; + private boolean isImplicit = false; private final JDTTreeBuilder jdtTreeBuilder; - public ReferenceBuilder(JDTTreeBuilder jdtTreeBuilder) { + ReferenceBuilder(JDTTreeBuilder jdtTreeBuilder) { this.jdtTreeBuilder = jdtTreeBuilder; } - public CtTypeReference getBoundedTypeReference(TypeBinding binding) { + private CtTypeReference getBoundedTypeReference(TypeBinding binding) { bounds = true; CtTypeReference ref = getTypeReference(binding); bounds = false; return ref; } + /** + * Builds a type reference from a {@link TypeReference}. + * + * @param type Type from JDT. + * @param scope Scope of the parent element. + * @param Type of the type reference. + * @return a type reference. + */ + CtTypeReference buildTypeReference(TypeReference type, Scope scope) { + if (type == null) { + return null; + } + return buildTypeReferenceInternal(this.getTypeReference(type.resolvedType, type), type, scope); + } + + /** + * Builds a type parameter reference from a {@link TypeReference} + * + * @param type Type from JDT. + * @param scope Scope of the parent element. + * @return a type parameter reference. + */ + private CtTypeParameterReference buildTypeParameterReference(TypeReference type, Scope scope) { + if (type == null) { + return null; + } + return (CtTypeParameterReference) this.buildTypeReferenceInternal(this.getTypeParameterReference(type.resolvedType, type), type, scope); + } + + + private CtTypeReference buildTypeReferenceInternal(CtTypeReference typeReference, TypeReference type, Scope scope) { + if (type == null) { + return null; + } + CtTypeReference currentReference = typeReference; + + for (int position = type.getTypeName().length - 1; position >= 0; position--) { + if (currentReference == null) { + break; + } + this.jdtTreeBuilder.getContext().enter(currentReference, type); + if (type.annotations != null && type.annotations.length - 1 <= position && type.annotations[position] != null && type.annotations[position].length > 0) { + for (Annotation annotation : type.annotations[position]) { + if (scope instanceof ClassScope) { + annotation.traverse(this.jdtTreeBuilder, (ClassScope) scope); + } else if (scope instanceof BlockScope) { + annotation.traverse(this.jdtTreeBuilder, (BlockScope) scope); + } else { + annotation.traverse(this.jdtTreeBuilder, (BlockScope) null); + } + } + } + if (type.getTypeArguments() != null && type.getTypeArguments().length - 1 <= position && type.getTypeArguments()[position] != null && type.getTypeArguments()[position].length > 0) { + currentReference.getActualTypeArguments().clear(); + for (TypeReference typeArgument : type.getTypeArguments()[position]) { + if (typeArgument instanceof Wildcard || typeArgument.resolvedType instanceof WildcardBinding || typeArgument.resolvedType instanceof TypeVariableBinding) { + currentReference.addActualTypeArgument(buildTypeParameterReference(typeArgument, scope)); + } else { + currentReference.addActualTypeArgument(buildTypeReference(typeArgument, scope)); + } + } + } + if (type instanceof Wildcard && typeReference instanceof CtTypeParameterReference) { + ((CtTypeParameterReference) typeReference).setBoundingType(buildTypeReference(((Wildcard) type).bound, scope)); + } + this.jdtTreeBuilder.getContext().exit(type); + currentReference = currentReference.getDeclaringType(); + } + return typeReference; + } + + /** + * Builds a type reference from a qualified name when a type specified in the name isn't available. + * + * @param tokens Qualified name. + * @param receiverType Last type in the qualified name. + * @param enclosingType Enclosing type of the type name. + * @param listener Listener to know if we must build the type reference. + * @return a type reference. + */ + CtTypeReference getQualifiedTypeReference(char[][] tokens, TypeBinding receiverType, ReferenceBinding enclosingType, JDTTreeBuilder.OnAccessListener listener) { + if (enclosingType != null && Collections.disjoint(Arrays.asList(ModifierKind.PUBLIC, ModifierKind.PROTECTED), HelperJDTTreeBuilder.getModifiers(enclosingType.modifiers))) { + String access = ""; + int i = 0; + for (; i < tokens.length; i++) { + final char[][] qualified = Arrays.copyOfRange(tokens, 0, i + 1); + if (!HelperJDTTreeBuilder.isPackage(qualified, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.typeRequestor))) { + access = CharOperation.toString(qualified); + break; + } + } + if (!access.contains(CtPackage.PACKAGE_SEPARATOR)) { + access = HelperJDTTreeBuilder.hasTypeInImports(access, this.jdtTreeBuilder.getContext()); + } + final TypeBinding accessBinding = HelperJDTTreeBuilder.searchTypeBinding(access, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.typeRequestor)); + if (accessBinding != null && listener.onAccess(tokens, i)) { + final TypeBinding superClassBinding = HelperJDTTreeBuilder.searchTypeBinding(accessBinding.superclass(), CharOperation.charToString(tokens[i + 1])); + if (superClassBinding != null) { + return this.getTypeReference(superClassBinding.clone(accessBinding)); + } else { + return this.getTypeReference(receiverType); + } + } else { + return this.getTypeReference(receiverType); + } + } + return null; + } + /** * Try to get the declaring reference (package or type) from imports of the current * compilation unit declaration (current class). This method returns a CtReference @@ -109,9 +225,9 @@ public CtTypeReference getBoundedTypeReference(TypeBinding binding) { * @param expectedName Name expected in imports. * @return CtReference which can be a CtTypeReference, a CtPackageReference or null. */ - public CtReference getDeclaringReferenceFromImports(char[] expectedName) { - if (this.jdtTreeBuilder.context.compilationunitdeclaration != null && this.jdtTreeBuilder.context.compilationunitdeclaration.imports != null) { - for (ImportReference anImport : this.jdtTreeBuilder.context.compilationunitdeclaration.imports) { + CtReference getDeclaringReferenceFromImports(char[] expectedName) { + if (this.jdtTreeBuilder.getContext().compilationunitdeclaration != null && this.jdtTreeBuilder.getContext().compilationunitdeclaration.imports != null) { + for (ImportReference anImport : this.jdtTreeBuilder.getContext().compilationunitdeclaration.imports) { if (CharOperation.equals(anImport.getImportName()[anImport.getImportName().length - 1], expectedName)) { if (anImport.isStatic()) { int indexDeclaring = 2; @@ -123,27 +239,27 @@ public CtReference getDeclaringReferenceFromImports(char[] expectedName) { char[][] className = CharOperation.subarray(anImport.getImportName(), anImport.getImportName().length - indexDeclaring, anImport.getImportName().length - (indexDeclaring - 1)); PackageBinding aPackage; if (packageName.length != 0) { - aPackage = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment.createPackage(packageName); + aPackage = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.createPackage(packageName); } else { aPackage = null; } - final MissingTypeBinding declaringType = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment.createMissingType(aPackage, className); - this.jdtTreeBuilder.context.ignoreComputeImports = true; + final MissingTypeBinding declaringType = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.createMissingType(aPackage, className); + this.jdtTreeBuilder.getContext().ignoreComputeImports = true; final CtTypeReference typeReference = getTypeReference(declaringType); - this.jdtTreeBuilder.context.ignoreComputeImports = false; + this.jdtTreeBuilder.getContext().ignoreComputeImports = false; return typeReference; } else { char[][] chars = CharOperation.subarray(anImport.getImportName(), 0, anImport.getImportName().length - 1); - Binding someBinding = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.findImport(chars, false, false); + Binding someBinding = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.findImport(chars, false, false); PackageBinding packageBinding; if (someBinding != null && someBinding.isValidBinding() && someBinding instanceof PackageBinding) { packageBinding = (PackageBinding) someBinding; } else { - packageBinding = this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment.createPackage(chars); + packageBinding = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.createPackage(chars); if (packageBinding == null) { // Big crisis here. We are already in noclasspath mode but JDT doesn't support always // creation of a package in this mode. So, if we are in this brace, we make the job of JDT... - packageBinding = new PackageBinding(chars, null, this.jdtTreeBuilder.context.compilationunitdeclaration.scope.environment); + packageBinding = new PackageBinding(chars, null, this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment); } } return getPackageReference(packageBinding); @@ -155,12 +271,12 @@ public CtReference getDeclaringReferenceFromImports(char[] expectedName) { } @SuppressWarnings("unchecked") - public CtExecutableReference getExecutableReference(MethodBinding exec) { + CtExecutableReference getExecutableReference(MethodBinding exec) { if (exec == null) { return null; } - final CtExecutableReference ref = this.jdtTreeBuilder.factory.Core().createExecutableReference(); + final CtExecutableReference ref = this.jdtTreeBuilder.getFactory().Core().createExecutableReference(); ref.setSimpleName(new String(exec.selector)); ref.setType(getTypeReference(exec.returnType)); @@ -206,19 +322,19 @@ public CtExecutableReference getExecutableReference(MethodBinding exec) { return ref; } - public CtPackageReference getPackageReference(PackageBinding reference) { + private CtPackageReference getPackageReference(PackageBinding reference) { String name = new String(reference.shortReadableName()); if (name.length() == 0) { - return this.jdtTreeBuilder.factory.Package().topLevel(); + return this.jdtTreeBuilder.getFactory().Package().topLevel(); } - CtPackageReference ref = this.jdtTreeBuilder.factory.Core().createPackageReference(); + CtPackageReference ref = this.jdtTreeBuilder.getFactory().Core().createPackageReference(); ref.setSimpleName(name); return ref; } final Map bindingCache = new HashMap<>(); - public CtTypeReference getTypeReference(TypeBinding binding, TypeReference ref) { + CtTypeReference getTypeReference(TypeBinding binding, TypeReference ref) { CtTypeReference ctRef = getTypeReference(binding); if (ctRef != null && isCorrectTypeReference(ref)) { insertGenericTypesInNoClasspathFromJDTInSpoon(ref, ctRef); @@ -227,11 +343,11 @@ public CtTypeReference getTypeReference(TypeBinding binding, TypeReferenc return getTypeReference(ref); } - public CtTypeReference getTypeParameterReference(TypeBinding binding, TypeReference ref) { + CtTypeReference getTypeParameterReference(TypeBinding binding, TypeReference ref) { CtTypeReference ctRef = getTypeReference(binding); if (ctRef != null && isCorrectTypeReference(ref)) { if (!(ctRef instanceof CtTypeParameterReference)) { - CtTypeParameterReference typeParameterRef = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + CtTypeParameterReference typeParameterRef = this.jdtTreeBuilder.getFactory().Core().createTypeParameterReference(); typeParameterRef.setSimpleName(ctRef.getSimpleName()); typeParameterRef.setDeclaringType(ctRef.getDeclaringType()); typeParameterRef.setPackage(ctRef.getPackage()); @@ -280,7 +396,7 @@ private void insertGenericTypesInNoClasspathFromJDTInSpoon(TypeReference ori * Returns a complete Spoon AST when the name is correct, otherwise a spoon type * reference with a name that correspond to the name of the JDT type reference. */ - public CtTypeReference getTypeReference(TypeReference ref) { + CtTypeReference getTypeReference(TypeReference ref) { CtTypeReference res = null; CtTypeReference inner = null; final String[] namesParameterized = CharOperation.charArrayToStringArray(ref.getParameterizedTypeName()); @@ -299,11 +415,11 @@ public CtTypeReference getTypeReference(TypeReference ref) { inner = main; } if (res == null) { - return this.jdtTreeBuilder.factory.Type().createReference(CharOperation.toString(ref.getParameterizedTypeName())); + return this.jdtTreeBuilder.getFactory().Type().createReference(CharOperation.toString(ref.getParameterizedTypeName())); } CtPackageReference packageReference = index >= 0 - ? this.jdtTreeBuilder.factory.Package().getOrCreate(concatSubArray(namesParameterized, index)).getReference() - : this.jdtTreeBuilder.factory.Package().topLevel(); + ? this.jdtTreeBuilder.getFactory().Package().getOrCreate(concatSubArray(namesParameterized, index)).getReference() + : this.jdtTreeBuilder.getFactory().Package().topLevel(); inner.setPackage(packageReference); return res; } @@ -321,15 +437,15 @@ private String concatSubArray(String[] a, int endIndex) { * Try to build a CtTypeReference from a simple name with specified generic types but * returns null if the name doesn't correspond to a type (not start by an upper case). */ - public CtTypeReference getTypeReference(String name) { + private CtTypeReference getTypeReference(String name) { CtTypeReference main = null; if (name.matches(".*(<.+>)")) { Pattern pattern = Pattern.compile("([^<]+)<(.+)>"); Matcher m = pattern.matcher(name); if (name.startsWith("?")) { - main = (CtTypeReference) this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + main = (CtTypeReference) this.jdtTreeBuilder.getFactory().Core().createTypeParameterReference(); } else { - main = this.jdtTreeBuilder.factory.Core().createTypeReference(); + main = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); } if (m.find()) { main.setSimpleName(m.group(1)); @@ -339,10 +455,10 @@ public CtTypeReference getTypeReference(String name) { } } } else if (Character.isUpperCase(name.charAt(0))) { - main = this.jdtTreeBuilder.factory.Core().createTypeReference(); + main = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); main.setSimpleName(name); } else if (name.startsWith("?")) { - return (CtTypeReference) this.jdtTreeBuilder.factory.Type().createTypeParameterReference(name); + return (CtTypeReference) this.jdtTreeBuilder.getFactory().Type().createTypeParameterReference(name); } return main; } @@ -351,8 +467,8 @@ public CtTypeReference getTypeReference(String name) { * Try to build a CtTypeParameterReference from a single name with specified generic types but * keep in mind that if you give wrong data in the strong, reference will be wrong. */ - public CtTypeParameterReference getTypeParameterReference(String name) { - CtTypeParameterReference param = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); + private CtTypeParameterReference getTypeParameterReference(String name) { + CtTypeParameterReference param = this.jdtTreeBuilder.getFactory().Core().createTypeParameterReference(); if (name.contains("extends") || name.contains("super")) { String[] split = name.contains("extends") ? name.split("extends") : name.split("super"); param.setSimpleName(split[0].trim()); @@ -374,7 +490,7 @@ public CtTypeParameterReference getTypeParameterReference(String name) { } @SuppressWarnings("unchecked") - public CtTypeReference getTypeReference(TypeBinding binding) { + CtTypeReference getTypeReference(TypeBinding binding) { if (binding == null) { return null; } @@ -390,8 +506,8 @@ public CtTypeReference getTypeReference(TypeBinding binding) { // and hide the real class in actualType(). ref = getTypeReference(binding.actualType()); } else { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { ref.setSimpleName(""); } else { @@ -406,7 +522,7 @@ public CtTypeReference getTypeReference(TypeBinding binding) { if (((ParameterizedTypeBinding) binding).arguments != null) { for (TypeBinding b : ((ParameterizedTypeBinding) binding).arguments) { - if (!this.jdtTreeBuilder.context.isGenericTypeExplicit) { + if (!this.jdtTreeBuilder.getContext().isGenericTypeExplicit) { isImplicit = true; } if (bindingCache.containsKey(b)) { @@ -418,10 +534,10 @@ public CtTypeReference getTypeReference(TypeBinding binding) { } } } else if (binding instanceof MissingTypeBinding) { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setSimpleName(new String(binding.sourceName())); ref.setPackage(getPackageReference(binding.getPackage())); - if (!this.jdtTreeBuilder.context.ignoreComputeImports) { + if (!this.jdtTreeBuilder.getContext().ignoreComputeImports) { final CtReference declaring = this.getDeclaringReferenceFromImports(binding.sourceName()); if (declaring instanceof CtPackageReference) { ref.setPackage((CtPackageReference) declaring); @@ -430,8 +546,8 @@ public CtTypeReference getTypeReference(TypeBinding binding) { } } } else if (binding instanceof BinaryTypeBinding) { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); if (binding.enclosingType() != null) { ref.setDeclaringType(getTypeReference(binding.enclosingType())); } else { @@ -440,8 +556,8 @@ public CtTypeReference getTypeReference(TypeBinding binding) { ref.setSimpleName(new String(binding.sourceName())); } else if (binding instanceof TypeVariableBinding) { boolean oldBounds = bounds; - ref = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeParameterReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); if (binding instanceof CaptureBinding) { ref.setSimpleName("?"); bounds = true; @@ -470,21 +586,21 @@ public CtTypeReference getTypeReference(TypeBinding binding) { for (ReferenceBinding superInterface : b.superInterfaces) { bounds.add(getTypeReference(superInterface)); } - ((CtTypeParameterReference) ref).setBoundingType(this.jdtTreeBuilder.factory.Type().createIntersectionTypeReferenceWithBounds(bounds)); + ((CtTypeParameterReference) ref).setBoundingType(this.jdtTreeBuilder.getFactory().Type().createIntersectionTypeReferenceWithBounds(bounds)); } if (binding instanceof CaptureBinding) { bounds = false; } } else if (binding instanceof BaseTypeBinding) { String name = new String(binding.sourceName()); - if (!this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped) { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + if (!this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped) { + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setImplicit(true); ref.setSimpleName(name); } else { ref = basestypes.get(name); if (ref == null) { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setSimpleName(name); basestypes.put(name, ref); } else { @@ -492,8 +608,8 @@ public CtTypeReference getTypeReference(TypeBinding binding) { } } } else if (binding instanceof WildcardBinding) { - ref = this.jdtTreeBuilder.factory.Core().createTypeParameterReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeParameterReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); ref.setSimpleName("?"); if (((WildcardBinding) binding).boundKind == Wildcard.SUPER && ref instanceof CtTypeParameterReference) { ((CtTypeParameterReference) ref).setUpper(false); @@ -508,8 +624,8 @@ public CtTypeReference getTypeReference(TypeBinding binding) { } } } else if (binding instanceof LocalTypeBinding) { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); ref.setDeclaringType(getTypeReference((binding.enclosingType()))); @@ -523,8 +639,8 @@ public CtTypeReference getTypeReference(TypeBinding binding) { } } } else if (binding instanceof SourceTypeBinding) { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); ref.setDeclaringType(getTypeReference((binding.enclosingType()))); @@ -545,24 +661,24 @@ public CtTypeReference getTypeReference(TypeBinding binding) { } } else if (binding instanceof ArrayBinding) { CtArrayTypeReference arrayref; - arrayref = this.jdtTreeBuilder.factory.Core().createArrayTypeReference(); - arrayref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + arrayref = this.jdtTreeBuilder.getFactory().Core().createArrayTypeReference(); + arrayref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); ref = arrayref; for (int i = 1; i < binding.dimensions(); i++) { - CtArrayTypeReference tmp = this.jdtTreeBuilder.factory.Core().createArrayTypeReference(); + CtArrayTypeReference tmp = this.jdtTreeBuilder.getFactory().Core().createArrayTypeReference(); arrayref.setComponentType(tmp); arrayref = tmp; } arrayref.setComponentType(getTypeReference(binding.leafComponentType())); } else if (binding instanceof ProblemReferenceBinding || binding instanceof PolyTypeBinding) { // Spoon is able to analyze also without the classpath - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.context.isLambdaParameterImplicitlyTyped); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); ref.setSimpleName(new String(binding.readableName())); final CtReference declaring = this.getDeclaringReferenceFromImports(binding.sourceName()); this.jdtTreeBuilder.setPackageOrDeclaringType(ref, declaring); } else if (binding instanceof JDTTreeBuilder.SpoonReferenceBinding) { - ref = this.jdtTreeBuilder.factory.Core().createTypeReference(); + ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setSimpleName(new String(binding.sourceName())); ref.setDeclaringType(getTypeReference(binding.enclosingType())); } else if (binding instanceof IntersectionTypeBinding18) { @@ -570,7 +686,7 @@ public CtTypeReference getTypeReference(TypeBinding binding) { for (ReferenceBinding superInterface : binding.getIntersectingTypes()) { bounds.add(getTypeReference(superInterface)); } - ref = this.jdtTreeBuilder.factory.Type().createIntersectionTypeReferenceWithBounds(bounds); + ref = this.jdtTreeBuilder.getFactory().Type().createIntersectionTypeReferenceWithBounds(bounds); } else { throw new RuntimeException("Unknown TypeBinding: " + binding.getClass() + " " + binding); } @@ -579,7 +695,7 @@ public CtTypeReference getTypeReference(TypeBinding binding) { } private CtCircularTypeReference getCtCircularTypeReference(TypeBinding b) { - final CtCircularTypeReference circularRef = this.jdtTreeBuilder.factory.Internal().createCircularTypeReference(); + final CtCircularTypeReference circularRef = this.jdtTreeBuilder.getFactory().Internal().createCircularTypeReference(); final CtTypeReference originalRef = bindingCache.get(b).clone(); circularRef.setPackage(originalRef.getPackage()); circularRef.setSimpleName(originalRef.getSimpleName()); @@ -590,8 +706,8 @@ private CtCircularTypeReference getCtCircularTypeReference(TypeBinding b) { } @SuppressWarnings("unchecked") - public CtVariableReference getVariableReference(MethodBinding methbin) { - CtFieldReference ref = this.jdtTreeBuilder.factory.Core().createFieldReference(); + CtVariableReference getVariableReference(MethodBinding methbin) { + CtFieldReference ref = this.jdtTreeBuilder.getFactory().Core().createFieldReference(); ref.setSimpleName(new String(methbin.selector)); ref.setType((CtTypeReference) getTypeReference(methbin.returnType)); @@ -604,8 +720,8 @@ public CtVariableReference getVariableReference(MethodBinding methbin) { } @SuppressWarnings("unchecked") - public CtFieldReference getVariableReference(FieldBinding varbin) { - CtFieldReference ref = this.jdtTreeBuilder.factory.Core().createFieldReference(); + CtFieldReference getVariableReference(FieldBinding varbin) { + CtFieldReference ref = this.jdtTreeBuilder.getFactory().Core().createFieldReference(); if (varbin == null) { return ref; } @@ -623,14 +739,14 @@ public CtFieldReference getVariableReference(FieldBinding varbin) { } @SuppressWarnings("unchecked") - public CtVariableReference getVariableReference(VariableBinding varbin) { + CtVariableReference getVariableReference(VariableBinding varbin) { if (varbin instanceof FieldBinding) { return getVariableReference((FieldBinding) varbin); } else if (varbin instanceof LocalVariableBinding) { final LocalVariableBinding localVariableBinding = (LocalVariableBinding) varbin; if (localVariableBinding.declaration instanceof Argument && localVariableBinding.declaringScope instanceof MethodScope) { - CtParameterReference ref = this.jdtTreeBuilder.factory.Core().createParameterReference(); + CtParameterReference ref = this.jdtTreeBuilder.getFactory().Core().createParameterReference(); ref.setSimpleName(new String(varbin.name)); ref.setType((CtTypeReference) getTypeReference(varbin.type)); final ReferenceContext referenceContext = localVariableBinding.declaringScope.referenceContext(); @@ -641,14 +757,14 @@ public CtVariableReference getVariableReference(VariableBinding varbin) { } return ref; } else if (localVariableBinding.declaration.binding instanceof CatchParameterBinding) { - CtCatchVariableReference ref = this.jdtTreeBuilder.factory.Core().createCatchVariableReference(); + CtCatchVariableReference ref = this.jdtTreeBuilder.getFactory().Core().createCatchVariableReference(); ref.setSimpleName(new String(varbin.name)); CtTypeReference ref2 = getTypeReference(varbin.type); ref.setType(ref2); ref.setDeclaration((CtCatchVariable) this.jdtTreeBuilder.getCatchVariableDeclaration(ref.getSimpleName())); return ref; } else { - CtLocalVariableReference ref = this.jdtTreeBuilder.factory.Core().createLocalVariableReference(); + CtLocalVariableReference ref = this.jdtTreeBuilder.getFactory().Core().createLocalVariableReference(); ref.setSimpleName(new String(varbin.name)); CtTypeReference ref2 = getTypeReference(varbin.type); ref.setType(ref2); @@ -661,8 +777,8 @@ public CtVariableReference getVariableReference(VariableBinding varbin) { } } - public CtVariableReference getVariableReference(ProblemBinding binding) { - CtFieldReference ref = this.jdtTreeBuilder.factory.Core().createFieldReference(); + CtVariableReference getVariableReference(ProblemBinding binding) { + CtFieldReference ref = this.jdtTreeBuilder.getFactory().Core().createFieldReference(); if (binding == null) { return ref; } @@ -671,7 +787,7 @@ public CtVariableReference getVariableReference(ProblemBinding binding) { return ref; } - public List> getBoundedTypesReferences(TypeBinding[] genericTypeArguments) { + List> getBoundedTypesReferences(TypeBinding[] genericTypeArguments) { List> res = new ArrayList<>(genericTypeArguments.length); for (TypeBinding tb : genericTypeArguments) { res.add(getBoundedTypeReference(tb)); diff --git a/src/test/java/spoon/test/position/PositionTest.java b/src/test/java/spoon/test/position/PositionTest.java index b3d88d7470e..ee9a5191e48 100644 --- a/src/test/java/spoon/test/position/PositionTest.java +++ b/src/test/java/spoon/test/position/PositionTest.java @@ -1,9 +1,16 @@ package spoon.test.position; import org.junit.Test; +import spoon.reflect.code.CtAssignment; import spoon.reflect.code.CtBlock; +import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtFieldAccess; import spoon.reflect.code.CtIf; +import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtThisAccess; import spoon.reflect.cu.SourcePosition; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtField; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; import spoon.reflect.factory.Factory; @@ -70,6 +77,38 @@ public void testPositionField() throws Exception { assertEquals("int field2 =\n" + "\t\t\t0;", contentAtPosition(classContent, position2)); + + + CtAssignment m = foo.getMethod("m").getBody().getStatement(0); + CtFieldAccess assigned = (CtFieldAccess) m.getAssigned(); + SourcePosition position3 = assigned.getPosition(); + assertEquals(13, position3.getLine()); + assertEquals(13, position3.getEndLine()); + + assertEquals(168, position3.getSourceStart()); + assertEquals(184, position3.getSourceEnd()); + + assertEquals("FooField.f.field2", contentAtPosition(classContent, position3)); + + CtFieldAccess target = (CtFieldAccess) assigned.getTarget(); + SourcePosition position4 = target.getPosition(); + assertEquals(13, position4.getLine()); + assertEquals(13, position4.getEndLine()); + + assertEquals(168, position4.getSourceStart()); + assertEquals(177, position4.getSourceEnd()); + + assertEquals("FooField.f", contentAtPosition(classContent, position4)); + + CtExpression typeAccess = target.getTarget(); + SourcePosition position5 = typeAccess.getPosition(); + assertEquals(13, position5.getLine()); + assertEquals(13, position5.getEndLine()); + + assertEquals(168, position5.getSourceStart()); + assertEquals(175, position5.getSourceEnd()); + + assertEquals("FooField", contentAtPosition(classContent, position5)); } @Test diff --git a/src/test/java/spoon/test/position/testclasses/FooField.java b/src/test/java/spoon/test/position/testclasses/FooField.java index 9cc0eeb96af..fff751d1771 100644 --- a/src/test/java/spoon/test/position/testclasses/FooField.java +++ b/src/test/java/spoon/test/position/testclasses/FooField.java @@ -6,4 +6,10 @@ public class FooField { int field2 = 0; + + static FooField f = null; + + public void m() { + FooField.f.field2 = 0; + } } \ No newline at end of file diff --git a/src/test/java/spoon/test/prettyprinter/DefaultPrettyPrinterTest.java b/src/test/java/spoon/test/prettyprinter/DefaultPrettyPrinterTest.java index 62dad65cbbe..87310a797ae 100644 --- a/src/test/java/spoon/test/prettyprinter/DefaultPrettyPrinterTest.java +++ b/src/test/java/spoon/test/prettyprinter/DefaultPrettyPrinterTest.java @@ -181,7 +181,7 @@ public void autoImportUsesFullyQualifiedNameWhenImportedNameAlreadyPresent() thr expected = "public void setFieldOfClassWithSameNameAsTheCompilationUnitClass() {" +nl+ - " spoon.test.prettyprinter.testclasses.sub.TypeIdentifierCollision.globalField = localField;" +nl+ + " TypeIdentifierCollision.globalField = localField;" +nl+ "}" ; computed = aClass.getMethodsByName("setFieldOfClassWithSameNameAsTheCompilationUnitClass").get(0).toString(); From f73bd068a89d430e54a45e40e9cb8329ca945d6b Mon Sep 17 00:00:00 2001 From: bdanglot Date: Fri, 8 Jul 2016 15:44:12 +0200 Subject: [PATCH 3/4] move getter declaration to ContextBuilder --- .../support/compiler/jdt/ContextBuilder.java | 60 ++++++++++++++- .../compiler/jdt/HelperJDTTreeBuilder.java | 4 +- .../support/compiler/jdt/JDTTreeBuilder.java | 73 +++---------------- .../support/compiler/jdt/ParentExiter.java | 36 ++++----- .../support/compiler/jdt/PositionBuilder.java | 8 +- .../compiler/jdt/ReferenceBuilder.java | 54 +++++++------- 6 files changed, 121 insertions(+), 114 deletions(-) diff --git a/src/main/java/spoon/support/compiler/jdt/ContextBuilder.java b/src/main/java/spoon/support/compiler/jdt/ContextBuilder.java index f4cc3c657d9..1a6810b3b16 100644 --- a/src/main/java/spoon/support/compiler/jdt/ContextBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ContextBuilder.java @@ -19,13 +19,16 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.Expression; +import spoon.reflect.code.CtCatchVariable; import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtLocalVariable; import spoon.reflect.code.CtStatement; import spoon.reflect.code.CtTargetedExpression; import spoon.reflect.code.CtTry; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtTypedElement; import spoon.reflect.reference.CtTypeReference; +import spoon.reflect.visitor.EarlyTerminatingScanner; import java.util.ArrayDeque; import java.util.ArrayList; @@ -82,7 +85,7 @@ void enter(CtElement e, ASTNode node) { stack.push(new ASTPair(e, node)); // aststack.push(node); if (compilationunitdeclaration != null) { - e.setPosition(this.jdtTreeBuilder.getPosition().buildPositionCtElement(e, node)); + e.setPosition(this.jdtTreeBuilder.getPositionBuilder().buildPositionCtElement(e, node)); } ASTPair pair = stack.peek(); @@ -100,7 +103,7 @@ void enter(CtElement e, ASTNode node) { try { if (e instanceof CtTypedElement && node instanceof Expression) { if (((CtTypedElement) e).getType() == null) { - ((CtTypedElement) e).setType(this.jdtTreeBuilder.getReferences().getTypeReference(((Expression) node).resolvedType)); + ((CtTypedElement) e).setType(this.jdtTreeBuilder.getReferencesBuilder().getTypeReference(((Expression) node).resolvedType)); } } } catch (UnsupportedOperationException ignore) { @@ -121,6 +124,59 @@ void exit(ASTNode node) { } } + CtLocalVariable getLocalVariableDeclaration(final String name) { + for (ASTPair astPair : this.stack) { + // TODO check if the variable is visible from here + + EarlyTerminatingScanner> scanner = new EarlyTerminatingScanner>() { + @Override + public void visitCtLocalVariable(CtLocalVariable localVariable) { + if (name.equals(localVariable.getSimpleName())) { + setResult(localVariable); + terminate(); + return; + } + super.visitCtLocalVariable(localVariable); + } + }; + astPair.element.accept(scanner); + CtLocalVariable var = (CtLocalVariable) scanner.getResult(); + if (var != null) { + return var; + } + } + // note: this happens when using the new try(vardelc) structure + this.jdtTreeBuilder.getLogger().error("could not find declaration for local variable " + name + " at " + this.stack.peek().element.getPosition()); + + return null; + } + + CtCatchVariable getCatchVariableDeclaration(final String name) { + for (ASTPair astPair : this.stack) { + EarlyTerminatingScanner> scanner = new EarlyTerminatingScanner>() { + @Override + public void visitCtCatchVariable(CtCatchVariable catchVariable) { + if (name.equals(catchVariable.getSimpleName())) { + setResult(catchVariable); + terminate(); + return; + } + super.visitCtCatchVariable(catchVariable); + } + }; + astPair.element.accept(scanner); + + CtCatchVariable var = (CtCatchVariable) scanner.getResult(); + if (var != null) { + return null; + } + } + // note: this happens when using the new try(vardelc) structure + this.jdtTreeBuilder.getLogger().error("could not find declaration for catch variable " + name + " at " + this.stack.peek().element.getPosition()); + + return null; + } + boolean isArgument(CtElement e) { return arguments.size() > 0 && arguments.peek() == e; } diff --git a/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java index 9819328b9e0..8e2205f5de0 100644 --- a/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java @@ -39,7 +39,7 @@ import java.util.EnumSet; import java.util.Set; -public class HelperJDTTreeBuilder { +class HelperJDTTreeBuilder { static UnaryOperatorKind getUnaryOperator(int op) { switch (op) { @@ -263,7 +263,7 @@ static String hasTypeInImports(String typeName, ContextBuilder context) { * * @param a An annotation. * @param elementType Type of the annotation. - * @return true if the annotation is compitble with the given element type. + * @return true if the annotation is compatible with the given element type. */ private static boolean hasAnnotationWithType(Annotation a, CtAnnotatedElementType elementType) { if (a.resolvedType == null) { diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index 163bdb95ee9..da0111cf24e 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -181,7 +181,6 @@ import spoon.reflect.reference.CtTypeParameterReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.reference.CtVariableReference; -import spoon.reflect.visitor.EarlyTerminatingScanner; import spoon.support.reflect.reference.CtUnboundVariableReferenceImpl; import java.util.ArrayList; @@ -212,22 +211,26 @@ public class JDTTreeBuilder extends ASTVisitor { boolean defaultValue; + public static Logger getLogger() { + return LOGGER; + } + private static final Logger LOGGER = Logger.getLogger(JDTTreeBuilder.class); - public PositionBuilder getPosition() { + public PositionBuilder getPositionBuilder() { return position; } - public ContextBuilder getContext() { + public ContextBuilder getContextBuilder() { return context; } - public ParentExiter getExiter() { - return exiter; + public ReferenceBuilder getReferencesBuilder() { + return references; } - public ReferenceBuilder getReferences() { - return references; + public ParentExiter getExiter() { + return exiter; } public Factory getFactory() { @@ -241,7 +244,7 @@ public JDTTreeBuilder(Factory factory) { this.context = new ContextBuilder(this); this.exiter = new ParentExiter(this); this.references = new ReferenceBuilder(this); - LOGGER.setLevel(factory.getEnvironment().getLevel()); + this.LOGGER.setLevel(factory.getEnvironment().getLevel()); } interface OnAccessListener { @@ -829,59 +832,7 @@ public void endVisit(WhileStatement whileStatement, BlockScope scope) { } - //TODO - protected CtLocalVariable getLocalVariableDeclaration(final String name) { - for (ASTPair astPair : context.stack) { - // TODO check if the variable is visible from here - - EarlyTerminatingScanner> scanner = new EarlyTerminatingScanner>() { - @Override - public void visitCtLocalVariable(CtLocalVariable localVariable) { - if (name.equals(localVariable.getSimpleName())) { - setResult(localVariable); - terminate(); - return; - } - super.visitCtLocalVariable(localVariable); - } - }; - astPair.element.accept(scanner); - CtLocalVariable var = (CtLocalVariable) scanner.getResult(); - if (var != null) { - return var; - } - } - // note: this happens when using the new try(vardelc) structure - LOGGER.error("could not find declaration for local variable " + name + " at " + context.stack.peek().element.getPosition()); - - return null; - } - - protected CtCatchVariable getCatchVariableDeclaration(final String name) { - for (ASTPair astPair : context.stack) { - EarlyTerminatingScanner> scanner = new EarlyTerminatingScanner>() { - @Override - public void visitCtCatchVariable(CtCatchVariable catchVariable) { - if (name.equals(catchVariable.getSimpleName())) { - setResult(catchVariable); - terminate(); - return; - } - super.visitCtCatchVariable(catchVariable); - } - }; - astPair.element.accept(scanner); - - CtCatchVariable var = (CtCatchVariable) scanner.getResult(); - if (var != null) { - return null; - } - } - // note: this happens when using the new try(vardelc) structure - LOGGER.error("could not find declaration for catch variable " + name + " at " + context.stack.peek().element.getPosition()); - return null; - } @Override public boolean visit(ReferenceExpression referenceExpression, BlockScope blockScope) { @@ -2304,7 +2255,7 @@ public boolean visit(SingleNameReference singleNameReference, BlockScope scope) } CtLocalVariableReference ref = factory.Core().createLocalVariableReference(); ref.setSimpleName(new String(singleNameReference.token)); - ref.setDeclaration((CtLocalVariable) getLocalVariableDeclaration(ref.getSimpleName())); + ref.setDeclaration((CtLocalVariable) this.context.getLocalVariableDeclaration(ref.getSimpleName())); va.setVariable(ref); } if (va != null) { diff --git a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java index b34cbcff733..eaa285d45a3 100644 --- a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java +++ b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java @@ -92,7 +92,7 @@ public void setChild(CtElement child) { @Override public void scanCtElement(CtElement e) { - if (child instanceof CtAnnotation && this.jdtTreeBuilder.getContext().annotationValueName.isEmpty()) { + if (child instanceof CtAnnotation && this.jdtTreeBuilder.getContextBuilder().annotationValueName.isEmpty()) { e.addAnnotation((CtAnnotation) child); return; } @@ -112,7 +112,7 @@ public void scanCtExecutable(CtExecutable e) { @Override public void scanCtFormalTypeDeclarer(CtFormalTypeDeclarer e) { - if (this.jdtTreeBuilder.getContext().isTypeParameter && child instanceof CtTypeParameterReference) { + if (this.jdtTreeBuilder.getContextBuilder().isTypeParameter && child instanceof CtTypeParameterReference) { e.addFormalTypeParameter((CtTypeParameterReference) child); } return; @@ -128,7 +128,7 @@ public void scanCtLoop(CtLoop loop) { @Override public > void scanCtTargetedExpression(CtTargetedExpression targetedExpression) { - if (!this.jdtTreeBuilder.getContext().target.isEmpty() && this.jdtTreeBuilder.getContext().target.peek() == targetedExpression && child instanceof CtExpression) { + if (!this.jdtTreeBuilder.getContextBuilder().target.isEmpty() && this.jdtTreeBuilder.getContextBuilder().target.peek() == targetedExpression && child instanceof CtExpression) { targetedExpression.setTarget((E) child); return; } @@ -160,7 +160,7 @@ public void scanCtType(CtType type) { @Override public void scanCtVariable(CtVariable v) { - if (child instanceof CtExpression && !this.jdtTreeBuilder.getContext().arguments.isEmpty() && this.jdtTreeBuilder.getContext().arguments.peek() == v) { + if (child instanceof CtExpression && !this.jdtTreeBuilder.getContextBuilder().arguments.isEmpty() && this.jdtTreeBuilder.getContextBuilder().arguments.peek() == v) { v.setDefaultExpression((CtExpression) child); return; } @@ -170,7 +170,7 @@ public void scanCtVariable(CtVariable v) { @Override public void visitCtAnnotation(CtAnnotation annotation) { if (child instanceof CtExpression) { - annotation.addValue(this.jdtTreeBuilder.getContext().annotationValueName.peek(), child); + annotation.addValue(this.jdtTreeBuilder.getContextBuilder().annotationValueName.peek(), child); } super.visitCtAnnotation(annotation); } @@ -200,7 +200,7 @@ public void visitCtArrayWrite(CtArrayWrite arrayWrite) { private > boolean visitArrayAccess(CtArrayAccess arrayAccess) { if (child instanceof CtExpression) { - if (this.jdtTreeBuilder.getContext().arguments.size() > 0 && this.jdtTreeBuilder.getContext().arguments.peek() == arrayAccess) { + if (this.jdtTreeBuilder.getContextBuilder().arguments.size() > 0 && this.jdtTreeBuilder.getContextBuilder().arguments.peek() == arrayAccess) { arrayAccess.setIndexExpression((CtExpression) child); return false; } else if (arrayAccess.getTarget() == null) { @@ -214,7 +214,7 @@ private > boolean visitArrayAccess(CtArrayAccess void visitCtAssert(CtAssert asserted) { if (child instanceof CtExpression) { - if (!this.jdtTreeBuilder.getContext().arguments.isEmpty() && this.jdtTreeBuilder.getContext().arguments.peek() == asserted) { + if (!this.jdtTreeBuilder.getContextBuilder().arguments.isEmpty() && this.jdtTreeBuilder.getContextBuilder().arguments.peek() == asserted) { asserted.setExpression((CtExpression) child); return; } else { @@ -264,7 +264,7 @@ public void visitCtBlock(CtBlock block) { @Override public void visitCtCase(CtCase caseStatement) { - if (this.jdtTreeBuilder.getContext().selector && caseStatement.getCaseExpression() == null && child instanceof CtExpression) { + if (this.jdtTreeBuilder.getContextBuilder().selector && caseStatement.getCaseExpression() == null && child instanceof CtExpression) { caseStatement.setCaseExpression((CtExpression) child); return; } else if (child instanceof CtStatement) { @@ -335,15 +335,15 @@ public void visitCtField(CtField f) { @Override public void visitCtFor(CtFor forLoop) { - if (this.jdtTreeBuilder.getContext().forinit && child instanceof CtStatement) { + if (this.jdtTreeBuilder.getContextBuilder().forinit && child instanceof CtStatement) { forLoop.addForInit((CtStatement) child); return; } - if (!this.jdtTreeBuilder.getContext().forupdate && forLoop.getExpression() == null && child instanceof CtExpression) { + if (!this.jdtTreeBuilder.getContextBuilder().forupdate && forLoop.getExpression() == null && child instanceof CtExpression) { forLoop.setExpression((CtExpression) child); return; } - if (this.jdtTreeBuilder.getContext().forupdate && child instanceof CtStatement) { + if (this.jdtTreeBuilder.getContextBuilder().forupdate && child instanceof CtStatement) { forLoop.addForUpdate((CtStatement) child); return; } @@ -385,7 +385,7 @@ public void visitCtIf(CtIf ifElement) { @Override public void visitCtInvocation(CtInvocation invocation) { if (child instanceof CtExpression) { - if (this.jdtTreeBuilder.getContext().isArgument(invocation)) { + if (this.jdtTreeBuilder.getContextBuilder().isArgument(invocation)) { invocation.addArgument((CtExpression) child); return; } else { @@ -399,7 +399,7 @@ public void visitCtInvocation(CtInvocation invocation) { @Override public void visitCtNewArray(CtNewArray newArray) { if (child instanceof CtExpression) { - if (this.jdtTreeBuilder.getContext().isArgument(newArray)) { + if (this.jdtTreeBuilder.getContextBuilder().isArgument(newArray)) { newArray.addDimensionExpression((CtExpression) child); return; } else { @@ -411,7 +411,7 @@ public void visitCtNewArray(CtNewArray newArray) { @Override public void visitCtConstructorCall(CtConstructorCall ctConstructorCall) { - if (this.jdtTreeBuilder.getContext().isArgument(ctConstructorCall) && child instanceof CtExpression) { + if (this.jdtTreeBuilder.getContextBuilder().isArgument(ctConstructorCall) && child instanceof CtExpression) { ctConstructorCall.addArgument((CtExpression) child); return; } @@ -420,12 +420,12 @@ public void visitCtConstructorCall(CtConstructorCall ctConstructorCall) { @Override public void visitCtNewClass(CtNewClass newClass) { - if (this.jdtTreeBuilder.getContext().isArgument(newClass) && child instanceof CtExpression) { + if (this.jdtTreeBuilder.getContextBuilder().isArgument(newClass) && child instanceof CtExpression) { newClass.addArgument((CtExpression) child); return; } else if (child instanceof CtClass) { newClass.setAnonymousClass((CtClass) child); - final QualifiedAllocationExpression node = (QualifiedAllocationExpression) jdtTreeBuilder.getContext().stack.peek().node; + final QualifiedAllocationExpression node = (QualifiedAllocationExpression) jdtTreeBuilder.getContextBuilder().stack.peek().node; final ReferenceBinding[] referenceBindings = node.resolvedType == null ? null : node.resolvedType.superInterfaces(); if (referenceBindings != null && referenceBindings.length > 0) { ((CtClass) child).addSuperInterface(newClass.getType().clone()); @@ -521,7 +521,7 @@ public void visitCtThrow(CtThrow throwStatement) { @Override public void visitCtTry(CtTry tryBlock) { if (child instanceof CtBlock) { - if (!this.jdtTreeBuilder.getContext().finallyzer.isEmpty() && this.jdtTreeBuilder.getContext().finallyzer.peek() == tryBlock) { + if (!this.jdtTreeBuilder.getContextBuilder().finallyzer.isEmpty() && this.jdtTreeBuilder.getContextBuilder().finallyzer.peek() == tryBlock) { tryBlock.setFinalizer((CtBlock) child); } else { tryBlock.setBody((CtBlock) child); @@ -537,7 +537,7 @@ public void visitCtTry(CtTry tryBlock) { @Override public void visitCtTryWithResource(CtTryWithResource tryWithResource) { if (child instanceof CtBlock) { - if (!this.jdtTreeBuilder.getContext().finallyzer.isEmpty() && this.jdtTreeBuilder.getContext().finallyzer.peek() == tryWithResource) { + if (!this.jdtTreeBuilder.getContextBuilder().finallyzer.isEmpty() && this.jdtTreeBuilder.getContextBuilder().finallyzer.peek() == tryWithResource) { tryWithResource.setFinalizer((CtBlock) child); } else { tryWithResource.setBody((CtBlock) child); diff --git a/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java index 80780d235ad..b8df29d99d3 100644 --- a/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java @@ -40,8 +40,8 @@ public PositionBuilder(JDTTreeBuilder jdtTreeBuilder) { } SourcePosition buildPosition(int sourceStart, int sourceEnd) { - CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().create(new String(this.jdtTreeBuilder.getContext().compilationunitdeclaration.getFileName())); - final int[] lineSeparatorPositions = this.jdtTreeBuilder.getContext().compilationunitdeclaration.compilationResult.lineSeparatorPositions; + CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().create(new String(this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.getFileName())); + final int[] lineSeparatorPositions = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.compilationResult.lineSeparatorPositions; return this.jdtTreeBuilder.getFactory().Core().createSourcePosition(cu, sourceStart, sourceStart, sourceEnd, lineSeparatorPositions); } @@ -77,7 +77,7 @@ SourcePosition buildPositionCtElement(CtElement e, ASTNode node) { if (!(e instanceof CtNamedElement)) { sourceStartSource = sourceStartDeclaration; } - CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().create(new String(this.jdtTreeBuilder.getContext().compilationunitdeclaration.getFileName())); - return cf.createSourcePosition(cu, sourceStartDeclaration, sourceStartSource, sourceEnd, this.jdtTreeBuilder.getContext().compilationunitdeclaration.compilationResult.lineSeparatorPositions); + CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().create(new String(this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.getFileName())); + return cf.createSourcePosition(cu, sourceStartDeclaration, sourceStartSource, sourceEnd, this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.compilationResult.lineSeparatorPositions); } } diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java index b3af906b791..0568c04a7da 100644 --- a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -146,7 +146,7 @@ private CtTypeReference buildTypeReferenceInternal(CtTypeReference typ if (currentReference == null) { break; } - this.jdtTreeBuilder.getContext().enter(currentReference, type); + this.jdtTreeBuilder.getContextBuilder().enter(currentReference, type); if (type.annotations != null && type.annotations.length - 1 <= position && type.annotations[position] != null && type.annotations[position].length > 0) { for (Annotation annotation : type.annotations[position]) { if (scope instanceof ClassScope) { @@ -171,7 +171,7 @@ private CtTypeReference buildTypeReferenceInternal(CtTypeReference typ if (type instanceof Wildcard && typeReference instanceof CtTypeParameterReference) { ((CtTypeParameterReference) typeReference).setBoundingType(buildTypeReference(((Wildcard) type).bound, scope)); } - this.jdtTreeBuilder.getContext().exit(type); + this.jdtTreeBuilder.getContextBuilder().exit(type); currentReference = currentReference.getDeclaringType(); } return typeReference; @@ -192,15 +192,15 @@ CtTypeReference getQualifiedTypeReference(char[][] tokens, TypeBinding re int i = 0; for (; i < tokens.length; i++) { final char[][] qualified = Arrays.copyOfRange(tokens, 0, i + 1); - if (!HelperJDTTreeBuilder.isPackage(qualified, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.typeRequestor))) { + if (!HelperJDTTreeBuilder.isPackage(qualified, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.typeRequestor))) { access = CharOperation.toString(qualified); break; } } if (!access.contains(CtPackage.PACKAGE_SEPARATOR)) { - access = HelperJDTTreeBuilder.hasTypeInImports(access, this.jdtTreeBuilder.getContext()); + access = HelperJDTTreeBuilder.hasTypeInImports(access, this.jdtTreeBuilder.getContextBuilder()); } - final TypeBinding accessBinding = HelperJDTTreeBuilder.searchTypeBinding(access, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.typeRequestor)); + final TypeBinding accessBinding = HelperJDTTreeBuilder.searchTypeBinding(access, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.typeRequestor)); if (accessBinding != null && listener.onAccess(tokens, i)) { final TypeBinding superClassBinding = HelperJDTTreeBuilder.searchTypeBinding(accessBinding.superclass(), CharOperation.charToString(tokens[i + 1])); if (superClassBinding != null) { @@ -226,8 +226,8 @@ CtTypeReference getQualifiedTypeReference(char[][] tokens, TypeBinding re * @return CtReference which can be a CtTypeReference, a CtPackageReference or null. */ CtReference getDeclaringReferenceFromImports(char[] expectedName) { - if (this.jdtTreeBuilder.getContext().compilationunitdeclaration != null && this.jdtTreeBuilder.getContext().compilationunitdeclaration.imports != null) { - for (ImportReference anImport : this.jdtTreeBuilder.getContext().compilationunitdeclaration.imports) { + if (this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration != null && this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.imports != null) { + for (ImportReference anImport : this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.imports) { if (CharOperation.equals(anImport.getImportName()[anImport.getImportName().length - 1], expectedName)) { if (anImport.isStatic()) { int indexDeclaring = 2; @@ -239,27 +239,27 @@ CtReference getDeclaringReferenceFromImports(char[] expectedName) { char[][] className = CharOperation.subarray(anImport.getImportName(), anImport.getImportName().length - indexDeclaring, anImport.getImportName().length - (indexDeclaring - 1)); PackageBinding aPackage; if (packageName.length != 0) { - aPackage = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.createPackage(packageName); + aPackage = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.createPackage(packageName); } else { aPackage = null; } - final MissingTypeBinding declaringType = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.createMissingType(aPackage, className); - this.jdtTreeBuilder.getContext().ignoreComputeImports = true; + final MissingTypeBinding declaringType = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.createMissingType(aPackage, className); + this.jdtTreeBuilder.getContextBuilder().ignoreComputeImports = true; final CtTypeReference typeReference = getTypeReference(declaringType); - this.jdtTreeBuilder.getContext().ignoreComputeImports = false; + this.jdtTreeBuilder.getContextBuilder().ignoreComputeImports = false; return typeReference; } else { char[][] chars = CharOperation.subarray(anImport.getImportName(), 0, anImport.getImportName().length - 1); - Binding someBinding = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.findImport(chars, false, false); + Binding someBinding = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.findImport(chars, false, false); PackageBinding packageBinding; if (someBinding != null && someBinding.isValidBinding() && someBinding instanceof PackageBinding) { packageBinding = (PackageBinding) someBinding; } else { - packageBinding = this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment.createPackage(chars); + packageBinding = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.createPackage(chars); if (packageBinding == null) { // Big crisis here. We are already in noclasspath mode but JDT doesn't support always // creation of a package in this mode. So, if we are in this brace, we make the job of JDT... - packageBinding = new PackageBinding(chars, null, this.jdtTreeBuilder.getContext().compilationunitdeclaration.scope.environment); + packageBinding = new PackageBinding(chars, null, this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment); } } return getPackageReference(packageBinding); @@ -507,7 +507,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { ref = getTypeReference(binding.actualType()); } else { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { ref.setSimpleName(""); } else { @@ -522,7 +522,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { if (((ParameterizedTypeBinding) binding).arguments != null) { for (TypeBinding b : ((ParameterizedTypeBinding) binding).arguments) { - if (!this.jdtTreeBuilder.getContext().isGenericTypeExplicit) { + if (!this.jdtTreeBuilder.getContextBuilder().isGenericTypeExplicit) { isImplicit = true; } if (bindingCache.containsKey(b)) { @@ -537,7 +537,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setSimpleName(new String(binding.sourceName())); ref.setPackage(getPackageReference(binding.getPackage())); - if (!this.jdtTreeBuilder.getContext().ignoreComputeImports) { + if (!this.jdtTreeBuilder.getContextBuilder().ignoreComputeImports) { final CtReference declaring = this.getDeclaringReferenceFromImports(binding.sourceName()); if (declaring instanceof CtPackageReference) { ref.setPackage((CtPackageReference) declaring); @@ -547,7 +547,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } } else if (binding instanceof BinaryTypeBinding) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); if (binding.enclosingType() != null) { ref.setDeclaringType(getTypeReference(binding.enclosingType())); } else { @@ -557,7 +557,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } else if (binding instanceof TypeVariableBinding) { boolean oldBounds = bounds; ref = this.jdtTreeBuilder.getFactory().Core().createTypeParameterReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); if (binding instanceof CaptureBinding) { ref.setSimpleName("?"); bounds = true; @@ -593,7 +593,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } } else if (binding instanceof BaseTypeBinding) { String name = new String(binding.sourceName()); - if (!this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped) { + if (!this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setImplicit(true); ref.setSimpleName(name); @@ -609,7 +609,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } } else if (binding instanceof WildcardBinding) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeParameterReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); ref.setSimpleName("?"); if (((WildcardBinding) binding).boundKind == Wildcard.SUPER && ref instanceof CtTypeParameterReference) { ((CtTypeParameterReference) ref).setUpper(false); @@ -625,7 +625,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } } else if (binding instanceof LocalTypeBinding) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); ref.setDeclaringType(getTypeReference((binding.enclosingType()))); @@ -640,7 +640,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } } else if (binding instanceof SourceTypeBinding) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); ref.setDeclaringType(getTypeReference((binding.enclosingType()))); @@ -662,7 +662,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } else if (binding instanceof ArrayBinding) { CtArrayTypeReference arrayref; arrayref = this.jdtTreeBuilder.getFactory().Core().createArrayTypeReference(); - arrayref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + arrayref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); ref = arrayref; for (int i = 1; i < binding.dimensions(); i++) { CtArrayTypeReference tmp = this.jdtTreeBuilder.getFactory().Core().createArrayTypeReference(); @@ -673,7 +673,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { } else if (binding instanceof ProblemReferenceBinding || binding instanceof PolyTypeBinding) { // Spoon is able to analyze also without the classpath ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); - ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContext().isLambdaParameterImplicitlyTyped); + ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); ref.setSimpleName(new String(binding.readableName())); final CtReference declaring = this.getDeclaringReferenceFromImports(binding.sourceName()); this.jdtTreeBuilder.setPackageOrDeclaringType(ref, declaring); @@ -761,14 +761,14 @@ CtVariableReference getVariableReference(VariableBinding varbin) { ref.setSimpleName(new String(varbin.name)); CtTypeReference ref2 = getTypeReference(varbin.type); ref.setType(ref2); - ref.setDeclaration((CtCatchVariable) this.jdtTreeBuilder.getCatchVariableDeclaration(ref.getSimpleName())); + ref.setDeclaration((CtCatchVariable) this.jdtTreeBuilder.getContextBuilder().getCatchVariableDeclaration(ref.getSimpleName())); return ref; } else { CtLocalVariableReference ref = this.jdtTreeBuilder.getFactory().Core().createLocalVariableReference(); ref.setSimpleName(new String(varbin.name)); CtTypeReference ref2 = getTypeReference(varbin.type); ref.setType(ref2); - ref.setDeclaration((CtLocalVariable) this.jdtTreeBuilder.getLocalVariableDeclaration(ref.getSimpleName())); + ref.setDeclaration((CtLocalVariable) this.jdtTreeBuilder.getContextBuilder().getLocalVariableDeclaration(ref.getSimpleName())); return ref; } } else { From 007142218e4e6112913949217d77eb062cab8969 Mon Sep 17 00:00:00 2001 From: bdanglot Date: Thu, 21 Jul 2016 13:57:57 +0200 Subject: [PATCH 4/4] rename JDTTreeBuilderHelper --- .../support/compiler/jdt/JDTTreeBuilder.java | 42 +++++++++---------- ...Builder.java => JDTTreeBuilderHelper.java} | 4 +- .../compiler/jdt/ReferenceBuilder.java | 16 +++---- 3 files changed, 31 insertions(+), 31 deletions(-) rename src/main/java/spoon/support/compiler/jdt/{HelperJDTTreeBuilder.java => JDTTreeBuilderHelper.java} (99%) diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index da0111cf24e..4efcb6e693c 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -319,7 +319,7 @@ CtType createType(TypeDeclaration typeDeclaration) { if ((resolvedType instanceof MemberTypeBinding || resolvedType instanceof BinaryTypeBinding) && resolvedType.enclosingType() != null && typeDeclaration.enclosingType.superclass != null - && Collections.disjoint(modifiers, HelperJDTTreeBuilder.getModifiers(resolvedType.enclosingType().modifiers))) { + && Collections.disjoint(modifiers, JDTTreeBuilderHelper.getModifiers(resolvedType.enclosingType().modifiers))) { typeDeclaration.superclass.resolvedType = new SpoonReferenceBinding(typeDeclaration.superclass.resolvedType.sourceName(), (ReferenceBinding) typeDeclaration.enclosingType.superclass.resolvedType); } @@ -328,7 +328,7 @@ CtType createType(TypeDeclaration typeDeclaration) { ((CtClass) type).setSuperclass(this.references.buildTypeReference(typeDeclaration.superclass, typeDeclaration.scope)); } if (typeDeclaration.binding.isAnonymousType() || (typeDeclaration.binding instanceof LocalTypeBinding && typeDeclaration.binding.enclosingMethod() != null)) { - type.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName(typeDeclaration.binding)); + type.setSimpleName(JDTTreeBuilderHelper.computeAnonymousName(typeDeclaration.binding)); } else { type.setSimpleName(new String(typeDeclaration.name)); } @@ -337,7 +337,7 @@ CtType createType(TypeDeclaration typeDeclaration) { } // Setting modifiers - type.setModifiers(HelperJDTTreeBuilder.getModifiers(typeDeclaration.modifiers)); + type.setModifiers(JDTTreeBuilderHelper.getModifiers(typeDeclaration.modifiers)); return type; } @@ -963,7 +963,7 @@ private > T buildCommonPartForCtNewClassAndC @Override public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((and_and_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(JDTTreeBuilderHelper.getBinaryOperatorKind((and_and_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, and_and_Expression); return true; // do nothing by default, keep traversing } @@ -979,7 +979,7 @@ public boolean visit(AnnotationMethodDeclaration annotationTypeDeclaration, Clas if (annotationTypeDeclaration.annotations != null) { for (Annotation a : annotationTypeDeclaration.annotations) { a.traverse(this, annotationTypeDeclaration.scope); - HelperJDTTreeBuilder.substituteAnnotation(f, a, CtAnnotatedElementType.TYPE_USE); + JDTTreeBuilderHelper.substituteAnnotation(f, a, CtAnnotatedElementType.TYPE_USE); } } @@ -996,7 +996,7 @@ public boolean visit(Argument argument, BlockScope scope) { CtParameter p = factory.Core().createParameter(); p.setSimpleName(new String(argument.name)); p.setVarArgs(argument.isVarArgs()); - p.setModifiers(HelperJDTTreeBuilder.getModifiers(argument.modifiers)); + p.setModifiers(JDTTreeBuilderHelper.getModifiers(argument.modifiers)); if (argument.binding != null && argument.binding.type != null) { context.isLambdaParameterImplicitlyTyped = argument.type != null; if (argument.binding.type instanceof WildcardBinding) { @@ -1031,7 +1031,7 @@ public boolean onAccess(char[][] tokens, int index) { if (argument.annotations != null) { for (Annotation a : argument.annotations) { a.traverse(this, scope); - HelperJDTTreeBuilder.substituteAnnotation(p, a, CtAnnotatedElementType.TYPE_USE); + JDTTreeBuilderHelper.substituteAnnotation(p, a, CtAnnotatedElementType.TYPE_USE); } } @@ -1164,7 +1164,7 @@ public boolean visit(Assignment assignment, BlockScope scope) { @Override public boolean visit(BinaryExpression binaryExpression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(JDTTreeBuilderHelper.getBinaryOperatorKind((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, binaryExpression); return true; } @@ -1224,7 +1224,7 @@ public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) { @Override public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) { CtOperatorAssignment a = factory.Core().createOperatorAssignment(); - a.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind(compoundAssignment.operator)); + a.setKind(JDTTreeBuilderHelper.getBinaryOperatorKind(compoundAssignment.operator)); context.enter(a, compoundAssignment); context.arguments.push(a); context.assigned = true; @@ -1250,7 +1250,7 @@ public boolean visit(ConditionalExpression conditionalExpression, BlockScope sco @Override public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { CtConstructor c = factory.Core().createConstructor(); - c.setModifiers(HelperJDTTreeBuilder.getModifiers(constructorDeclaration.modifiers)); + c.setModifiers(JDTTreeBuilderHelper.getModifiers(constructorDeclaration.modifiers)); context.enter(c, constructorDeclaration); @@ -1376,7 +1376,7 @@ public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) { @Override public boolean visit(EqualExpression equalExpression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((equalExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(JDTTreeBuilderHelper.getBinaryOperatorKind((equalExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, equalExpression); return true; // do nothing by default, keep traversing } @@ -1449,7 +1449,7 @@ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { } } field.setSimpleName(new String(fieldDeclaration.name)); - field.setModifiers(HelperJDTTreeBuilder.getModifiers(fieldDeclaration.modifiers)); + field.setModifiers(JDTTreeBuilderHelper.getModifiers(fieldDeclaration.modifiers)); if (fieldDeclaration.annotations != null) { int annotationsLength = fieldDeclaration.annotations.length; @@ -1596,7 +1596,7 @@ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { CtLocalVariable v = factory.Core().createLocalVariable(); v.setSimpleName(new String(localDeclaration.name)); v.setType(this.references.buildTypeReference(localDeclaration.type, scope)); - v.setModifiers(HelperJDTTreeBuilder.getModifiers(localDeclaration.modifiers)); + v.setModifiers(JDTTreeBuilderHelper.getModifiers(localDeclaration.modifiers)); context.enter(v, localDeclaration); if (localDeclaration.initialization != null) { @@ -1608,7 +1608,7 @@ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) { if (localDeclaration.annotations != null) { for (Annotation a : localDeclaration.annotations) { a.traverse(this, scope); - HelperJDTTreeBuilder.substituteAnnotation(v, a, CtAnnotatedElementType.TYPE_USE); + JDTTreeBuilderHelper.substituteAnnotation(v, a, CtAnnotatedElementType.TYPE_USE); } } @@ -1790,7 +1790,7 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { CtMethod m = factory.Core().createMethod(); m.setSimpleName(new String(methodDeclaration.selector)); m.setType(this.references.buildTypeReference(methodDeclaration.returnType, scope)); - m.setModifiers(HelperJDTTreeBuilder.getModifiers(methodDeclaration.modifiers)); + m.setModifiers(JDTTreeBuilderHelper.getModifiers(methodDeclaration.modifiers)); m.setDefaultMethod(methodDeclaration.isDefaultMethod()); context.enter(m, methodDeclaration); @@ -1811,7 +1811,7 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { if (methodDeclaration.annotations != null) { for (Annotation a : methodDeclaration.annotations) { a.traverse(this, methodDeclaration.scope); - HelperJDTTreeBuilder.substituteAnnotation(m, a, CtAnnotatedElementType.TYPE_USE); + JDTTreeBuilderHelper.substituteAnnotation(m, a, CtAnnotatedElementType.TYPE_USE); } } @@ -1847,7 +1847,7 @@ public boolean visit(NullLiteral nullLiteral, BlockScope scope) { @Override public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) { CtBinaryOperator op = factory.Core().createBinaryOperator(); - op.setKind(HelperJDTTreeBuilder.getBinaryOperatorKind((or_or_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(JDTTreeBuilderHelper.getBinaryOperatorKind((or_or_Expression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, or_or_Expression); return true; } @@ -2135,7 +2135,7 @@ public boolean onAccess(char[][] tokens, int index) { ((CtFieldAccess) va).setTarget(factory.Code().createTypeAccess(declaringRef)); } // In no classpath mode and with qualified name, the binding don't have a good name. - va.getVariable().setSimpleName(HelperJDTTreeBuilder.createTypeName(CharOperation.subarray(qualifiedNameReference.tokens, qualifiedNameReference.tokens.length - 1, qualifiedNameReference.tokens.length))); + va.getVariable().setSimpleName(JDTTreeBuilderHelper.createTypeName(CharOperation.subarray(qualifiedNameReference.tokens, qualifiedNameReference.tokens.length - 1, qualifiedNameReference.tokens.length))); context.enter(va, qualifiedNameReference); return false; } else { @@ -2480,7 +2480,7 @@ private CtCatch createCtCatch(Argument jdtCatch, CtTypeReference r) { context.enter(var, jdtCatch); var.setSimpleName(new String(jdtCatch.name)); var.setType(r); - for (ModifierKind modifier : HelperJDTTreeBuilder.getModifiers(jdtCatch.modifiers)) { + for (ModifierKind modifier : JDTTreeBuilderHelper.getModifiers(jdtCatch.modifiers)) { var.addModifier(modifier); } context.exit(jdtCatch); @@ -2497,7 +2497,7 @@ private CtCatch createCtCatchJava7(Argument jdtCatch, CtTypeReference for (CtTypeReference ref : refs) { var.addMultiType(ref); } - for (ModifierKind modifier : HelperJDTTreeBuilder.getModifiers(jdtCatch.modifiers)) { + for (ModifierKind modifier : JDTTreeBuilderHelper.getModifiers(jdtCatch.modifiers)) { var.addModifier(modifier); } context.exit(jdtCatch); @@ -2604,7 +2604,7 @@ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope @Override public boolean visit(UnaryExpression unaryExpression, BlockScope scope) { CtUnaryOperator op = factory.Core().createUnaryOperator(); - op.setKind(HelperJDTTreeBuilder.getUnaryOperator((unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); + op.setKind(JDTTreeBuilderHelper.getUnaryOperator((unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT)); context.enter(op, unaryExpression); return true; } diff --git a/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java similarity index 99% rename from src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java rename to src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java index 8e2205f5de0..07bff5b4853 100644 --- a/src/main/java/spoon/support/compiler/jdt/HelperJDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java @@ -39,7 +39,7 @@ import java.util.EnumSet; import java.util.Set; -class HelperJDTTreeBuilder { +class JDTTreeBuilderHelper { static UnaryOperatorKind getUnaryOperator(int op) { switch (op) { @@ -297,7 +297,7 @@ private static boolean hasAnnotationWithType(Annotation a, CtAnnotatedElementTyp * @param elementType Type of the annotation. */ static void substituteAnnotation(CtTypedElement typedElement, Annotation a, CtAnnotatedElementType elementType) { - if (HelperJDTTreeBuilder.hasAnnotationWithType(a, elementType)) { + if (JDTTreeBuilderHelper.hasAnnotationWithType(a, elementType)) { CtAnnotation targetAnnotation = typedElement.getAnnotations().get(typedElement.getAnnotations().size() - 1); typedElement.removeAnnotation(targetAnnotation); typedElement.getType().addAnnotation(targetAnnotation); diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java index 0568c04a7da..bb2c35ee2aa 100644 --- a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -187,22 +187,22 @@ private CtTypeReference buildTypeReferenceInternal(CtTypeReference typ * @return a type reference. */ CtTypeReference getQualifiedTypeReference(char[][] tokens, TypeBinding receiverType, ReferenceBinding enclosingType, JDTTreeBuilder.OnAccessListener listener) { - if (enclosingType != null && Collections.disjoint(Arrays.asList(ModifierKind.PUBLIC, ModifierKind.PROTECTED), HelperJDTTreeBuilder.getModifiers(enclosingType.modifiers))) { + if (enclosingType != null && Collections.disjoint(Arrays.asList(ModifierKind.PUBLIC, ModifierKind.PROTECTED), JDTTreeBuilderHelper.getModifiers(enclosingType.modifiers))) { String access = ""; int i = 0; for (; i < tokens.length; i++) { final char[][] qualified = Arrays.copyOfRange(tokens, 0, i + 1); - if (!HelperJDTTreeBuilder.isPackage(qualified, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.typeRequestor))) { + if (!JDTTreeBuilderHelper.isPackage(qualified, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.typeRequestor))) { access = CharOperation.toString(qualified); break; } } if (!access.contains(CtPackage.PACKAGE_SEPARATOR)) { - access = HelperJDTTreeBuilder.hasTypeInImports(access, this.jdtTreeBuilder.getContextBuilder()); + access = JDTTreeBuilderHelper.hasTypeInImports(access, this.jdtTreeBuilder.getContextBuilder()); } - final TypeBinding accessBinding = HelperJDTTreeBuilder.searchTypeBinding(access, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.typeRequestor)); + final TypeBinding accessBinding = JDTTreeBuilderHelper.searchTypeBinding(access, ((TreeBuilderCompiler) this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.scope.environment.typeRequestor)); if (accessBinding != null && listener.onAccess(tokens, i)) { - final TypeBinding superClassBinding = HelperJDTTreeBuilder.searchTypeBinding(accessBinding.superclass(), CharOperation.charToString(tokens[i + 1])); + final TypeBinding superClassBinding = JDTTreeBuilderHelper.searchTypeBinding(accessBinding.superclass(), CharOperation.charToString(tokens[i + 1])); if (superClassBinding != null) { return this.getTypeReference(superClassBinding.clone(accessBinding)); } else { @@ -627,14 +627,14 @@ CtTypeReference getTypeReference(TypeBinding binding) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { - ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); + ref.setSimpleName(JDTTreeBuilderHelper.computeAnonymousName((SourceTypeBinding) binding)); ref.setDeclaringType(getTypeReference((binding.enclosingType()))); } else { ref.setSimpleName(new String(binding.sourceName())); if (((LocalTypeBinding) binding).enclosingMethod == null && binding.enclosingType() != null && binding.enclosingType() instanceof LocalTypeBinding) { ref.setDeclaringType(getTypeReference(binding.enclosingType())); } else if (binding.enclosingMethod() != null) { - ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); + ref.setSimpleName(JDTTreeBuilderHelper.computeAnonymousName((SourceTypeBinding) binding)); ref.setDeclaringType(getTypeReference(binding.enclosingType())); } } @@ -642,7 +642,7 @@ CtTypeReference getTypeReference(TypeBinding binding) { ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference(); ref.setImplicit(isImplicit || !this.jdtTreeBuilder.getContextBuilder().isLambdaParameterImplicitlyTyped); if (binding.isAnonymousType()) { - ref.setSimpleName(HelperJDTTreeBuilder.computeAnonymousName((SourceTypeBinding) binding)); + ref.setSimpleName(JDTTreeBuilderHelper.computeAnonymousName((SourceTypeBinding) binding)); ref.setDeclaringType(getTypeReference((binding.enclosingType()))); } else { ref.setSimpleName(new String(binding.sourceName()));