private boolean nodesHaveSameParentAndLocation(List<? extends ASTNode> nodes) { if (nodes.isEmpty()) { return true; } final ASTNode firstNode = nodes.get(0); final ASTNode parent = firstNode.getParent(); final StructuralPropertyDescriptor locInParent = firstNode.getLocationInParent(); for (ASTNode node : nodes) { if (!equal(node.getParent(), parent) || !equal(node.getLocationInParent(), locInParent)) { return false; } } 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); }
/** * Replace an AST node with another one by substituting the corresponding child of its parent. * * @param node The node to be replace. * @param newNode The new node. */ public static void replaceNode(ASTNode node, ASTNode newNode) { ASTNode parent = node.getParent(); StructuralPropertyDescriptor location = node.getLocationInParent(); if (location.isChildProperty()) { parent.setStructuralProperty(location, newNode); } else { List<ASTNode> properties = (List<ASTNode>) parent.getStructuralProperty(location); int position = properties.indexOf(node); properties.set(position, newNode); } }
private static ASTNode getDeclaringNode(ASTNode selectedNode) { ASTNode declaringNode = null; if (selectedNode instanceof MethodDeclaration) { declaringNode = selectedNode; } else if (selectedNode instanceof SimpleName) { StructuralPropertyDescriptor locationInParent = selectedNode.getLocationInParent(); if (locationInParent == MethodDeclaration.NAME_PROPERTY || locationInParent == TypeDeclaration.NAME_PROPERTY) { declaringNode = selectedNode.getParent(); } else if (locationInParent == VariableDeclarationFragment.NAME_PROPERTY) { declaringNode = selectedNode.getParent().getParent(); } } return declaringNode; }
private boolean validSelectedNodes() { ASTNode[] nodes = getSelectedNodes(); for (int i = 0; i < nodes.length; i++) { ASTNode node = nodes[i]; boolean isValidNode = node instanceof Statement; if (fSurroundWithTryCatch) { // allow method reference and lambda's expression body also isValidNode = isValidNode || node instanceof MethodReference || node.getLocationInParent() == LambdaExpression.BODY_PROPERTY; } if (!isValidNode) return false; } return true; }
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 void insertMissingJavadocTag( ASTRewrite rewrite, ASTNode missingNode, BodyDeclaration bodyDecl) { AST ast = bodyDecl.getAST(); Javadoc javadoc = bodyDecl.getJavadoc(); if (javadoc == null) { javadoc = ast.newJavadoc(); rewrite.set(bodyDecl, bodyDecl.getJavadocProperty(), javadoc, null); } ListRewrite tagsRewriter = rewrite.getListRewrite(javadoc, Javadoc.TAGS_PROPERTY); StructuralPropertyDescriptor location = missingNode.getLocationInParent(); TagElement newTag; if (location == SingleVariableDeclaration.NAME_PROPERTY) { // normal parameter SingleVariableDeclaration decl = (SingleVariableDeclaration) missingNode.getParent(); String name = ((SimpleName) missingNode).getIdentifier(); newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_PARAM); newTag.fragments().add(ast.newSimpleName(name)); MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDecl; List<SingleVariableDeclaration> params = methodDeclaration.parameters(); Set<String> sameKindLeadingNames = getPreviousParamNames(params, decl); List<TypeParameter> typeParams = methodDeclaration.typeParameters(); for (int i = 0; i < typeParams.size(); i++) { String curr = '<' + typeParams.get(i).getName().getIdentifier() + '>'; sameKindLeadingNames.add(curr); } insertTag(tagsRewriter, newTag, sameKindLeadingNames); } else if (location == TypeParameter.NAME_PROPERTY) { // type parameter TypeParameter typeParam = (TypeParameter) missingNode.getParent(); String name = '<' + ((SimpleName) missingNode).getIdentifier() + '>'; newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_PARAM); TextElement text = ast.newTextElement(); text.setText(name); newTag.fragments().add(text); List<TypeParameter> params; if (bodyDecl instanceof TypeDeclaration) { params = ((TypeDeclaration) bodyDecl).typeParameters(); } else { params = ((MethodDeclaration) bodyDecl).typeParameters(); } insertTag(tagsRewriter, newTag, getPreviousTypeParamNames(params, typeParam)); } else if (location == MethodDeclaration.RETURN_TYPE2_PROPERTY) { newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_RETURN); insertTag(tagsRewriter, newTag, null); } else if (location == MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY) { newTag = ast.newTagElement(); newTag.setTagName(TagElement.TAG_THROWS); TextElement excNode = ast.newTextElement(); excNode.setText(ASTNodes.getQualifiedTypeName((Type) missingNode)); newTag.fragments().add(excNode); List<Type> exceptions = ((MethodDeclaration) bodyDecl).thrownExceptionTypes(); insertTag(tagsRewriter, newTag, getPreviousExceptionNames(exceptions, missingNode)); } else { Assert.isTrue( false, "AddMissingJavadocTagProposal: unexpected node location"); // $NON-NLS-1$ return; } TextElement textElement = ast.newTextElement(); textElement.setText(""); // $NON-NLS-1$ newTag.fragments().add(textElement); addLinkedPosition(rewrite.track(textElement), false, "comment_start"); // $NON-NLS-1$ if (bodyDecl.getJavadoc() == null) { // otherwise the linked position spans over a line delimiter newTag.fragments().add(ast.newTextElement()); } }
private void createTryCatchStatement(org.eclipse.jdt.core.IBuffer buffer, String lineDelimiter) throws CoreException { List<Statement> result = new ArrayList<>(1); TryStatement tryStatement = getAST().newTryStatement(); ITypeBinding[] exceptions = fAnalyzer.getExceptions(); ImportRewriteContext context = new ContextSensitiveImportRewriteContext( fAnalyzer.getEnclosingBodyDeclaration(), fImportRewrite); if (!fIsMultiCatch) { for (int i = 0; i < exceptions.length; i++) { ITypeBinding exception = exceptions[i]; CatchClause catchClause = getAST().newCatchClause(); tryStatement.catchClauses().add(catchClause); SingleVariableDeclaration decl = getAST().newSingleVariableDeclaration(); String varName = StubUtility.getExceptionVariableName(fCUnit.getJavaProject()); String name = fScope.createName(varName, false); decl.setName(getAST().newSimpleName(name)); Type type = fImportRewrite.addImport(exception, getAST(), context); decl.setType(type); catchClause.setException(decl); Statement st = getCatchBody(ASTNodes.getQualifiedTypeName(type), name, lineDelimiter); if (st != null) { catchClause.getBody().statements().add(st); } fLinkedProposalModel .getPositionGroup(GROUP_EXC_TYPE + i, true) .addPosition(fRewriter.track(decl.getType()), i == 0); fLinkedProposalModel .getPositionGroup(GROUP_EXC_NAME + i, true) .addPosition(fRewriter.track(decl.getName()), false); } } else { List<ITypeBinding> filteredExceptions = filterSubtypeExceptions(exceptions); CatchClause catchClause = getAST().newCatchClause(); SingleVariableDeclaration decl = getAST().newSingleVariableDeclaration(); String varName = StubUtility.getExceptionVariableName(fCUnit.getJavaProject()); String name = fScope.createName(varName, false); decl.setName(getAST().newSimpleName(name)); UnionType unionType = getAST().newUnionType(); List<Type> types = unionType.types(); int i = 0; for (ITypeBinding exception : filteredExceptions) { Type type = fImportRewrite.addImport(exception, getAST(), context); types.add(type); fLinkedProposalModel .getPositionGroup(GROUP_EXC_TYPE + i, true) .addPosition(fRewriter.track(type), i == 0); i++; } decl.setType(unionType); catchClause.setException(decl); fLinkedProposalModel .getPositionGroup(GROUP_EXC_NAME + 0, true) .addPosition(fRewriter.track(decl.getName()), false); Statement st = getCatchBody("Exception", name, lineDelimiter); // $NON-NLS-1$ if (st != null) { catchClause.getBody().statements().add(st); } tryStatement.catchClauses().add(catchClause); } List<ASTNode> variableDeclarations = getSpecialVariableDeclarationStatements(); ListRewrite statements = fRewriter.getListRewrite(tryStatement.getBody(), Block.STATEMENTS_PROPERTY); boolean selectedNodeRemoved = false; ASTNode expressionStatement = null; for (int i = 0; i < fSelectedNodes.length; i++) { ASTNode node = fSelectedNodes[i]; if (node instanceof VariableDeclarationStatement && variableDeclarations.contains(node)) { AST ast = getAST(); VariableDeclarationStatement statement = (VariableDeclarationStatement) node; // Create a copy and remove the initializer VariableDeclarationStatement copy = (VariableDeclarationStatement) ASTNode.copySubtree(ast, statement); List<IExtendedModifier> modifiers = copy.modifiers(); for (Iterator<IExtendedModifier> iter = modifiers.iterator(); iter.hasNext(); ) { IExtendedModifier modifier = iter.next(); if (modifier.isModifier() && Modifier.isFinal(((Modifier) modifier).getKeyword().toFlagValue())) { iter.remove(); } } List<VariableDeclarationFragment> fragments = copy.fragments(); for (Iterator<VariableDeclarationFragment> iter = fragments.iterator(); iter.hasNext(); ) { VariableDeclarationFragment fragment = iter.next(); fragment.setInitializer(null); } CompilationUnit root = (CompilationUnit) statement.getRoot(); int extendedStart = root.getExtendedStartPosition(statement); // we have a leading comment and the comment is covered by the selection if (extendedStart != statement.getStartPosition() && extendedStart >= fSelection.getOffset()) { String commentToken = buffer.getText(extendedStart, statement.getStartPosition() - extendedStart); commentToken = Strings.trimTrailingTabsAndSpaces(commentToken); Type type = statement.getType(); String typeName = buffer.getText(type.getStartPosition(), type.getLength()); copy.setType( (Type) fRewriter.createStringPlaceholder(commentToken + typeName, type.getNodeType())); } result.add(copy); // convert the fragments into expression statements fragments = statement.fragments(); if (!fragments.isEmpty()) { List<ExpressionStatement> newExpressionStatements = new ArrayList<>(); for (Iterator<VariableDeclarationFragment> iter = fragments.iterator(); iter.hasNext(); ) { VariableDeclarationFragment fragment = iter.next(); Expression initializer = fragment.getInitializer(); if (initializer != null) { Assignment assignment = ast.newAssignment(); assignment.setLeftHandSide( (Expression) fRewriter.createCopyTarget(fragment.getName())); assignment.setRightHandSide((Expression) fRewriter.createCopyTarget(initializer)); newExpressionStatements.add(ast.newExpressionStatement(assignment)); } } if (!newExpressionStatements.isEmpty()) { if (fSelectedNodes.length == 1) { expressionStatement = fRewriter.createGroupNode( newExpressionStatements.toArray(new ASTNode[newExpressionStatements.size()])); } else { fRewriter.replace( statement, fRewriter.createGroupNode( newExpressionStatements.toArray(new ASTNode[newExpressionStatements.size()])), null); } } else { fRewriter.remove(statement, null); selectedNodeRemoved = true; } } else { fRewriter.remove(statement, null); selectedNodeRemoved = true; } } } result.add(tryStatement); ASTNode replacementNode; if (result.size() == 1) { replacementNode = result.get(0); } else { replacementNode = fRewriter.createGroupNode(result.toArray(new ASTNode[result.size()])); } if (fSelectedNodes.length == 1) { ASTNode selectedNode = fSelectedNodes[0]; if (selectedNode instanceof MethodReference) { MethodReference methodReference = (MethodReference) selectedNode; IMethodBinding functionalMethod = QuickAssistProcessor.getFunctionalMethodForMethodReference(methodReference); // functionalMethod is non-null and non-generic. See // ExceptionAnalyzer.handleMethodReference(MethodReference node). Assert.isTrue(functionalMethod != null && !functionalMethod.isGenericMethod()); LambdaExpression lambda = QuickAssistProcessor.convertMethodRefernceToLambda( methodReference, functionalMethod, fRootNode, fRewriter, null, true); ASTNode statementInBlock = (ASTNode) ((Block) lambda.getBody()).statements().get(0); fRewriter.replace(statementInBlock, replacementNode, null); statements.insertLast(statementInBlock, null); return; } LambdaExpression enclosingLambda = ASTResolving.findEnclosingLambdaExpression(selectedNode); if (enclosingLambda != null && selectedNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY && enclosingLambda.resolveMethodBinding() != null) { QuickAssistProcessor.changeLambdaBodyToBlock(enclosingLambda, getAST(), fRewriter); Block blockBody = (Block) fRewriter.get(enclosingLambda, LambdaExpression.BODY_PROPERTY); ASTNode statementInBlock = (ASTNode) blockBody.statements().get(0); fRewriter.replace(statementInBlock, replacementNode, null); statements.insertLast(statementInBlock, null); return; } if (expressionStatement != null) { statements.insertLast(expressionStatement, null); } else { if (!selectedNodeRemoved) statements.insertLast(fRewriter.createMoveTarget(selectedNode), null); } fRewriter.replace(selectedNode, replacementNode, null); } else { ListRewrite source = fRewriter.getListRewrite( fSelectedNodes[0].getParent(), (ChildListPropertyDescriptor) fSelectedNodes[0].getLocationInParent()); ASTNode toMove = source.createMoveTarget( fSelectedNodes[0], fSelectedNodes[fSelectedNodes.length - 1], replacementNode, null); statements.insertLast(toMove, null); } }