public function enterScope(NodeTraversal $traversal)
 {
     $typeInference = new TypeInference($traversal->getControlFlowGraph(), $this->reverseInterpreter, $this->functionInterpreter, $this->methodInterpreter, $this->commentParser, $traversal->getScope(), $this->registry, $this->logger);
     try {
         $typeInference->analyze();
     } catch (MaxIterationsExceededException $ex) {
         $scopeRoot = $traversal->getScopeRoot();
         $this->logger->warning($ex->getMessage() . ' - Scope-Root: ' . get_class($scopeRoot) . ' on line ' . $scopeRoot->getLine() . ' in ' . $this->file->getName());
     }
 }
 /**
  * Declares a refined type in {@code scope} for the name represented by
  * {@code node}. It must be possible to refine the type of the given node in
  * the given scope, as determined by {@link #getTypeIfRefinable}.
  */
 protected function declareNameInScope(LinkedFlowScope $scope, \PHPParser_Node $node, PhpType $type)
 {
     switch (true) {
         case $node instanceof \PHPParser_Node_Expr_Variable:
             if (is_string($node->name)) {
                 $scope->inferSlotType($node->name, $type);
             }
             break;
         case $node instanceof \PHPParser_Node_Expr_StaticPropertyFetch:
         case $node instanceof \PHPParser_Node_Expr_PropertyFetch:
             if (null !== ($qualifiedName = TypeInference::getQualifiedName($node))) {
                 $origType = $node->getAttribute('type') ?: $this->typeRegistry->getNativeType('unknown');
                 $scope->inferQualifiedSlot($node, $qualifiedName, $origType, $type);
             }
             break;
             // Something like: if (is_array($functions = getFunctionNames())) { }
         // Something like: if (is_array($functions = getFunctionNames())) { }
         case $node instanceof \PHPParser_Node_Expr_Assign:
         case $node instanceof \PHPParser_Node_Expr_AssignRef:
             $this->declareNameInScope($scope, $node->var, $type);
             break;
         case $node instanceof \PHPParser_Node_Expr_ArrayDimFetch:
             $dim = \Scrutinizer\PhpAnalyzer\PhpParser\NodeUtil::getValue($node->dim);
             if ($dim->isDefined() && null !== ($slotType = $node->var->getAttribute('type')) && $slotType->isArrayType()) {
                 $newSlotType = $slotType->inferItemType($dim->get(), $type);
                 $this->declareNameInScope($scope, $node->var, $newSlotType);
             }
             break;
     }
 }
 private function join(FlowScopeInterface $a, FlowScopeInterface $b)
 {
     return call_user_func(TypeInference::createJoinOperation(), array($a, $b));
 }
 private function inMethod($phpCode)
 {
     // Parse the body of the function.
     $ast = $this->parser->parse(new \PHPParser_Lexer('<?php class Foo { function foo() {' . $phpCode . '} }'));
     // Normalize the AST.
     $traverser = new \PHPParser_NodeTraverser();
     $traverser->addVisitor(new \PHPParser_NodeVisitor_NameResolver());
     $traverser->addvisitor(new NormalizingNodeVisitor());
     $ast = $traverser->traverse($ast);
     $traverser = new \PHPParser_NodeTraverser();
     $traverser->addVisitor(new \PHPParser_NodeVisitor_NodeConnector());
     $traverser->traverse($ast);
     $root = $ast[0];
     $node = $root->stmts[0]->stmts;
     // Create the scope with the assumptions.
     $scopeCreator = new TypedScopeCreator($this->registry);
     $assumedScope = $scopeCreator->createScope($node, $scopeCreator->createScope($root, null));
     foreach ($this->assumptions as $symbolName => $type) {
         $var = $assumedScope->getVar($symbolName);
         if (!$var) {
             $assumedScope->declareVar($symbolName, $type);
         } else {
             $var->setType($type);
         }
     }
     // Create the control graph.
     $cfa = new ControlFlowAnalysis();
     $cfa->process($node);
     $cfg = $cfa->getGraph();
     // Create a simple reverse abstract interpreter.
     $rai = new SemanticReverseAbstractInterpreter($this->registry);
     $fi = new ArrayFunctionInterpreter($this->registry);
     $mi = $this->getMock('Scrutinizer\\PhpAnalyzer\\DataFlow\\TypeInference\\MethodInterpreter\\MethodInterpreterInterface');
     $commentParser = new \Scrutinizer\PhpAnalyzer\PhpParser\DocCommentParser($this->registry);
     // Do the type inference by data-flow analysis.
     $dfa = new TypeInference($cfg, $rai, $fi, $mi, $commentParser, $assumedScope, $this->registry);
     $dfa->analyze();
     // Get the scope of the implicit return.
     $this->returnScope = $cfg->getImplicitReturn()->getAttribute(DataFlowAnalysis::ATTR_FLOW_STATE_IN);
     $this->astGraph = \Scrutinizer\PhpAnalyzer\PhpParser\NodeUtil::dump($node);
 }