PHPStan\Broker\Broker::getClassFromReflection PHP Method

getClassFromReflection() public method

public getClassFromReflection ( ReflectionClass $reflectionClass ) : ClassReflection
$reflectionClass ReflectionClass
return PHPStan\Reflection\ClassReflection
    public function getClassFromReflection(\ReflectionClass $reflectionClass) : \PHPStan\Reflection\ClassReflection
    {
        return new ClassReflection($this, $this->propertiesClassReflectionExtensions, $this->methodsClassReflectionExtensions, $reflectionClass);
    }

Usage Example

Beispiel #1
0
 private function processNode(\PhpParser\Node $node, Scope $scope, \Closure $nodeCallback)
 {
     $nodeCallback($node, $scope);
     if ($node instanceof \PhpParser\Node\Stmt\ClassLike) {
         if ($node instanceof Node\Stmt\Trait_) {
             return;
         }
         if (isset($node->namespacedName)) {
             $scope = $scope->enterClass((string) $node->namespacedName);
         } else {
             $scope = $scope->enterAnonymousClass($this->anonymousClassReflection);
         }
     } elseif ($node instanceof Node\Stmt\TraitUse) {
         $this->processTraitUse($node, $scope, $nodeCallback);
     } elseif ($node instanceof \PhpParser\Node\Stmt\Function_) {
         $scope = $scope->enterFunction($this->broker->getFunction($node->namespacedName, $scope));
     } elseif ($node instanceof \PhpParser\Node\Stmt\ClassMethod) {
         $scope = $this->enterClassMethod($scope, $node);
     } elseif ($node instanceof \PhpParser\Node\Stmt\Namespace_) {
         $scope = $scope->enterNamespace((string) $node->name);
     } elseif ($node instanceof \PhpParser\Node\Expr\StaticCall && (is_string($node->class) || $node->class instanceof \PhpParser\Node\Name) && is_string($node->name) && (string) $node->class === 'Closure' && $node->name === 'bind') {
         $thisType = null;
         if (isset($node->args[1])) {
             $argValue = $node->args[1]->value;
             if ($argValue instanceof Expr\ConstFetch && (string) $argValue->name === 'null') {
                 $thisType = null;
             } else {
                 $thisType = $scope->getType($argValue);
             }
         }
         $scopeClass = 'static';
         if (isset($node->args[2])) {
             $argValue = $node->args[2]->value;
             $argValueType = $scope->getType($argValue);
             if ($argValueType->getClass() !== null) {
                 $scopeClass = $argValueType->getClass();
             } elseif ($argValue instanceof Expr\ClassConstFetch && $argValue->name === 'class' && $argValue->class instanceof Name) {
                 $resolvedName = $scope->resolveName($argValue->class);
                 if ($resolvedName !== null) {
                     $scopeClass = $resolvedName;
                 }
             } elseif ($argValue instanceof Node\Scalar\String_) {
                 $scopeClass = $argValue->value;
             }
         }
         $closureBindScope = $scope->enterClosureBind($thisType, $scopeClass);
     } elseif ($node instanceof \PhpParser\Node\Expr\Closure) {
         $scope = $scope->enterAnonymousFunction($node->params, $node->uses, $node->returnType);
     } elseif ($node instanceof Foreach_) {
         if ($node->valueVar instanceof Variable) {
             $scope = $scope->enterForeach($node->expr, $node->valueVar->name, $node->keyVar !== null && $node->keyVar instanceof Variable ? $node->keyVar->name : null);
         } else {
             if ($node->keyVar !== null && $node->keyVar instanceof Variable) {
                 $scope = $scope->assignVariable($node->keyVar->name);
             }
             if ($node->valueVar instanceof Array_) {
                 $scope = $this->lookForArrayDestructuringArray($scope, $node->valueVar);
             } else {
                 $scope = $this->lookForAssigns($scope, $node->valueVar);
             }
         }
     } elseif ($node instanceof Catch_) {
         if (isset($node->types)) {
             $nodeTypes = $node->types;
         } elseif (isset($node->type)) {
             $nodeTypes = [$node->type];
         } else {
             throw new \PHPStan\ShouldNotHappenException();
         }
         $scope = $scope->enterCatch($nodeTypes, $node->var);
     } elseif ($node instanceof For_) {
         foreach ($node->init as $initExpr) {
             $scope = $this->lookForAssigns($scope, $initExpr);
         }
         foreach ($node->cond as $condExpr) {
             $scope = $this->lookForAssigns($scope, $condExpr);
         }
         foreach ($node->loop as $loopExpr) {
             $scope = $this->lookForAssigns($scope, $loopExpr);
         }
     } elseif ($node instanceof If_) {
         $scope = $this->lookForAssigns($scope, $node->cond);
         $ifScope = $scope;
         $scope = $this->lookForTypeSpecifications($scope, $node->cond);
         $this->processNode($node->cond, $scope, $nodeCallback);
         $this->processNodes($node->stmts, $scope, $nodeCallback);
         foreach ($node->elseifs as $elseif) {
             $this->processNode($elseif, $ifScope, $nodeCallback);
             $ifScope = $this->lookForAssigns($ifScope, $elseif->cond);
         }
         if ($node->else !== null) {
             $this->processNode($node->else, $ifScope, $nodeCallback);
         }
         return;
     } elseif ($node instanceof Switch_) {
         $scope = $this->lookForAssigns($scope, $node->cond);
         $switchScope = $scope;
         $switchConditionIsTrue = $node->cond instanceof Expr\ConstFetch && strtolower((string) $node->cond->name) === 'true';
         foreach ($node->cases as $caseNode) {
             if ($caseNode->cond !== null) {
                 $switchScope = $this->lookForAssigns($switchScope, $caseNode->cond);
                 if ($switchConditionIsTrue) {
                     $switchScope = $this->lookForTypeSpecifications($switchScope, $caseNode->cond);
                 }
             }
             $this->processNode($caseNode, $switchScope, $nodeCallback);
             if ($this->hasEarlyTermination($caseNode->stmts, $switchScope)) {
                 $switchScope = $scope;
             }
         }
         return;
     } elseif ($node instanceof ElseIf_) {
         $scope = $this->lookForAssigns($scope, $node->cond);
         $scope = $this->lookForTypeSpecifications($scope, $node->cond);
     } elseif ($node instanceof While_) {
         $scope = $this->lookForAssigns($scope, $node->cond);
         $scope = $this->lookForTypeSpecifications($scope, $node->cond);
     } elseif ($this->polluteCatchScopeWithTryAssignments && $node instanceof TryCatch) {
         foreach ($node->stmts as $statement) {
             $scope = $this->lookForAssigns($scope, $statement);
         }
     } elseif ($node instanceof Ternary) {
         $scope = $this->lookForAssigns($scope, $node->cond);
     } elseif ($node instanceof Do_) {
         foreach ($node->stmts as $statement) {
             $scope = $this->lookForAssigns($scope, $statement);
         }
     } elseif ($node instanceof FuncCall) {
         $scope = $scope->enterFunctionCall($node);
     } elseif ($node instanceof Expr\StaticCall) {
         $scope = $scope->enterFunctionCall($node);
     } elseif ($node instanceof MethodCall) {
         if ($scope->getType($node->var)->getClass() === 'Closure' && $node->name === 'call' && isset($node->args[0])) {
             $closureCallScope = $scope->enterClosureBind($scope->getType($node->args[0]->value), 'static');
         }
         $scope = $scope->enterFunctionCall($node);
     } elseif ($node instanceof Array_) {
         foreach ($node->items as $item) {
             $scope = $this->lookForAssigns($scope, $item->value);
         }
     } elseif ($node instanceof New_ && $node->class instanceof Class_) {
         $node->args = [];
         foreach ($node->class->stmts as $i => $statement) {
             if ($statement instanceof Node\Stmt\ClassMethod && $statement->name === '__construct') {
                 unset($node->class->stmts[$i]);
                 $node->class->stmts = array_values($node->class->stmts);
                 break;
             }
         }
         $code = $this->printer->prettyPrint([$node]);
         $classReflection = new \ReflectionClass(eval(sprintf('return %s', $code)));
         $this->anonymousClassReflection = $this->broker->getClassFromReflection($classReflection);
     } elseif ($node instanceof BooleanNot) {
         $scope = $scope->enterNegation();
     }
     $originalScope = $scope;
     foreach ($node->getSubNodeNames() as $subNodeName) {
         $scope = $originalScope;
         $subNode = $node->{$subNodeName};
         if (is_array($subNode)) {
             $argClosureBindScope = null;
             if (isset($closureBindScope) && $subNodeName === 'args') {
                 $argClosureBindScope = $closureBindScope;
             }
             $this->processNodes($subNode, $scope, $nodeCallback, $argClosureBindScope);
         } elseif ($subNode instanceof \PhpParser\Node) {
             if ($node instanceof Coalesce && $subNodeName === 'left') {
                 $scope = $this->assignVariable($scope, $subNode);
             }
             if ($node instanceof Ternary && $subNodeName === 'if') {
                 $scope = $this->lookForTypeSpecifications($scope, $node->cond);
             }
             if ($node instanceof BooleanAnd && $subNodeName === 'right') {
                 $scope = $this->lookForTypeSpecifications($scope, $node->left);
             }
             if (($node instanceof Assign || $node instanceof AssignRef) && $subNodeName === 'var') {
                 $scope = $this->lookForEnterVariableAssign($scope, $node->var);
             }
             $nodeScope = $scope;
             if ($node instanceof MethodCall && $subNodeName === 'var' && isset($closureCallScope)) {
                 $nodeScope = $closureCallScope;
             }
             $this->processNode($subNode, $nodeScope, $nodeCallback);
         }
     }
 }