public function leaveNode(\PHPParser_Node $node)
 {
     if (isset($node->stmts)) {
         $node->stmts = new BlockNode($node->stmts, $node->getLine());
     }
     if ($node instanceof \PHPParser_Node_Stmt_Namespace) {
         $node->setAttribute('imports', $this->imports);
     }
 }
 public function setInput($code, \PHPParser_Node $ast = null)
 {
     $this->astStream->setAst($ast ?: PhpParser\ParseUtils::parse($code));
     $this->tokenStream->setCode($code);
     $lastNode = null;
     while ($this->moveNext()) {
         if ($lastNode !== $this->node) {
             $this->node->setAttribute('start_token', $this->token);
             if (null !== $lastNode) {
                 $lastNode->setAttribute('end_token', $this->token->getPreviousToken()->get());
             }
         }
         $lastNode = $this->node;
     }
     $this->reset();
 }
 private function attachLiteralTypes(\PHPParser_Node $node, \PHPParser_Node $parent = null)
 {
     switch (true) {
         case $node instanceof \PHPParser_Node_Name_FullyQualified:
             $node->setAttribute('type', $this->typeRegistry->getClassOrCreate(implode("\\", $node->parts)));
             break;
         case $node instanceof \PHPParser_Node_Name:
             if ($parent instanceof \PHPParser_Node_Expr_New || $parent instanceof \PHPParser_Node_Expr_StaticPropertyFetch || $parent instanceof \PHPParser_Node_Expr_StaticCall || $parent instanceof \PHPParser_Node_Expr_Instanceof || $parent instanceof \PHPParser_Node_Stmt_Catch) {
                 $name = implode("\\", $node->parts);
                 $lowerName = strtolower($name);
                 if ('static' === $name) {
                     $node->setAttribute('type', $this->typeRegistry->getThisType($this->scope->getTypeOfThis()));
                 } else {
                     if ('self' === $name) {
                         $node->setAttribute('type', $this->scope->getTypeOfThis());
                     } else {
                         if ('parent' === $name) {
                             $thisType = $this->scope->getTypeOfThis()->toMaybeObjectType();
                             if (null === $thisType || !$thisType->isClass() || null === $thisType->getSuperClassType()) {
                                 $node->setAttribute('type', $this->typeRegistry->getNativeType('unknown'));
                             } else {
                                 $node->setAttribute('type', $thisType->getSuperClassType());
                             }
                         } else {
                             $node->setAttribute('type', $this->typeRegistry->getClassOrCreate($name));
                         }
                     }
                 }
             }
             break;
         case $node instanceof \PHPParser_Node_Expr_Array:
         case $node instanceof \PHPParser_Node_Expr_Cast_Array:
             // We only do attach the generic array type on the first build.
             // For subsequent builds, other passes likely have already made
             // the array type more specific.
             if (null === $node->getAttribute('type')) {
                 $node->setAttribute('type', $this->typeRegistry->getNativeType('array'));
             }
             break;
         case $node instanceof \PHPParser_Node_Expr_UnaryMinus:
         case $node instanceof \PHPParser_Node_Expr_UnaryPlus:
         case $node instanceof \PHPParser_Node_Scalar_LNumber:
         case $node instanceof \PHPParser_Node_Scalar_LineConst:
             $node->setAttribute('type', $this->typeRegistry->getNativeType('integer'));
             break;
         case $node instanceof \PHPParser_Node_Scalar_DNumber:
             $node->setAttribute('type', $this->typeRegistry->getNativeType('double'));
             break;
         case $node instanceof \PHPParser_Node_Scalar_String:
         case $node instanceof \PHPParser_Node_Scalar_FileConst:
         case $node instanceof \PHPParser_Node_Scalar_DirConst:
             $node->setAttribute('type', $this->typeRegistry->getNativeType('string'));
             break;
         case $node instanceof \PHPParser_Node_Expr_ClassConstFetch:
             if ($node->class instanceof \PHPParser_Node_Name && in_array($node->class->parts[0], array('self', 'static')) && null !== ($thisType = $this->scope->getTypeOfThis()) && null !== ($objType = $thisType->toMaybeObjectType()) && ($objType->isClass() || $objType->isInterface()) && $objType->hasConstant($node->name)) {
                 $node->setAttribute('type', $objType->getConstant($node->name)->getPhpType());
             }
             break;
         case $node instanceof \PHPParser_Node_Expr_ConstFetch:
             $nameParts = $node->name->parts;
             if (1 === count($nameParts)) {
                 $name = strtolower($nameParts[0]);
                 if ('true' === $name) {
                     $node->setAttribute('type', $this->typeRegistry->getNativeType('boolean'));
                 } else {
                     if ('false' === $name) {
                         $node->setAttribute('type', $this->typeRegistry->getNativeType('false'));
                     } else {
                         if ('null' === $name) {
                             $node->setAttribute('type', $this->typeRegistry->getNativeType('null'));
                         }
                     }
                 }
             }
             break;
     }
 }
 /**
  * This method will stop traversal depending on the parent node.
  *
  * Principally, we are only interested in adding edges between nodes that change control flow. Notable ones are
  * loops (WHILE, FOR, etc.) and IF-ELSE statements; other statements typically transfer control to their next sibling.
  *
  * With regard to expression trees, we currently do not perform any sort of control flow within them, even if there
  * are short circuiting operators or conditionals. Instead, we synthesize lattices up when performing data flow
  * analysis by finding the meet at each expression node.
  *
  * @param NodeTraversal $t
  * @param \PHPParser_Node $node
  * @param \PHPParser_Node $parent
  *
  * @return boolean
  */
 public function shouldTraverse(NodeTraversal $t, \PHPParser_Node $node, \PHPParser_Node $parent = null)
 {
     $node->setAttribute('position', $this->astPositionCounter++);
     if ($node instanceof \PHPParser_Node_Stmt_TryCatch) {
         $this->exceptionHandlers->push($node);
         return true;
     }
     if (null !== $parent) {
         // Do not traverse into classes, interfaces, or traits as control flow never gets passed in.
         if (NodeUtil::isMethodContainer($parent)) {
             return false;
         }
         // Generally, the above also applies to closures except when they are the scope's root.
         if (NodeUtil::isScopeCreator($parent) && $parent !== $this->root) {
             return false;
         }
         // Skip conditions.
         if ($parent instanceof \PHPParser_Node_Stmt_For || $parent instanceof \PHPParser_Node_Stmt_Foreach) {
             return $parent->stmts === $node;
         }
         // Skip conditions.
         if ($parent instanceof \PHPParser_Node_Stmt_If || $parent instanceof \PHPParser_Node_Stmt_ElseIf || $parent instanceof \PHPParser_Node_Stmt_While || $parent instanceof \PHPParser_Node_Stmt_Do || $parent instanceof \PHPParser_Node_Stmt_Switch || $parent instanceof \PHPParser_Node_Stmt_Case) {
             return $parent->cond !== $node;
         }
         // Skip exception type.
         if ($parent instanceof \PHPParser_Node_Stmt_Catch) {
             return $parent->stmts === $node;
         }
         // Skip expressions, see above.
         if ($parent instanceof \PHPParser_Node_Expr && !$parent instanceof \PHPParser_Node_Expr_Closure) {
             return false;
         }
         if ($parent instanceof \PHPParser_Node_Stmt_Continue || $parent instanceof \PHPParser_Node_Stmt_Break || $parent instanceof \PHPParser_Node_Stmt_Return || $parent instanceof \PHPParser_Node_Stmt_Echo || $parent instanceof \PHPParser_Node_Stmt_Use || $parent instanceof \PHPParser_Node_Stmt_Unset || $parent instanceof \PHPParser_Node_Stmt_Declare || $parent instanceof \PHPParser_Node_Stmt_Global || $parent instanceof \PHPParser_Node_Stmt_Static || $parent instanceof \PHPParser_Node_Stmt_StaticVar || $parent instanceof \PHPParser_Node_Stmt_Throw) {
             return false;
         }
         // Skip parameters.
         if (NodeUtil::isScopeCreator($parent) && $node !== $parent->stmts) {
             return false;
         }
         // If we are reaching the CATCH, or FINALLY node, they current exception handler cannot catch anymore
         // exceptions, and we therefore can remove it.
         // TODO: Add Support for FINALLY (PHP 5.5)
         if ($parent instanceof \PHPParser_Node_Stmt_TryCatch && $parent->catches[0] === $node && $parent === $this->exceptionHandlers->top()) {
             $this->exceptionHandlers->pop();
         }
     }
     return true;
 }
 private function traverseShortCircuitingBinOp(\PHPParser_Node $node, LinkedFlowScope $scope, $condition)
 {
     $left = $node->left;
     $right = $node->right;
     // Type the left node.
     $leftLiterals = $this->traverseWithinShortCircuitingBinOp($left, $scope->createChildFlowScope());
     $leftType = $left->getAttribute('type');
     // As these operations are short circuiting, we can reverse interpreter the left node as we know the
     // outcome to its evaluation if we are ever going to reach the right node.
     $rightScope = $this->reverseInterpreter->getPreciserScopeKnowingConditionOutcome($left, $leftLiterals->getOutcomeFlowScope($left, $condition), $condition);
     // Now, type the right node in the updated scope.
     $rightLiterals = $this->traverseWithinShortCircuitingBinOp($right, $rightScope->createChildFlowScope());
     $rightType = $right->getAttribute('type');
     if (null === $leftType || null === $rightType) {
         return new BooleanOutcomePair($this, array(true, false), array(true, false), $leftLiterals->getJoinedFlowScope(), $rightLiterals->getJoinedFlowScope());
     }
     // In PHP, binary operations are always of boolean type.
     $node->setAttribute('type', $this->typeRegistry->getNativeType('boolean'));
     if ($leftLiterals->toBooleanOutcomes === array(!$condition)) {
         // Use the restricted left type, since the right side never gets evaluated.
         return $leftLiterals;
     }
     // Use the join of the restricted left type knowing the outcome of the
     // ToBoolean predicate of the right type.
     return BooleanOutcomePair::fromPairs($this, $leftLiterals, $rightLiterals, $condition);
 }
 private function addDefToVarNodes($name, \PHPParser_Node $defNode, \PHPParser_Node $defExpr, UseLattice $uses)
 {
     if (null === ($var = $this->scope->getVar($name))) {
         return;
     }
     $maybeUsingVarNodes = $uses->getUsingVarNodes($var);
     $defNode->setAttribute('maybe_using_vars', $maybeUsingVarNodes);
     foreach ($maybeUsingVarNodes as $varNode) {
         $maybeDefiningExprs = $varNode->getAttribute('maybe_defining_exprs', array());
         if (in_array($defExpr, $maybeDefiningExprs, true)) {
             continue;
         }
         $maybeDefiningExprs[] = $defExpr;
         $varNode->setAttribute('maybe_defining_exprs', $maybeDefiningExprs);
     }
 }