@Test public void throw_inside_nested_try_catch_finally() { ControlFlowGraph actualCfg = cfgForBlock("" + "try {" + " try {" + " innerTryBody( succ = [catchBody1], syntSucc = dead );" + " throw $e;" + " dead( succ = [catchBody1, _empty]);" + " } catch (Type $e) {" + " catchBody1( succ = [_empty] );" + " }" + " outerTryBody( succ = [catchBody2, _empty] );" + "} catch (Type $e) {" + " catchBody2( succ = [_empty] );" + "}"); ExpectedCfgStructure expectedCfg = ExpectedCfgStructure.parse(actualCfg.blocks(), expected -> { expected.createEmptyBlockExpectation() .withPredecessorIds("catchBody1", "dead") .withSuccessorsIds("outerTryBody", "_empty"); expected.createEmptyBlockExpectation() .withPredecessorIds("outerTryBody", "catchBody2", "_empty") .withSuccessorsIds("END"); return expected; }); new Validator(expectedCfg).assertCfg(actualCfg); }
public Set<CfgBlock> blocks() { return blocks; }
ControlFlowGraph { public Set<CfgBlock> blocks() { return blocks; } }
ControlFlowGraph { public Set<CfgBlock> blocks() { return blocks; } ControlFlowGraph(ImmutableSet<CfgBlock> blocks, CfgBlock start, PhpCfgEndBlock end); }
ControlFlowGraph { public Set<CfgBlock> blocks() { return blocks; } ControlFlowGraph(ImmutableSet<CfgBlock> blocks, CfgBlock start, PhpCfgEndBlock end); @VisibleForTesting static ControlFlowGraph build(BlockTree body); @CheckForNull static ControlFlowGraph build(Tree tree, CheckContext context); CfgBlock start(); CfgBlock end(); Set<CfgBlock> blocks(); }
ControlFlowGraph { public Set<CfgBlock> blocks() { return blocks; } ControlFlowGraph(ImmutableSet<CfgBlock> blocks, CfgBlock start, PhpCfgEndBlock end); @VisibleForTesting static ControlFlowGraph build(BlockTree body); @CheckForNull static ControlFlowGraph build(Tree tree, CheckContext context); CfgBlock start(); CfgBlock end(); Set<CfgBlock> blocks(); static final Set<Tree.Kind> KINDS_WITH_CONTROL_FLOW; }