/** * Inserts the provided {@code statement} after the the node this inserter was created for. Tries * to put the {@code statement} as close to the {@code marker} as possible. * * @param statement The statement to insert after the insertion node. */ void insertAfter(final Statement statement) { Validate.notNull(statement); Validate.validState( this.insertionList != null, "Insertion is only possible after the inserter has been set up."); Validate.validState( this.insertionList.isPresent(), "Insertion is only possible if setting up the inserter succeeded."); if (this.differentAfterList) { this.afterList.add(0, statement); } else if (this.breakDetector.containsControlFlowBreakingStatement(this.markedStatement)) { // we are trying to insert after a control flow breaking statement. That’s // dangerous, better surround with try…finally final AST factory = this.markedStatement.getAST(); final TryStatement tryStatement = factory.newTryStatement(); tryStatement.setFinally(factory.newBlock()); @SuppressWarnings("unchecked") final List<Statement> tryBodyStatements = tryStatement.getBody().statements(); @SuppressWarnings("unchecked") final List<Statement> finallyStatements = tryStatement.getFinally().statements(); final Statement copy = (Statement) ASTNode.copySubtree(factory, this.markedStatement); tryBodyStatements.add(copy); finallyStatements.add(statement); this.insertionList.get().set(this.markerIndex, tryStatement); this.markedStatement = tryStatement; this.differentAfterList = true; this.afterList = finallyStatements; } else { this.insertionList.get().add(this.markerIndex, statement); } }
@SuppressWarnings("unchecked") public TryStatement newTryCatch(Block tryBlock, CatchClause... clauses) { TryStatement tryStmt = ast.newTryStatement(); tryStmt.setBody(tryBlock); tryStmt.catchClauses().addAll(Arrays.asList(clauses)); return tryStmt; }
@Override public boolean visit(TryStatement node) { final List<Statement> tryStmts = asList(node.getBody()); if (tryStmts.isEmpty()) { final List<Statement> finallyStmts = asList(node.getFinally()); if (!finallyStmts.isEmpty()) { final ASTBuilder b = this.ctx.getASTBuilder(); this.ctx.getRefactorings().replace(node, b.copy(node.getFinally())); return DO_NOT_VISIT_SUBTREE; } else if (node.resources().isEmpty()) { this.ctx.getRefactorings().remove(node); return DO_NOT_VISIT_SUBTREE; } } // }else { // for (CatchClause catchClause : (List<CatchClause>) node.catchClauses()) { // final List<Statement> finallyStmts = asList(catchClause.getBody()); // if (finallyStmts.isEmpty()) { // // TODO cannot remove without checking what subsequent catch clauses are // catching // this.ctx.getRefactorings().remove(catchClause); // } // } // // final List<Statement> finallyStmts = asList(node.getFinally()); // if (finallyStmts.isEmpty()) { // this.ctx.getRefactorings().remove(node.getFinally()); // } // // TODO If all finally and catch clauses have been removed, // // then we can remove the whole try statement and replace it with a simple block // return DO_NOT_VISIT_SUBTREE; // TODO JNR is this correct? // } return VISIT_SUBTREE; }
/* * @see ASTVisitor#visit(TryStatement) */ public boolean visit(TryStatement node) { this.fBuffer.append("try "); // $NON-NLS-1$ node.getBody().accept(this); this.fBuffer.append(" "); // $NON-NLS-1$ for (Iterator it = node.catchClauses().iterator(); it.hasNext(); ) { CatchClause cc = (CatchClause) it.next(); cc.accept(this); } if (node.getFinally() != null) { this.fBuffer.append("finally "); // $NON-NLS-1$ node.getFinally().accept(this); } return false; }
/* * @see ASTVisitor#visit(TryStatement) */ @Override public boolean visit(TryStatement node) { this.fBuffer.append("try "); // $NON-NLS-1$ if (node.getAST().apiLevel() >= JLS4) { if (!node.resources().isEmpty()) { this.fBuffer.append("("); // $NON-NLS-1$ for (Iterator<VariableDeclarationExpression> it = node.resources().iterator(); it.hasNext(); ) { VariableDeclarationExpression var = it.next(); var.accept(this); if (it.hasNext()) { this.fBuffer.append(","); // $NON-NLS-1$ } } this.fBuffer.append(") "); // $NON-NLS-1$ } } node.getBody().accept(this); this.fBuffer.append(" "); // $NON-NLS-1$ for (Iterator<CatchClause> it = node.catchClauses().iterator(); it.hasNext(); ) { CatchClause cc = it.next(); cc.accept(this); } if (node.getFinally() != null) { this.fBuffer.append("finally "); // $NON-NLS-1$ node.getFinally().accept(this); } return false; }
@Override public void indexTryCatchBlock( final Document document, final TryStatement tryStatement, final CatchClause catchClause) { final ASTVisitor visitor = new MethodCallVisitor() { @Override protected void handleMethodCall(final IMethodBinding methodBinding) { final Optional<String> opt = BindingHelper.getIdentifier(methodBinding); if (opt.isPresent()) { CodeIndexer.addFieldToDocument(document, Fields.USED_METHODS_IN_FINALLY, opt.get()); } }; }; if (tryStatement.getFinally() != null) { tryStatement.getFinally().accept(visitor); } }
@Test public void testIsThrowStatementInCatchClause() { TryStatement tryStatement; CatchClause catchStatement; // 測試 符合的例子 是否會抓出 MethodDeclaration md = null; md = ASTNodeFinder.getMethodDeclarationNodeByName(compilationUnit, "false_throwAndPrint"); tryStatement = (TryStatement) md.getBody().statements().get(0); catchStatement = (CatchClause) tryStatement.catchClauses().get(0); assertTrue(dummyHandlerVisitor.isThrowStatementInCatchClause(catchStatement)); // 測試 不符合例子 是否會抓出 md = ASTNodeFinder.getMethodDeclarationNodeByName( compilationUnit, "true_DummyHandlerTryNestedTry"); tryStatement = (TryStatement) md.getBody().statements().get(1); catchStatement = (CatchClause) tryStatement.catchClauses().get(0); assertFalse(dummyHandlerVisitor.isThrowStatementInCatchClause(catchStatement)); }
@Override public boolean visit(EmptyStatement node) { ASTNode parent = node.getParent(); if (parent instanceof Block) { this.ctx.getRefactorings().remove(node); return DO_NOT_VISIT_SUBTREE; } parent = getParentIgnoring(node, Block.class); if (parent instanceof IfStatement) { IfStatement is = (IfStatement) parent; List<Statement> thenStmts = asList(is.getThenStatement()); List<Statement> elseStmts = asList(is.getElseStatement()); boolean thenIsEmptyStmt = thenStmts.size() == 1 && is(thenStmts.get(0), EmptyStatement.class); boolean elseIsEmptyStmt = elseStmts.size() == 1 && is(elseStmts.get(0), EmptyStatement.class); if (thenIsEmptyStmt && elseIsEmptyStmt) { this.ctx.getRefactorings().remove(parent); return DO_NOT_VISIT_SUBTREE; } else if (thenIsEmptyStmt && is.getElseStatement() == null) { this.ctx.getRefactorings().remove(is); return DO_NOT_VISIT_SUBTREE; } else if (elseIsEmptyStmt) { this.ctx.getRefactorings().remove(is.getElseStatement()); return DO_NOT_VISIT_SUBTREE; } } else if (parent instanceof TryStatement) { TryStatement ts = (TryStatement) parent; return removeEmptyStmtBody(node, ts, ts.getBody()); } else if (parent instanceof EnhancedForStatement) { EnhancedForStatement efs = (EnhancedForStatement) parent; return removeEmptyStmtBody(node, efs, efs.getBody()); } else if (parent instanceof ForStatement) { ForStatement fs = (ForStatement) parent; return removeEmptyStmtBody(node, fs, fs.getBody()); } else if (parent instanceof WhileStatement) { WhileStatement ws = (WhileStatement) parent; return removeEmptyStmtBody(node, ws, ws.getBody()); } return VISIT_SUBTREE; }
/* (omit javadoc for this method) * Method declared on ASTNode. */ ASTNode clone0(AST target) { TryStatement result = new TryStatement(target); result.setSourceRange(this.getStartPosition(), this.getLength()); result.copyLeadingComment(this); result.setBody((Block) getBody().clone(target)); result.catchClauses().addAll(ASTNode.copySubtrees(target, catchClauses())); result.setFinally((Block) ASTNode.copySubtree(target, getFinally())); return result; }
/** * Builds a new {@link TryStatement} instance. * * @param body the try body * @param catchClauses the catch clauses for the try * @return a new try statement */ public TryStatement try0(final Block body, CatchClause... catchClauses) { final TryStatement tryS = ast.newTryStatement(); tryS.setBody(body); addAll(catchClauses(tryS), catchClauses); return tryS; }
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); } }