public function serialize(ControlFlowGraph $graph)
 {
     $dot = "digraph G {\n";
     $this->ids = new \SplObjectStorage();
     $this->idCount = 0;
     $dot .= "    " . $this->getId($graph->getImplicitReturn()) . " [shape=box,label=\"implicit return\",style=filled]\n";
     $entryPoint = $graph->getEntryPoint();
     $nodes = $graph->getNodes();
     foreach ($nodes as $astNode) {
         $node = $nodes[$astNode];
         $id = $this->getId($node);
         $dot .= sprintf('    %s [shape=box,label="%s"', $id, str_replace('"', '\\"', NodeUtil::getStringRepr($astNode)));
         if ($node === $entryPoint) {
             $dot .= ",style=filled";
         }
         $dot .= "]\n";
         foreach ($node->getOutEdges() as $edge) {
             $dot .= sprintf("    %s -> %s", $id, $this->getId($edge->getDest()));
             switch ($edge->getType()) {
                 case GraphEdge::TYPE_ON_FALSE:
                     $dot .= ' [label="false"]';
                     break;
                 case GraphEdge::TYPE_ON_TRUE:
                     $dot .= ' [label="true"]';
                     break;
                 case GraphEdge::TYPE_ON_EX:
                     $dot .= ' [label="exception"]';
                     break;
             }
             $dot .= "\n";
         }
     }
     $dot .= "}";
     return $dot;
 }
 private function tryRemoveDeadAssignments(NodeTraversal $t, ControlFlowGraph $cfg)
 {
     $nodes = $cfg->getDirectedGraphNodes();
     foreach ($nodes as $cfgNode) {
         $inState = $cfgNode->getAttribute(DataFlowAnalysis::ATTR_FLOW_STATE_IN);
         $outState = $cfgNode->getAttribute(DataFlowAnalysis::ATTR_FLOW_STATE_OUT);
         $n = $cfgNode->getAstNode();
         if (null === $n) {
             continue;
         }
         switch (true) {
             case $n instanceof \PHPParser_Node_Stmt_If:
             case $n instanceof \PHPParser_Node_Stmt_ElseIf:
             case $n instanceof \PHPParser_Node_Stmt_While:
             case $n instanceof \PHPParser_Node_Stmt_Do:
             case $n instanceof \PHPParser_Node_Stmt_For:
             case $n instanceof \PHPParser_Node_Stmt_Switch:
             case $n instanceof \PHPParser_Node_Stmt_Case:
                 if (null !== ($condition = NodeUtil::getConditionExpression($n))) {
                     $this->tryRemoveAssignment($t, $condition, null, $inState, $outState);
                 }
                 continue 2;
             case $n instanceof \PHPParser_Node_Stmt_Return:
                 if (null !== $n->expr) {
                     $this->tryRemoveAssignment($t, $n->expr, null, $inState, $outState);
                 }
                 continue 2;
         }
         $this->tryRemoveAssignment($t, $n, null, $inState, $outState);
     }
 }
 private function connectToPossibleExceptionHandler(\PHPParser_Node $cfgNode, \PHPParser_Node $target)
 {
     if (!self::mayThrowException($target)) {
         return;
     }
     if ($this->exceptionHandlers->isEmpty()) {
         return;
     }
     foreach ($this->exceptionHandlers as $handler) {
         assert($handler instanceof \PHPParser_Node_Stmt_TryCatch);
         $catches = $handler->catches;
         $this->graph->connectIfNotConnected($cfgNode, GraphEdge::TYPE_ON_EX, $catches[0]);
         break;
     }
 }
 public function testComputeFixedPoint()
 {
     $graph = new ControlFlowGraph($entry = $this->getAstNode());
     $node1 = $this->getAstNode();
     $graph->connect($entry, null, $node1);
     $node2 = $this->getAstNode();
     $graph->connect($node1, null, $node2);
     $node3 = $this->getAstNode();
     $graph->connect($node3, null, $node2);
     $node4 = $this->getAstNode();
     $graph->connect($node2, null, $node4);
     $callback = $this->getMock('Scrutinizer\\PhpAnalyzer\\ControlFlow\\EdgeCallbackInterface');
     $t = new FixedPointGraphTraversal($callback);
     $callback->expects($this->at(0))->method('traverseEdge')->with($entry, null, $node1)->will($this->returnValue(true));
     $callback->expects($this->at(1))->method('traverseEdge')->with($node1, null, $node2)->will($this->returnValue(false));
     $t->computeFixedPointWithEntry($graph, $entry);
 }
 public function testBranchedSimpleIf()
 {
     // if (a) { a = 0; } else { b = 0; } c = b;
     $a = new Variable('a');
     $b = new Variable('b');
     $c = new Variable('c');
     $inst1 = new BranchInstruction($a);
     $inst2 = ArithmeticInstruction::newAssignNumberToVariableInstruction($a, 0);
     $inst3 = ArithmeticInstruction::newAssignNumberToVariableInstruction($b, 0);
     $inst4 = ArithmeticInstruction::newAssignVariableToVariableInstruction($c, $b);
     $cfg = new ControlFlowGraph($inst1);
     $cfg->connectIfNotConnected($inst1, GraphEdge::TYPE_ON_TRUE, $inst2);
     $cfg->connectIfNotConnected($inst1, GraphEdge::TYPE_ON_FALSE, $inst3);
     $cfg->connectIfNotConnected($inst2, GraphEdge::TYPE_UNCOND, $inst4);
     $cfg->connectIfNotConnected($inst3, GraphEdge::TYPE_UNCOND, $inst4);
     $n1 = $cfg->getNode($inst1);
     $n2 = $cfg->getNode($inst2);
     $n3 = $cfg->getNode($inst3);
     $n4 = $cfg->getNode($inst4);
     $constProp = new BranchedDummyConstPropagation($cfg);
     $constProp->analyze();
     // We cannot conclude anything from if(a).
     $this->verifyInHas($n1, $a, null);
     $this->verifyInHas($n1, $b, null);
     $this->verifyInHas($n1, $c, null);
     // Nothing is known on the true branch.
     $this->verifyInHas($n2, $a, null);
     $this->verifyInHas($n2, $b, null);
     $this->verifyInHas($n2, $c, null);
     // Verify that we have a = 0 on the false branch.
     $this->verifyInHas($n3, $a, 0);
     $this->verifyInHas($n3, $b, null);
     $this->verifyInHas($n3, $c, null);
     // After the merge we should still have a = 0.
     $this->verifyInHas($n4, $a, 0);
 }