@Override public void visitTryStatement(TryStatementTree tree) { super.visitTryStatement(tree); checkBlock(tree.block(), tree.tryToken()); if (tree.finallyToken() != null) { checkBlock(tree.finallyBlock(), tree.finallyToken()); } }
private PhpCfgBlock buildTryStatement(TryStatementTree tree, PhpCfgBlock successor) { PhpCfgBlock exitBlock = exitTargets.peek().exitBlock; PhpCfgBlock finallyBlockEnd = createMultiSuccessorBlock(ImmutableSet.of(successor, exitBlock)); PhpCfgBlock finallyBlock; if (tree.finallyBlock() != null) { finallyBlock = build(tree.finallyBlock().statements(), finallyBlockEnd); } else { finallyBlock = finallyBlockEnd; } List<PhpCfgBlock> catchBlocks = tree.catchBlocks().stream() .map(catchBlockTree -> buildSubFlow(catchBlockTree.block().statements(), finallyBlock)) .collect(Collectors.toList()); if (catchBlocks.isEmpty()) { throwTargets.push(finallyBlock); } else { throwTargets.push(catchBlocks.get(0)); } Set<PhpCfgBlock> bodySuccessors = new HashSet<>(catchBlocks); bodySuccessors.add(finallyBlock); PhpCfgBlock tryBodySuccessors = createMultiSuccessorBlock(bodySuccessors); addBreakable(tryBodySuccessors, tryBodySuccessors); exitTargets.push(new TryBodyEnd(tryBodySuccessors, finallyBlock)); PhpCfgBlock tryBodyStartingBlock = build(tree.block().statements(), tryBodySuccessors); throwTargets.pop(); exitTargets.pop(); removeBreakable(); return tryBodyStartingBlock; }
@Override public void visitTryStatement(TryStatementTree tree) { List<CatchBlockTree> catchBlocks = tree.catchBlocks(); if (catchBlocks.stream().allMatch(catchBlock -> hasSingleStatement(catchBlock) && isRetrowingException(catchBlock))) { catchBlocks.stream() .flatMap(catchBlock -> catchBlock.block().statements().stream()) .forEach(statement -> context().newIssue(this, statement, "Add logic to this catch clause or eliminate it and rethrow the exception automatically.")); } super.visitTryStatement(tree); }
private void checkSpaceBetweenKeywordAndNextNode(TokenVisitor tokenVisitor, Tree tree) { SyntaxToken keyword = tokenVisitor.firstKeyword(); if (tree.is(Kind.TRY_STATEMENT)) { TryStatementTree tryStatement = (TryStatementTree) tree; if (tryStatement.finallyToken() != null) { SyntaxToken finallyKeyword = tryStatement.finallyToken(); checkSpaceBetweenKeywordAndNextNode(finallyKeyword, tokenVisitor.nextToken(finallyKeyword)); } } checkSpaceBetweenKeywordAndNextNode(keyword, tokenVisitor.nextToken(keyword)); }
@Override public void visitTryStatement(TryStatementTree tree) { enterBlock(tree.tryToken()); super.visitTryStatement(tree); leaveBlock(); }
private PhpCfgBlock buildTryStatement(TryStatementTree tree, PhpCfgBlock successor) { PhpCfgBlock exitBlock = exitTargets.peek().exitBlock; PhpCfgBlock finallyBlockEnd = createMultiSuccessorBlock(ImmutableSet.of(successor, exitBlock)); PhpCfgBlock finallyBlock; if (tree.finallyBlock() != null) { finallyBlock = build(tree.finallyBlock().statements(), finallyBlockEnd); } else { finallyBlock = finallyBlockEnd; } List<PhpCfgBlock> catchBlocks = tree.catchBlocks().stream() .map(catchBlockTree -> buildSubFlow(catchBlockTree.block().statements(), finallyBlock)) .collect(Collectors.toList()); if (catchBlocks.isEmpty()) { throwTargets.push(finallyBlock); } else { throwTargets.push(catchBlocks.get(0)); } Set<PhpCfgBlock> bodySuccessors = new HashSet<>(catchBlocks); bodySuccessors.add(finallyBlock); PhpCfgBlock tryBodySuccessors = createMultiSuccessorBlock(bodySuccessors); addBreakable(tryBodySuccessors, tryBodySuccessors); exitTargets.push(new TryBodyEnd(tryBodySuccessors, finallyBlock)); PhpCfgBlock tryBodyStartingBlock = build(tree.block().statements(), tryBodySuccessors); throwTargets.pop(); exitTargets.pop(); removeBreakable(); return tryBodyStartingBlock; }
@Override public void visitTryStatement(TryStatementTree tree) { List<CatchBlockTree> catchBlocks = tree.catchBlocks(); if (catchBlocks.stream().allMatch(catchBlock -> hasSingleStatement(catchBlock) && isRetrowingException(catchBlock))) { catchBlocks.stream() .flatMap(catchBlock -> catchBlock.block().statements().stream()) .forEach(statement -> context().newIssue(this, statement, "Add logic to this catch clause or eliminate it and rethrow the exception automatically.")); } super.visitTryStatement(tree); }
private void checkSpaceBetweenKeywordAndNextNode(TokenVisitor tokenVisitor, Tree tree) { SyntaxToken keyword = tokenVisitor.firstKeyword(); if (tree.is(Kind.TRY_STATEMENT)) { TryStatementTree tryStatement = (TryStatementTree) tree; if (tryStatement.finallyToken() != null) { SyntaxToken finallyKeyword = tryStatement.finallyToken(); checkSpaceBetweenKeywordAndNextNode(finallyKeyword, tokenVisitor.nextToken(finallyKeyword)); } } checkSpaceBetweenKeywordAndNextNode(keyword, tokenVisitor.nextToken(keyword)); }
@Override public void visitTryStatement(TryStatementTree tree) { enterBlock(tree.tryToken()); super.visitTryStatement(tree); leaveBlock(); }
@Override public void visitTryStatement(TryStatementTree tree) { super.visitTryStatement(tree); checkBlock(tree.block(), tree.tryToken()); if (tree.finallyToken() != null) { checkBlock(tree.finallyBlock(), tree.finallyToken()); } }
@Override public void visitTryStatement(TryStatementTree tree) { super.visitTryStatement(tree); checkBlock(tree.block(), tree.tryToken()); if (tree.finallyToken() != null) { checkBlock(tree.finallyBlock(), tree.finallyToken()); } }
@Override public void visitTryStatement(TryStatementTree tree) { super.visitTryStatement(tree); checkBlock(tree.block(), tree.tryToken()); if (tree.finallyToken() != null) { checkBlock(tree.finallyBlock(), tree.finallyToken()); } }
@Override public void visitTryStatement(TryStatementTree tree) { checkControlStructureOpenCurly(tree.tryToken(), tree.block().openCurlyBraceToken()); TokenVisitor tokenVisitor = new TokenVisitor(tree); // Check catch keyword for (CatchBlockTree catchBlock : tree.catchBlocks()) { checkCloseCurlyNextToKeyword(tokenVisitor.prevToken(catchBlock.catchToken()), catchBlock.catchToken()); } // Check finally keyword if (tree.finallyBlock() != null) { checkCloseCurlyNextToKeyword(tokenVisitor.prevToken(tree.finallyToken()), tree.finallyToken()); } super.visitTryStatement(tree); }
@Override public void visitTryStatement(TryStatementTree tree) { checkControlStructureOpenCurly(tree.tryToken(), tree.block().openCurlyBraceToken()); TokenVisitor tokenVisitor = new TokenVisitor(tree); // Check catch keyword for (CatchBlockTree catchBlock : tree.catchBlocks()) { checkCloseCurlyNextToKeyword(tokenVisitor.prevToken(catchBlock.catchToken()), catchBlock.catchToken()); } // Check finally keyword if (tree.finallyBlock() != null) { checkCloseCurlyNextToKeyword(tokenVisitor.prevToken(tree.finallyToken()), tree.finallyToken()); } super.visitTryStatement(tree); }
@Test public void test_finally_block() throws Exception { TryStatementTree tree = parse("try {} finally {}", PHPLexicalGrammar.TRY_STATEMENT); assertThat(tree.is(Kind.TRY_STATEMENT)).isTrue(); assertThat(tree.tryToken().text()).isEqualTo("try"); assertThat(expressionToString(tree.block())).isEqualTo("{}"); assertThat(tree.catchBlocks()).hasSize(0); assertThat(tree.finallyToken().text()).isEqualTo("finally"); assertThat(expressionToString(tree.finallyBlock())).isEqualTo("{}"); }
@Test public void test_2_catch_blocks() throws Exception { TryStatementTree tree = parse("try {} catch(Exception1 $e1) {} catch(Exception2 $e2) {}", PHPLexicalGrammar.TRY_STATEMENT); assertThat(tree.is(Kind.TRY_STATEMENT)).isTrue(); assertThat(tree.tryToken().text()).isEqualTo("try"); assertThat(expressionToString(tree.block())).isEqualTo("{}"); assertThat(tree.catchBlocks()).hasSize(2); assertThat(tree.finallyToken()).isNull(); assertThat(tree.finallyBlock()).isNull(); }