private static String getArgument(TagElement curr) { List<? extends ASTNode> fragments = curr.fragments(); if (!fragments.isEmpty()) { Object first = fragments.get(0); if (first instanceof Name) { return ASTNodes.getSimpleNameIdentifier((Name) first); } else if (first instanceof TextElement && TagElement.TAG_PARAM.equals(curr.getTagName())) { String text = ((TextElement) first).getText(); if ("<".equals(text) && fragments.size() >= 3) { // $NON-NLS-1$ Object second = fragments.get(1); Object third = fragments.get(2); if (second instanceof Name && third instanceof TextElement && ">".equals(((TextElement) third).getText())) { // $NON-NLS-1$ return '<' + ASTNodes.getSimpleNameIdentifier((Name) second) + '>'; } } else if (text.startsWith(String.valueOf('<')) && text.endsWith(String.valueOf('>')) && text.length() > 2) { return text.substring(1, text.length() - 1); } } } return null; }
private static VariableDeclaration getVariableDeclaration(Name node) { IBinding binding = node.resolveBinding(); if (binding == null && node.getParent() instanceof VariableDeclaration) return (VariableDeclaration) node.getParent(); if (binding != null && binding.getKind() == IBinding.VARIABLE) { CompilationUnit cu = (CompilationUnit) ASTNodes.getParent(node, CompilationUnit.class); return ASTNodes.findVariableDeclaration(((IVariableBinding) binding), cu); } return null; }
private int findFieldInsertIndex( List<BodyDeclaration> decls, FieldDeclaration newDecl, int maxOffset) { if (maxOffset != -1) { for (int i = decls.size() - 1; i >= 0; i--) { BodyDeclaration curr = decls.get(i); if (maxOffset > curr.getStartPosition() + curr.getLength()) { return ASTNodes.getInsertionIndex(newDecl, decls.subList(0, i + 1)); } } return 0; } return ASTNodes.getInsertionIndex(newDecl, decls); }
/* * Evaluates possible return expressions. The favourite expression is returned. */ private Expression evaluateReturnExpressions( AST ast, ITypeBinding returnBinding, int returnOffset) { CompilationUnit root = (CompilationUnit) fMethodDecl.getRoot(); Expression result = null; if (returnBinding != null) { ScopeAnalyzer analyzer = new ScopeAnalyzer(root); IBinding[] bindings = analyzer.getDeclarationsInScope( returnOffset, ScopeAnalyzer.VARIABLES | ScopeAnalyzer.CHECK_VISIBILITY); for (int i = 0; i < bindings.length; i++) { IVariableBinding curr = (IVariableBinding) bindings[i]; ITypeBinding type = curr.getType(); if (type != null && type.isAssignmentCompatible(returnBinding) && testModifier(curr)) { if (result == null) { result = ast.newSimpleName(curr.getName()); } addLinkedPositionProposal(RETURN_EXPRESSION_KEY, curr.getName(), null); } } } Expression defaultExpression = ASTNodeFactory.newDefaultExpression( ast, fMethodDecl.getReturnType2(), fMethodDecl.getExtraDimensions()); addLinkedPositionProposal(RETURN_EXPRESSION_KEY, ASTNodes.asString(defaultExpression), null); if (result == null) { return defaultExpression; } return result; }
private static boolean canAddFinal(IBinding binding, ASTNode declNode) { if (!(binding instanceof IVariableBinding)) return false; IVariableBinding varbinding = (IVariableBinding) binding; int modifiers = varbinding.getModifiers(); if (Modifier.isFinal(modifiers) || Modifier.isVolatile(modifiers) || Modifier.isTransient(modifiers)) return false; ASTNode parent = ASTNodes.getParent(declNode, VariableDeclarationExpression.class); if (parent != null && ((VariableDeclarationExpression) parent).fragments().size() > 1) return false; if (varbinding.isField() && !Modifier.isPrivate(modifiers)) return false; if (varbinding.isParameter()) { ASTNode varDecl = declNode.getParent(); if (varDecl instanceof MethodDeclaration) { MethodDeclaration declaration = (MethodDeclaration) varDecl; if (declaration.getBody() == null) return false; } } return true; }
private ASTNode getCommonParent(ASTNode node1, ASTNode node2) { ASTNode parent = node1.getParent(); while (parent != null && !ASTNodes.isParent(node2, parent)) { parent = parent.getParent(); } return parent; }
/** * Checks if the assignment needs a downcast and inserts it if necessary * * @param expression the right hand-side * @param expressionType the type of the right hand-side. Can be null * @param ast the AST * @param variableType the Type of the variable the expression will be assigned to * @param is50OrHigher if <code>true</code> java 5.0 code will be assumed * @return the casted expression if necessary */ private static Expression createNarrowCastIfNessecary( Expression expression, ITypeBinding expressionType, AST ast, ITypeBinding variableType, boolean is50OrHigher) { PrimitiveType castTo = null; if (variableType.isEqualTo(expressionType)) return expression; // no cast for same type if (is50OrHigher) { if (ast.resolveWellKnownType("java.lang.Character").isEqualTo(variableType)) // $NON-NLS-1$ castTo = ast.newPrimitiveType(PrimitiveType.CHAR); if (ast.resolveWellKnownType("java.lang.Byte").isEqualTo(variableType)) // $NON-NLS-1$ castTo = ast.newPrimitiveType(PrimitiveType.BYTE); if (ast.resolveWellKnownType("java.lang.Short").isEqualTo(variableType)) // $NON-NLS-1$ castTo = ast.newPrimitiveType(PrimitiveType.SHORT); } if (ast.resolveWellKnownType("char").isEqualTo(variableType)) // $NON-NLS-1$ castTo = ast.newPrimitiveType(PrimitiveType.CHAR); if (ast.resolveWellKnownType("byte").isEqualTo(variableType)) // $NON-NLS-1$ castTo = ast.newPrimitiveType(PrimitiveType.BYTE); if (ast.resolveWellKnownType("short").isEqualTo(variableType)) // $NON-NLS-1$ castTo = ast.newPrimitiveType(PrimitiveType.SHORT); if (castTo != null) { CastExpression cast = ast.newCastExpression(); if (ASTNodes.needsParentheses(expression)) { ParenthesizedExpression parenthesized = ast.newParenthesizedExpression(); parenthesized.setExpression(expression); cast.setExpression(parenthesized); } else cast.setExpression(expression); cast.setType(castTo); return cast; } return expression; }
private boolean callsWritingConstructor( MethodDeclaration methodDeclaration, HashSet writingConstructorBindings, Set visitedMethodDeclarations) { Block body = methodDeclaration.getBody(); if (body == null) return false; List statements = body.statements(); if (statements.size() == 0) return false; Statement statement = (Statement) statements.get(0); if (!(statement instanceof ConstructorInvocation)) return false; ConstructorInvocation invocation = (ConstructorInvocation) statement; IMethodBinding constructorBinding = invocation.resolveConstructorBinding(); if (constructorBinding == null) return false; if (writingConstructorBindings.contains(constructorBinding)) { return true; } else { ASTNode declaration = ASTNodes.findDeclaration(constructorBinding, methodDeclaration.getParent()); if (!(declaration instanceof MethodDeclaration)) return false; if (visitedMethodDeclarations.contains(declaration)) { return false; } visitedMethodDeclarations.add(methodDeclaration); return callsWritingConstructor( (MethodDeclaration) declaration, writingConstructorBindings, visitedMethodDeclarations); } }
private static Set<String> getPreviousExceptionNames(List<Type> list, ASTNode missingNode) { Set<String> previousNames = new HashSet<>(); for (int i = 0; i < list.size() && missingNode != list.get(i); i++) { Type curr = list.get(i); previousNames.add(ASTNodes.getTypeName(curr)); } return previousNames; }
/** * Returns the type to which the new constant will be added to. It is the first non-anonymous * parent. * * @return the type to add the new constant to * @throws JavaModelException shouldn't happen */ private AbstractTypeDeclaration getContainingTypeDeclarationNode() throws JavaModelException { AbstractTypeDeclaration result = (AbstractTypeDeclaration) ASTNodes.getParent( getSelectedExpression().getAssociatedNode(), AbstractTypeDeclaration.class); Assert.isNotNull(result); return result; }
private boolean processCompilerError(RefactoringStatus result, ASTNode node) { Message[] messages = ASTNodes.getMessages(node, ASTNodes.INCLUDE_ALL_PARENTS); if (messages.length == 0) return false; result.addFatalError( Messages.format( "Compiler errors with the class to be refactored", new String[] {targetClass.getElementName(), messages[0].getMessage()})); return true; }
public static void getMissingJavadocTagProposals( IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) { ASTNode node = problem.getCoveringNode(context.getASTRoot()); if (node == null) { return; } node = ASTNodes.getNormalizedNode(node); BodyDeclaration bodyDeclaration = ASTResolving.findParentBodyDeclaration(node); if (bodyDeclaration == null) { return; } Javadoc javadoc = bodyDeclaration.getJavadoc(); if (javadoc == null) { return; } String label; StructuralPropertyDescriptor location = node.getLocationInParent(); if (location == SingleVariableDeclaration.NAME_PROPERTY) { label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_paramtag_description; if (node.getParent().getLocationInParent() != MethodDeclaration.PARAMETERS_PROPERTY) { return; // paranoia checks } } else if (location == TypeParameter.NAME_PROPERTY) { label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_paramtag_description; StructuralPropertyDescriptor parentLocation = node.getParent().getLocationInParent(); if (parentLocation != MethodDeclaration.TYPE_PARAMETERS_PROPERTY && parentLocation != TypeDeclaration.TYPE_PARAMETERS_PROPERTY) { return; // paranoia checks } } else if (location == MethodDeclaration.RETURN_TYPE2_PROPERTY) { label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_returntag_description; } else if (location == MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY) { label = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_throwstag_description; } else { return; } ASTRewriteCorrectionProposal proposal = new AddMissingJavadocTagProposal( label, context.getCompilationUnit(), bodyDeclaration, node, IProposalRelevance.ADD_MISSING_TAG); proposals.add(proposal); String label2 = CorrectionMessages.JavadocTagsSubProcessor_addjavadoc_allmissing_description; ASTRewriteCorrectionProposal addAllMissing = new AddAllMissingJavadocTagsProposal( label2, context.getCompilationUnit(), bodyDeclaration, IProposalRelevance.ADD_ALL_MISSING_TAGS); proposals.add(addAllMissing); }
/* * Check if the node is in a block. We don't want to update declarations */ private static boolean isNotInBlock(ASTNode parent) { ASTNode statement = parent.getParent(); boolean isStatement = statement.getNodeType() != ASTNode.EXPRESSION_STATEMENT; ASTNode block = statement.getParent(); boolean isBlock = block.getNodeType() == ASTNode.BLOCK || block.getNodeType() == ASTNode.SWITCH_STATEMENT; boolean isControlStatemenBody = ASTNodes.isControlStatementBody(statement.getLocationInParent()); return isStatement || !(isBlock || isControlStatemenBody); }
public void testPartialCU1() throws Exception { IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null); StringBuffer buf = new StringBuffer(); buf.append("package test1;\n"); buf.append("import java.util.Vector;\n"); buf.append("public class E {\n"); buf.append(" private int fField1;\n"); buf.append(" private int fField2;\n"); buf.append(" public void foo1() {\n"); buf.append(" fField1 = fField2;\n"); buf.append(" }\n"); buf.append(" public int foo1(int i) {\n"); buf.append(" return i;\n"); buf.append(" }\n"); buf.append("}"); String existing = buf.toString(); ICompilationUnit cu = pack1.createCompilationUnit("E.java", existing, false, null); String statement = "fField1 = fField2;"; int offset = existing.indexOf(statement); CompilationUnit astRoot = getPartialCompilationUnit(cu, offset); String string = ASTNodes.asFormattedString(astRoot, 0, String.valueOf('\n'), null); buf = new StringBuffer(); buf.append("package test1;\n"); buf.append("import java.util.Vector;\n"); buf.append("public class E {\n"); buf.append(" private int fField1;\n"); buf.append(" private int fField2;\n"); buf.append(" public void foo1() {\n"); buf.append(" fField1 = fField2;\n"); buf.append(" }\n"); buf.append(" public int foo1(int i) {\n"); buf.append(" }\n"); buf.append("}"); String expected = buf.toString(); assertEqualString(string, expected); offset = expected.indexOf(statement); ASTNode node = NodeFinder.perform(astRoot, offset, statement.length()); Assignment assignment = (Assignment) ((ExpressionStatement) node).getExpression(); Expression e1 = assignment.getLeftHandSide(); Expression e2 = assignment.getRightHandSide(); assertNotNull(e1.resolveTypeBinding()); assertNotNull(e2.resolveTypeBinding()); assertTrue(((SimpleName) e1).resolveBinding() instanceof IVariableBinding); assertTrue(((SimpleName) e2).resolveBinding() instanceof IVariableBinding); assertAllBindings(astRoot); }
private SingleVariableDeclaration createParameterDeclaration( String parameterName, VariableDeclarationFragment fragement, Expression arrayAccess, ForStatement statement, ImportRewrite importRewrite, ASTRewrite rewrite, TextEditGroup group, LinkedProposalPositionGroup pg, boolean makeFinal) { CompilationUnit compilationUnit = (CompilationUnit) arrayAccess.getRoot(); AST ast = compilationUnit.getAST(); SingleVariableDeclaration result = ast.newSingleVariableDeclaration(); SimpleName name = ast.newSimpleName(parameterName); pg.addPosition(rewrite.track(name), true); result.setName(name); ITypeBinding arrayTypeBinding = arrayAccess.resolveTypeBinding(); Type type = importType(arrayTypeBinding.getElementType(), statement, importRewrite, compilationUnit); if (arrayTypeBinding.getDimensions() != 1) { type = ast.newArrayType(type, arrayTypeBinding.getDimensions() - 1); } result.setType(type); if (fragement != null) { VariableDeclarationStatement declaration = (VariableDeclarationStatement) fragement.getParent(); ModifierRewrite.create(rewrite, result).copyAllModifiers(declaration, group); } if (makeFinal && (fragement == null || ASTNodes.findModifierNode(Modifier.FINAL, ASTNodes.getModifiers(fragement)) == null)) { ModifierRewrite.create(rewrite, result).setModifiers(Modifier.FINAL, 0, group); } return result; }
public void checkInput(RefactoringStatus status, String methodName, ASTNode destination) { ITypeBinding[] arguments = getArgumentTypes(); ITypeBinding type = ASTNodes.getEnclosingType(destination); status.merge(Checks.checkMethodInType(type, methodName, arguments)); ITypeBinding superClass = type.getSuperclass(); if (superClass != null) { status.merge(Checks.checkMethodInHierarchy(superClass, methodName, null, arguments)); } for (ITypeBinding superInterface : type.getInterfaces()) { status.merge(Checks.checkMethodInHierarchy(superInterface, methodName, null, arguments)); } }
public static ASTNode getEnclosingNode(ASTNode firstSelectedNode) { ASTNode enclosingNode; if (firstSelectedNode instanceof MethodReference) { enclosingNode = firstSelectedNode; } else { enclosingNode = ASTResolving.findEnclosingLambdaExpression(firstSelectedNode); if (enclosingNode != null) { enclosingNode = ((LambdaExpression) enclosingNode).getBody(); } else { enclosingNode = ASTNodes.getParent(firstSelectedNode, BodyDeclaration.class); } } return enclosingNode; }
public static void getUnusedAndUndocumentedParameterOrExceptionProposals( IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) { ICompilationUnit cu = context.getCompilationUnit(); IJavaProject project = cu.getJavaProject(); if (!JavaCore.ENABLED.equals(project.getOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, true))) { return; } int problemId = problem.getProblemId(); boolean isUnusedTypeParam = problemId == IProblem.UnusedTypeParameter; boolean isUnusedParam = problemId == IProblem.ArgumentIsNeverUsed || isUnusedTypeParam; String key = isUnusedParam ? JavaCore.COMPILER_PB_UNUSED_PARAMETER_INCLUDE_DOC_COMMENT_REFERENCE : JavaCore.COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION_INCLUDE_DOC_COMMENT_REFERENCE; if (!JavaCore.ENABLED.equals(project.getOption(key, true))) { return; } ASTNode node = problem.getCoveringNode(context.getASTRoot()); if (node == null) { return; } BodyDeclaration bodyDecl = ASTResolving.findParentBodyDeclaration(node); if (bodyDecl == null || ASTResolving.getParentMethodOrTypeBinding(bodyDecl) == null) { return; } String label; if (isUnusedTypeParam) { label = CorrectionMessages.JavadocTagsSubProcessor_document_type_parameter_description; } else if (isUnusedParam) { label = CorrectionMessages.JavadocTagsSubProcessor_document_parameter_description; } else { node = ASTNodes.getNormalizedNode(node); label = CorrectionMessages.JavadocTagsSubProcessor_document_exception_description; } ASTRewriteCorrectionProposal proposal = new AddMissingJavadocTagProposal( label, context.getCompilationUnit(), bodyDecl, node, IProposalRelevance.DOCUMENT_UNUSED_ITEM); proposals.add(proposal); }
private MethodDeclaration getWritingConstructor(SimpleName name) { Assignment assignement = (Assignment) ASTNodes.getParent(name, Assignment.class); if (assignement == null) return null; ASTNode expression = assignement.getParent(); if (!(expression instanceof ExpressionStatement)) return null; ASTNode block = expression.getParent(); if (!(block instanceof Block)) return null; ASTNode methodDeclaration = block.getParent(); if (!(methodDeclaration instanceof MethodDeclaration)) return null; return (MethodDeclaration) methodDeclaration; }
@Override public void run(IProgressMonitor monitor) throws CoreException { if (monitor == null) monitor = new NullProgressMonitor(); try { monitor.beginTask("", 1); // $NON-NLS-1$ monitor.setTaskName(CodeGenerationMessages.GenerateToStringOperation_description); AbstractTypeDeclaration declaration = (AbstractTypeDeclaration) ASTNodes.findDeclaration(fContext.getTypeBinding(), fRewrite.getRoot()); ListRewrite rewriter = fRewrite .getASTRewrite() .getListRewrite(declaration, declaration.getBodyDeclarationsProperty()); if (fContext.getTypeBinding() != null && rewriter != null) { MethodDeclaration toStringMethod = fGenerator.generateToStringMethod(); List<BodyDeclaration> list = declaration.bodyDeclarations(); BodyDeclaration replace = findMethodToReplace(list, toStringMethod); if (replace == null || ((Boolean) toStringMethod.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)) .booleanValue()) insertMethod(toStringMethod, rewriter, replace); List<MethodDeclaration> helperMethods = fGenerator.generateHelperMethods(); for (Iterator<MethodDeclaration> iterator = helperMethods.iterator(); iterator.hasNext(); ) { MethodDeclaration method = iterator.next(); replace = findMethodToReplace(list, method); if (replace == null || ((Boolean) method.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)) .booleanValue()) { insertMethod(method, rewriter, replace); } } JavaModelUtil.applyEdit( (ICompilationUnit) fUnit.getJavaElement(), fRewrite.createChange(true).getEdit(), false, monitor); } } finally { monitor.done(); } }
/** * Converts an assignment, postfix expression or prefix expression into an assignable equivalent * expression using the getter. * * @param node the assignment/prefix/postfix node * @param astRewrite the astRewrite to use * @param getterExpression the expression to insert for read accesses or <code>null</code> if such * an expression does not exist * @param variableType the type of the variable that the result will be assigned to * @param is50OrHigher <code>true</code> if a 5.0 or higher environment can be used * @return an expression that can be assigned to the type variableType with node being replaced by * a equivalent expression using the getter */ public static Expression getAssignedValue( ASTNode node, ASTRewrite astRewrite, Expression getterExpression, ITypeBinding variableType, boolean is50OrHigher) { InfixExpression.Operator op = null; AST ast = astRewrite.getAST(); if (isNotInBlock(node)) return null; if (node.getNodeType() == ASTNode.ASSIGNMENT) { Assignment assignment = ((Assignment) node); Expression rightHandSide = assignment.getRightHandSide(); Expression copiedRightOp = (Expression) astRewrite.createCopyTarget(rightHandSide); if (assignment.getOperator() == Operator.ASSIGN) { ITypeBinding rightHandSideType = rightHandSide.resolveTypeBinding(); copiedRightOp = createNarrowCastIfNessecary( copiedRightOp, rightHandSideType, ast, variableType, is50OrHigher); return copiedRightOp; } if (getterExpression != null) { InfixExpression infix = ast.newInfixExpression(); infix.setLeftOperand(getterExpression); infix.setOperator(ASTNodes.convertToInfixOperator(assignment.getOperator())); infix.setRightOperand(copiedRightOp); ITypeBinding infixType = infix.resolveTypeBinding(); return createNarrowCastIfNessecary(infix, infixType, ast, variableType, is50OrHigher); } } else if (node.getNodeType() == ASTNode.POSTFIX_EXPRESSION) { PostfixExpression po = (PostfixExpression) node; if (po.getOperator() == PostfixExpression.Operator.INCREMENT) op = InfixExpression.Operator.PLUS; if (po.getOperator() == PostfixExpression.Operator.DECREMENT) op = InfixExpression.Operator.MINUS; } else if (node.getNodeType() == ASTNode.PREFIX_EXPRESSION) { PrefixExpression pe = (PrefixExpression) node; if (pe.getOperator() == PrefixExpression.Operator.INCREMENT) op = InfixExpression.Operator.PLUS; if (pe.getOperator() == PrefixExpression.Operator.DECREMENT) op = InfixExpression.Operator.MINUS; } if (op != null && getterExpression != null) { return createInfixInvocationFromPostPrefixExpression( op, getterExpression, ast, variableType, is50OrHigher); } return null; }
private void checkExpression(RefactoringStatus status) { ASTNode[] nodes = getSelectedNodes(); if (nodes != null && nodes.length == 1) { ASTNode node = nodes[0]; if (node instanceof Type) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_type_reference, JavaStatusContext.create(fCUnit, node)); } else if (node.getLocationInParent() == SwitchCase.EXPRESSION_PROPERTY) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_switch_case, JavaStatusContext.create(fCUnit, node)); } else if (node instanceof Annotation || ASTNodes.getParent(node, Annotation.class) != null) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_from_annotation, JavaStatusContext.create(fCUnit, node)); } } }
@Override public void endVisit(CompilationUnit node) { postProcessSelectedNodes(internalGetSelectedNodes()); ASTNode enclosingNode = null; superCall: { if (getStatus().hasFatalError()) break superCall; if (!hasSelectedNodes()) { ASTNode coveringNode = getLastCoveringNode(); if (coveringNode instanceof Block) { Block block = (Block) coveringNode; Message[] messages = ASTNodes.getMessages(block, ASTNodes.NODE_ONLY); if (messages.length > 0) { invalidSelection( RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_compile_errors, JavaStatusContext.create(getCompilationUnit(), block)); break superCall; } } invalidSelection(RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_doesNotCover); break superCall; } enclosingNode = getEnclosingNode(getFirstSelectedNode()); boolean isValidEnclosingNode = enclosingNode instanceof MethodDeclaration || enclosingNode instanceof Initializer; if (fSurroundWithTryCatch) { isValidEnclosingNode = isValidEnclosingNode || enclosingNode instanceof MethodReference || enclosingNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY; } if (!isValidEnclosingNode) { invalidSelection(RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_doesNotContain); break superCall; } if (!validSelectedNodes()) { invalidSelection(RefactoringCoreMessages.SurroundWithTryCatchAnalyzer_onlyStatements); } fLocals = LocalDeclarationAnalyzer.perform(enclosingNode, getSelection()); } super.endVisit(node); }
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; }
private void insertAllMissingMethodTags(ASTRewrite rewriter, MethodDeclaration methodDecl) { AST ast = methodDecl.getAST(); Javadoc javadoc = methodDecl.getJavadoc(); ListRewrite tagsRewriter = rewriter.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY); List<TypeParameter> typeParams = methodDecl.typeParameters(); ASTNode root = methodDecl.getRoot(); if (root instanceof CompilationUnit) { ITypeRoot typeRoot = ((CompilationUnit) root).getTypeRoot(); if (typeRoot != null && !StubUtility.shouldGenerateMethodTypeParameterTags(typeRoot.getJavaProject())) typeParams = Collections.emptyList(); } List<String> typeParamNames = new ArrayList<>(); for (int i = typeParams.size() - 1; i >= 0; i--) { TypeParameter decl = typeParams.get(i); String name = '<' + decl.getName().getIdentifier() + '>'; if (findTag(javadoc, TagElement.TAG_PARAM, name) == null) { TagElement newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_PARAM); TextElement text = ast.newTextElement(); text.setText(name); newTag.fragments().add(text); insertTabStop(rewriter, newTag.fragments(), "typeParam" + i); // $NON-NLS-1$ insertTag(tagsRewriter, newTag, getPreviousTypeParamNames(typeParams, decl)); } typeParamNames.add(name); } List<SingleVariableDeclaration> params = methodDecl.parameters(); for (int i = params.size() - 1; i >= 0; i--) { SingleVariableDeclaration decl = params.get(i); String name = decl.getName().getIdentifier(); if (findTag(javadoc, TagElement.TAG_PARAM, name) == null) { TagElement newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_PARAM); newTag.fragments().add(ast.newSimpleName(name)); insertTabStop(rewriter, newTag.fragments(), "methParam" + i); // $NON-NLS-1$ Set<String> sameKindLeadingNames = getPreviousParamNames(params, decl); sameKindLeadingNames.addAll(typeParamNames); insertTag(tagsRewriter, newTag, sameKindLeadingNames); } } if (!methodDecl.isConstructor()) { Type type = methodDecl.getReturnType2(); if (!type.isPrimitiveType() || (((PrimitiveType) type).getPrimitiveTypeCode() != PrimitiveType.VOID)) { if (findTag(javadoc, TagElement.TAG_RETURN, null) == null) { TagElement newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_RETURN); insertTabStop(rewriter, newTag.fragments(), "return"); // $NON-NLS-1$ insertTag(tagsRewriter, newTag, null); } } } List<Type> thrownExceptions = methodDecl.thrownExceptionTypes(); for (int i = thrownExceptions.size() - 1; i >= 0; i--) { Type exception = thrownExceptions.get(i); ITypeBinding binding = exception.resolveBinding(); if (binding != null) { String name = binding.getName(); if (findThrowsTag(javadoc, name) == null) { TagElement newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_THROWS); TextElement excNode = ast.newTextElement(); excNode.setText(ASTNodes.getQualifiedTypeName(exception)); newTag.fragments().add(excNode); insertTabStop(rewriter, newTag.fragments(), "exception" + i); // $NON-NLS-1$ insertTag(tagsRewriter, newTag, getPreviousExceptionNames(thrownExceptions, exception)); } } } }
private boolean fieldCanBeFinal( VariableDeclarationFragment fragment, IVariableBinding binding) { if (Modifier.isStatic(((FieldDeclaration) fragment.getParent()).getModifiers())) return false; if (!fWrittenVariables.containsKey(binding)) { // variable is not written if (fragment.getInitializer() == null) { // variable is not initialized return false; } else { return true; } } if (fragment.getInitializer() != null) // variable is initialized and written return false; ITypeBinding declaringClass = binding.getDeclaringClass(); if (declaringClass == null) return false; ArrayList writes = (ArrayList) fWrittenVariables.get(binding); if (!isWrittenInTypeConstructors(writes, declaringClass)) return false; HashSet writingConstructorBindings = new HashSet(); ArrayList writingConstructors = new ArrayList(); for (int i = 0; i < writes.size(); i++) { SimpleName name = (SimpleName) writes.get(i); MethodDeclaration constructor = getWritingConstructor(name); if (writingConstructors.contains( constructor)) // variable is written twice or more in constructor return false; if (canReturn(constructor)) return false; writingConstructors.add(constructor); IMethodBinding constructorBinding = constructor.resolveBinding(); if (constructorBinding == null) return false; writingConstructorBindings.add(constructorBinding); } for (int i = 0; i < writingConstructors.size(); i++) { MethodDeclaration constructor = (MethodDeclaration) writingConstructors.get(i); if (callsWritingConstructor( constructor, writingConstructorBindings)) // writing constructor calls other writing constructor return false; } MethodDeclaration constructor = (MethodDeclaration) writingConstructors.get(0); TypeDeclaration typeDecl = (TypeDeclaration) ASTNodes.getParent(constructor, TypeDeclaration.class); if (typeDecl == null) return false; MethodDeclaration[] methods = typeDecl.getMethods(); for (int i = 0; i < methods.length; i++) { if (methods[i].isConstructor()) { IMethodBinding methodBinding = methods[i].resolveBinding(); if (methodBinding == null) return false; if (!writingConstructorBindings.contains(methodBinding)) { if (!callsWritingConstructor( methods[i], writingConstructorBindings)) // non writing constructor does not call a writing // constructor return false; } } } return true; }
@Override public void endVisit(CompilationUnit node) { RefactoringStatus status = getStatus(); superCall: { if (status.hasFatalError()) break superCall; if (!hasSelectedNodes()) { ASTNode coveringNode = getLastCoveringNode(); if (coveringNode instanceof Block && coveringNode.getParent() instanceof MethodDeclaration) { MethodDeclaration methodDecl = (MethodDeclaration) coveringNode.getParent(); Message[] messages = ASTNodes.getMessages(methodDecl, ASTNodes.NODE_ONLY); if (messages.length > 0) { status.addFatalError( Messages.format( RefactoringCoreMessages.ExtractMethodAnalyzer_compile_errors, BasicElementLabels.getJavaElementName(methodDecl.getName().getIdentifier())), JavaStatusContext.create(fCUnit, methodDecl)); break superCall; } } status.addFatalError(RefactoringCoreMessages.ExtractMethodAnalyzer_invalid_selection); break superCall; } fEnclosingBodyDeclaration = (BodyDeclaration) ASTNodes.getParent(getFirstSelectedNode(), BodyDeclaration.class); if (fEnclosingBodyDeclaration == null || (fEnclosingBodyDeclaration.getNodeType() != ASTNode.METHOD_DECLARATION && fEnclosingBodyDeclaration.getNodeType() != ASTNode.FIELD_DECLARATION && fEnclosingBodyDeclaration.getNodeType() != ASTNode.INITIALIZER)) { status.addFatalError(RefactoringCoreMessages.ExtractMethodAnalyzer_invalid_selection); break superCall; } else if (ASTNodes.getEnclosingType(fEnclosingBodyDeclaration) == null) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_compile_errors_no_parent_binding); break superCall; } else if (fEnclosingBodyDeclaration.getNodeType() == ASTNode.METHOD_DECLARATION) { fEnclosingMethodBinding = ((MethodDeclaration) fEnclosingBodyDeclaration).resolveBinding(); } if (!isSingleExpressionOrStatementSet()) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_single_expression_or_set); break superCall; } if (isExpressionSelected()) { ASTNode expression = getFirstSelectedNode(); if (expression instanceof Name) { Name name = (Name) expression; if (name.resolveBinding() instanceof ITypeBinding) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_type_reference); break superCall; } if (name.resolveBinding() instanceof IMethodBinding) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_method_name_reference); break superCall; } if (name.resolveBinding() instanceof IVariableBinding) { StructuralPropertyDescriptor locationInParent = name.getLocationInParent(); if (locationInParent == QualifiedName.NAME_PROPERTY || (locationInParent == FieldAccess.NAME_PROPERTY && !(((FieldAccess) name.getParent()).getExpression() instanceof ThisExpression))) { status.addFatalError( RefactoringCoreMessages .ExtractMethodAnalyzer_cannot_extract_part_of_qualified_name); break superCall; } } if (name.isSimpleName() && ((SimpleName) name).isDeclaration()) { status.addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_name_in_declaration); break superCall; } } fForceStatic = ASTNodes.getParent(expression, ASTNode.SUPER_CONSTRUCTOR_INVOCATION) != null || ASTNodes.getParent(expression, ASTNode.CONSTRUCTOR_INVOCATION) != null; } status.merge(LocalTypeAnalyzer.perform(fEnclosingBodyDeclaration, getSelection())); computeLastStatementSelected(); } super.endVisit(node); }
private void computeOutput(RefactoringStatus status) { // First find all writes inside the selection. FlowContext flowContext = new FlowContext(0, fMaxVariableId + 1); flowContext.setConsiderAccessMode(true); flowContext.setComputeMode(FlowContext.RETURN_VALUES); FlowInfo returnInfo = new InOutFlowAnalyzer(flowContext).perform(getSelectedNodes()); IVariableBinding[] returnValues = returnInfo.get(flowContext, FlowInfo.WRITE | FlowInfo.WRITE_POTENTIAL | FlowInfo.UNKNOWN); // Compute a selection that exactly covers the selected nodes IRegion region = getSelectedNodeRange(); Selection selection = Selection.createFromStartLength(region.getOffset(), region.getLength()); List<IVariableBinding> localReads = new ArrayList<>(); flowContext.setComputeMode(FlowContext.ARGUMENTS); FlowInfo argInfo = new InputFlowAnalyzer(flowContext, selection, true).perform(fEnclosingBodyDeclaration); IVariableBinding[] reads = argInfo.get(flowContext, FlowInfo.READ | FlowInfo.READ_POTENTIAL | FlowInfo.UNKNOWN); outer: for (int i = 0; i < returnValues.length && localReads.size() < returnValues.length; i++) { IVariableBinding binding = returnValues[i]; for (int x = 0; x < reads.length; x++) { if (reads[x] == binding) { localReads.add(binding); fReturnValue = binding; continue outer; } } } switch (localReads.size()) { case 0: fReturnValue = null; break; case 1: break; default: fReturnValue = null; StringBuffer affectedLocals = new StringBuffer(); for (int i = 0; i < localReads.size(); i++) { IVariableBinding binding = localReads.get(i); String bindingName = BindingLabelProvider.getBindingLabel( binding, BindingLabelProvider.DEFAULT_TEXTFLAGS | JavaElementLabels.F_PRE_TYPE_SIGNATURE); affectedLocals.append(bindingName); if (i != localReads.size() - 1) { affectedLocals.append('\n'); } } String message = MessageFormat.format( RefactoringCoreMessages.ExtractMethodAnalyzer_assignments_to_local, new Object[] {affectedLocals.toString()}); status.addFatalError(message, JavaStatusContext.create(fCUnit, getSelection())); return; } List<IVariableBinding> callerLocals = new ArrayList<>(5); FlowInfo localInfo = new InputFlowAnalyzer(flowContext, selection, false).perform(fEnclosingBodyDeclaration); IVariableBinding[] writes = localInfo.get(flowContext, FlowInfo.WRITE | FlowInfo.WRITE_POTENTIAL | FlowInfo.UNKNOWN); for (int i = 0; i < writes.length; i++) { IVariableBinding write = writes[i]; if (getSelection().covers(ASTNodes.findDeclaration(write, fEnclosingBodyDeclaration))) callerLocals.add(write); } fCallerLocals = callerLocals.toArray(new IVariableBinding[callerLocals.size()]); if (fReturnValue != null && getSelection().covers(ASTNodes.findDeclaration(fReturnValue, fEnclosingBodyDeclaration))) fReturnLocal = fReturnValue; }
private void initReturnType(ImportRewrite rewriter) { AST ast = fEnclosingBodyDeclaration.getAST(); fReturnType = null; fReturnTypeBinding = null; switch (fReturnKind) { case ACCESS_TO_LOCAL: VariableDeclaration declaration = ASTNodes.findVariableDeclaration(fReturnValue, fEnclosingBodyDeclaration); fReturnType = ASTNodeFactory.newType( ast, declaration, rewriter, new ContextSensitiveImportRewriteContext(declaration, rewriter)); if (declaration.resolveBinding() != null) { fReturnTypeBinding = declaration.resolveBinding().getType(); } break; case EXPRESSION: Expression expression = (Expression) getFirstSelectedNode(); if (expression.getNodeType() == ASTNode.CLASS_INSTANCE_CREATION) { fExpressionBinding = ((ClassInstanceCreation) expression).getType().resolveBinding(); } else { fExpressionBinding = expression.resolveTypeBinding(); } if (fExpressionBinding != null) { if (fExpressionBinding.isNullType()) { getStatus() .addFatalError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_null_type, JavaStatusContext.create(fCUnit, expression)); } else { ITypeBinding normalizedBinding = Bindings.normalizeForDeclarationUse(fExpressionBinding, ast); if (normalizedBinding != null) { ImportRewriteContext context = new ContextSensitiveImportRewriteContext(fEnclosingBodyDeclaration, rewriter); fReturnType = rewriter.addImport(normalizedBinding, ast, context); fReturnTypeBinding = normalizedBinding; } } } else { fReturnType = ast.newPrimitiveType(PrimitiveType.VOID); fReturnTypeBinding = ast.resolveWellKnownType("void"); // $NON-NLS-1$ getStatus() .addError( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_determine_return_type, JavaStatusContext.create(fCUnit, expression)); } break; case RETURN_STATEMENT_VALUE: LambdaExpression enclosingLambdaExpr = ASTResolving.findEnclosingLambdaExpression(getFirstSelectedNode()); if (enclosingLambdaExpr != null) { fReturnType = ASTNodeFactory.newReturnType(enclosingLambdaExpr, ast, rewriter, null); IMethodBinding methodBinding = enclosingLambdaExpr.resolveMethodBinding(); fReturnTypeBinding = methodBinding != null ? methodBinding.getReturnType() : null; } else if (fEnclosingBodyDeclaration.getNodeType() == ASTNode.METHOD_DECLARATION) { fReturnType = ((MethodDeclaration) fEnclosingBodyDeclaration).getReturnType2(); fReturnTypeBinding = fReturnType != null ? fReturnType.resolveBinding() : null; } break; default: fReturnType = ast.newPrimitiveType(PrimitiveType.VOID); fReturnTypeBinding = ast.resolveWellKnownType("void"); // $NON-NLS-1$ } if (fReturnType == null) { fReturnType = ast.newPrimitiveType(PrimitiveType.VOID); fReturnTypeBinding = ast.resolveWellKnownType("void"); // $NON-NLS-1$ } }
private ASTRewrite doAddField(CompilationUnit astRoot) { SimpleName node = fOriginalNode; boolean isInDifferentCU = false; ASTNode newTypeDecl = astRoot.findDeclaringNode(fSenderBinding); if (newTypeDecl == null) { astRoot = ASTResolving.createQuickFixAST(getCompilationUnit(), null); newTypeDecl = astRoot.findDeclaringNode(fSenderBinding.getKey()); isInDifferentCU = true; } ImportRewrite imports = createImportRewrite(astRoot); ImportRewriteContext importRewriteContext = new ContextSensitiveImportRewriteContext( ASTResolving.findParentBodyDeclaration(node), imports); if (newTypeDecl != null) { AST ast = newTypeDecl.getAST(); ASTRewrite rewrite = ASTRewrite.create(ast); VariableDeclarationFragment fragment = ast.newVariableDeclarationFragment(); fragment.setName(ast.newSimpleName(node.getIdentifier())); Type type = evaluateVariableType(ast, imports, importRewriteContext, fSenderBinding); FieldDeclaration newDecl = ast.newFieldDeclaration(fragment); newDecl.setType(type); newDecl .modifiers() .addAll(ASTNodeFactory.newModifiers(ast, evaluateFieldModifiers(newTypeDecl))); if (fSenderBinding.isInterface() || fVariableKind == CONST_FIELD) { fragment.setInitializer(ASTNodeFactory.newDefaultExpression(ast, type, 0)); } ChildListPropertyDescriptor property = ASTNodes.getBodyDeclarationsProperty(newTypeDecl); List<BodyDeclaration> decls = ASTNodes.<BodyDeclaration>getChildListProperty(newTypeDecl, property); int maxOffset = isInDifferentCU ? -1 : node.getStartPosition(); int insertIndex = findFieldInsertIndex(decls, newDecl, maxOffset); ListRewrite listRewriter = rewrite.getListRewrite(newTypeDecl, property); listRewriter.insertAt(newDecl, insertIndex, null); ModifierCorrectionSubProcessor.installLinkedVisibilityProposals( getLinkedProposalModel(), rewrite, newDecl.modifiers(), fSenderBinding.isInterface()); addLinkedPosition(rewrite.track(newDecl.getType()), false, KEY_TYPE); if (!isInDifferentCU) { addLinkedPosition(rewrite.track(node), true, KEY_NAME); } addLinkedPosition(rewrite.track(fragment.getName()), false, KEY_NAME); if (fragment.getInitializer() != null) { addLinkedPosition(rewrite.track(fragment.getInitializer()), false, KEY_INITIALIZER); } return rewrite; } return null; }