private ASTRewrite doAddLocal(CompilationUnit cu) { AST ast = cu.getAST(); Block body; BodyDeclaration decl = ASTResolving.findParentBodyDeclaration(fOriginalNode); IBinding targetContext = null; if (decl instanceof MethodDeclaration) { body = (((MethodDeclaration) decl).getBody()); targetContext = ((MethodDeclaration) decl).resolveBinding(); } else if (decl instanceof Initializer) { body = (((Initializer) decl).getBody()); targetContext = Bindings.getBindingOfParentType(decl); } else { return null; } ASTRewrite rewrite = ASTRewrite.create(ast); ImportRewrite imports = createImportRewrite((CompilationUnit) decl.getRoot()); ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext(decl, imports); SimpleName[] names = getAllReferences(body); ASTNode dominant = getDominantNode(names); Statement dominantStatement = ASTResolving.findParentStatement(dominant); if (ASTNodes.isControlStatementBody(dominantStatement.getLocationInParent())) { dominantStatement = (Statement) dominantStatement.getParent(); } SimpleName node = names[0]; if (isAssigned(dominantStatement, node)) { // x = 1; -> int x = 1; Assignment assignment = (Assignment) node.getParent(); // trick to avoid comment removal around the statement: keep the expression statement // and replace the assignment with an VariableDeclarationExpression VariableDeclarationFragment newDeclFrag = ast.newVariableDeclarationFragment(); VariableDeclarationExpression newDecl = ast.newVariableDeclarationExpression(newDeclFrag); newDecl.setType(evaluateVariableType(ast, imports, importRewriteContext, targetContext)); Expression placeholder = (Expression) rewrite.createCopyTarget(assignment.getRightHandSide()); newDeclFrag.setInitializer(placeholder); newDeclFrag.setName(ast.newSimpleName(node.getIdentifier())); rewrite.replace(assignment, newDecl, null); addLinkedPosition(rewrite.track(newDecl.getType()), false, KEY_TYPE); addLinkedPosition(rewrite.track(newDeclFrag.getName()), true, KEY_NAME); setEndPosition(rewrite.track(assignment.getParent())); return rewrite; } else if ((dominant != dominantStatement) && isForStatementInit(dominantStatement, node)) { // for (x = 1;;) ->for (int x = 1;;) Assignment assignment = (Assignment) node.getParent(); VariableDeclarationFragment frag = ast.newVariableDeclarationFragment(); VariableDeclarationExpression expression = ast.newVariableDeclarationExpression(frag); frag.setName(ast.newSimpleName(node.getIdentifier())); Expression placeholder = (Expression) rewrite.createCopyTarget(assignment.getRightHandSide()); frag.setInitializer(placeholder); expression.setType(evaluateVariableType(ast, imports, importRewriteContext, targetContext)); rewrite.replace(assignment, expression, null); addLinkedPosition(rewrite.track(expression.getType()), false, KEY_TYPE); addLinkedPosition(rewrite.track(frag.getName()), true, KEY_NAME); setEndPosition(rewrite.track(expression)); return rewrite; } else if ((dominant != dominantStatement) && isEnhancedForStatementVariable(dominantStatement, node)) { // for (x: collectionOfT) -> for (T x: collectionOfT) EnhancedForStatement enhancedForStatement = (EnhancedForStatement) dominantStatement; SingleVariableDeclaration parameter = enhancedForStatement.getParameter(); Expression expression = enhancedForStatement.getExpression(); SimpleName newName = (SimpleName) rewrite.createMoveTarget(node); rewrite.set(parameter, SingleVariableDeclaration.NAME_PROPERTY, newName, null); ITypeBinding elementBinding = null; ITypeBinding typeBinding = expression.resolveTypeBinding(); if (typeBinding != null) { if (typeBinding.isArray()) { elementBinding = typeBinding.getElementType(); } else { ITypeBinding iterable = Bindings.findTypeInHierarchy(typeBinding, "java.lang.Iterable"); // $NON-NLS-1$ if (iterable != null) { ITypeBinding[] typeArguments = iterable.getTypeArguments(); if (typeArguments.length == 1) { elementBinding = typeArguments[0]; elementBinding = Bindings.normalizeForDeclarationUse(elementBinding, ast); } } } } Type type; if (elementBinding != null) { type = imports.addImport(elementBinding, ast, importRewriteContext); } else { type = ast.newSimpleType(ast.newSimpleName("Object")); // $NON-NLS-1$ } rewrite.set(parameter, SingleVariableDeclaration.TYPE_PROPERTY, type, null); addLinkedPosition(rewrite.track(type), false, KEY_TYPE); addLinkedPosition(rewrite.track(newName), true, KEY_NAME); setEndPosition(rewrite.track(expression)); return rewrite; } // foo(x) -> int x; foo(x) VariableDeclarationFragment newDeclFrag = ast.newVariableDeclarationFragment(); VariableDeclarationStatement newDecl = ast.newVariableDeclarationStatement(newDeclFrag); newDeclFrag.setName(ast.newSimpleName(node.getIdentifier())); newDecl.setType(evaluateVariableType(ast, imports, importRewriteContext, targetContext)); // newDeclFrag.setInitializer(ASTNodeFactory.newDefaultExpression(ast, newDecl.getType(), 0)); addLinkedPosition(rewrite.track(newDecl.getType()), false, KEY_TYPE); addLinkedPosition(rewrite.track(node), true, KEY_NAME); addLinkedPosition(rewrite.track(newDeclFrag.getName()), false, KEY_NAME); Statement statement = dominantStatement; List<? extends ASTNode> list = ASTNodes.getContainingList(statement); while (list == null && statement.getParent() instanceof Statement) { // parent must be if, for or while statement = (Statement) statement.getParent(); list = ASTNodes.getContainingList(statement); } if (list != null) { ASTNode parent = statement.getParent(); StructuralPropertyDescriptor childProperty = statement.getLocationInParent(); if (childProperty.isChildListProperty()) { rewrite .getListRewrite(parent, (ChildListPropertyDescriptor) childProperty) .insertBefore(newDecl, statement, null); return rewrite; } else { return null; } } return rewrite; }
// generate a variable declaration with an initializer specified by the given expression // e.g. given x.f(a,b) ==> int y = x.f(a,b); public static List<Statement> genVarDeclStatement(Expression exp) { List<Statement> result = new ArrayList<Statement>(); VariableDeclarationFragment fragment = AST.newAST(AST.JLS8).newVariableDeclarationFragment(); ExpressionStatement assignmentStmt = genAssignmentStatement(exp); // The type of the generated variable Type varType = AST.newAST(AST.JLS8).newWildcardType(); if (exp.resolveTypeBinding() != null) { if (exp.resolveTypeBinding().isPrimitive()) { switch (exp.resolveTypeBinding().getName()) { case "void": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.VOID); break; case "int": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.INT); break; case "char": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.CHAR); break; case "long": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.LONG); break; case "boolean": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.BOOLEAN); break; case "float": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.FLOAT); break; case "short": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.SHORT); break; case "byte": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.BYTE); break; case "double": varType = AST.newAST(AST.JLS8).newPrimitiveType(PrimitiveType.DOUBLE); break; } } else { // Option 1: only use the simplename /* SimpleName typeName = AST.newAST(AST.JLS8).newSimpleName(exp.resolveTypeBinding().getName()); AST tempAST = AST.newAST(AST.JLS8); varType = tempAST.newSimpleType((Name) ASTNode.copySubtree(tempAST, typeName)); */ varType = resolveQualifiedType(exp.resolveTypeBinding().getQualifiedName()); } } // Declaration Fragment fragment.setName( (SimpleName) ASTNode.copySubtree( fragment.getAST(), ((SimpleName) ((Assignment) assignmentStmt.getExpression()).getLeftHandSide()))); // fragment.setInitializer((Expression) ASTNode.copySubtree(fragment.getAST(), exp)); AST varDeclFragAST = AST.newAST(AST.JLS8); VariableDeclarationStatement decl = varDeclFragAST.newVariableDeclarationStatement( (VariableDeclarationFragment) ASTNode.copySubtree(varDeclFragAST, fragment)); decl.setType((Type) ASTNode.copySubtree(decl.getAST(), varType)); result.add(decl); // initializer is defined here as a separate statement Assignment assign = varDeclFragAST.newAssignment(); assign.setLeftHandSide((Expression) ASTNode.copySubtree(varDeclFragAST, fragment.getName())); assign.setRightHandSide((Expression) ASTNode.copySubtree(varDeclFragAST, exp)); ExpressionStatement assignStmt = varDeclFragAST.newExpressionStatement(assign); result.add(assignStmt); return result; }