/** * @param \PHPStan\Reflection\ClassReflection $classReflection * @return \PHPStan\Reflection\MethodReflection[] */ private function createMethods(ClassReflection $classReflection) : array { $methods = []; foreach ($classReflection->getNativeReflection()->getMethods() as $methodReflection) { $declaringClass = $this->broker->getClass($methodReflection->getDeclaringClass()->getName()); $phpDocParameters = $this->getPhpDocParamsFromMethod($methodReflection); $phpDocParameterTypes = []; if (!$declaringClass->getNativeReflection()->isAnonymous() && $declaringClass->getNativeReflection()->getFileName() !== false) { $typeMap = $this->fileTypeMapper->getTypeMap($declaringClass->getNativeReflection()->getFileName()); foreach ($methodReflection->getParameters() as $parameterReflection) { $typeString = $this->getMethodParameterAnnotationTypeString($phpDocParameters, $parameterReflection); if ($typeString === null || !isset($typeMap[$typeString])) { continue; } $type = $typeMap[$typeString]; $phpDocParameterTypes[$parameterReflection->getName()] = $type; } } $phpDocReturnType = null; $returnTypeString = $this->getReturnTypeStringFromMethod($methodReflection); if ($returnTypeString !== null && isset($typeMap[$returnTypeString])) { $phpDocReturnType = $typeMap[$returnTypeString]; } $methods[strtolower($methodReflection->getName())] = $this->methodReflectionFactory->create($declaringClass, $methodReflection, $phpDocParameterTypes, $phpDocReturnType); } return $methods; }
private function enterClassMethod(Scope $scope, Node\Stmt\ClassMethod $classMethod) : Scope { $fileTypeMap = $this->fileTypeMapper->getTypeMap($scope->getFile()); $phpDocParameterTypes = []; $phpDocReturnType = null; if ($classMethod->getDocComment() !== null) { $docComment = $classMethod->getDocComment()->getText(); $phpDocParameterTypes = TypehintHelper::getPhpDocParameterTypesFromMethod($fileTypeMap, array_map(function (Param $parameter) : string { return $parameter->name; }, $classMethod->params), $docComment); $phpDocReturnType = TypehintHelper::getPhpDocReturnTypeFromMethod($fileTypeMap, $docComment); } return $scope->enterClassMethod($classMethod, $phpDocParameterTypes, $phpDocReturnType); }
private function updateScopeForVariableAssign(Scope $scope, \PhpParser\Node $node) : Scope { if ($node instanceof Assign || $node instanceof AssignRef || $node instanceof Isset_) { if ($node instanceof Assign || $node instanceof AssignRef) { $vars = [$node->var]; } elseif ($node instanceof Isset_) { $vars = $node->vars; } else { throw new \PHPStan\ShouldNotHappenException(); } foreach ($vars as $var) { $scope = $this->assignVariable($scope, $var, $node instanceof Assign || $node instanceof AssignRef ? $scope->getType($node->expr) : null); } if ($node instanceof Assign || $node instanceof AssignRef) { $scope = $this->lookForAssigns($scope, $node->expr); $comment = CommentHelper::getDocComment($node); if ($comment !== null && $node->var instanceof Variable && is_string($node->var->name)) { $variableName = $node->var->name; $processVarAnnotation = function (string $matchedType, string $matchedVariableName) use($scope, $variableName) : Scope { $fileTypeMap = $this->fileTypeMapper->getTypeMap($scope->getFile()); if (isset($fileTypeMap[$matchedType]) && $matchedVariableName === $variableName) { return $scope->assignVariable($matchedVariableName, $fileTypeMap[$matchedType]); } return $scope; }; if (preg_match('#@var\\s+' . FileTypeMapper::TYPE_PATTERN . '\\s+\\$([a-zA-Z0-9_]+)#', $comment, $matches)) { $scope = $processVarAnnotation($matches[1], $matches[2]); } elseif (preg_match('#@var\\s+\\$([a-zA-Z0-9_]+)\\s+' . FileTypeMapper::TYPE_PATTERN . '#', $comment, $matches)) { $scope = $processVarAnnotation($matches[2], $matches[1]); } } } if ($node instanceof Isset_) { foreach ($vars as $var) { if ($var instanceof PropertyFetch) { $scope = $scope->specifyFetchedPropertyFromIsset($var); } } } } return $scope; }
/** * @param \PHPStan\Reflection\ClassReflection $classReflection * @return \PHPStan\Reflection\MethodReflection[] */ private function createMethods(ClassReflection $classReflection) : array { $methods = []; foreach ($classReflection->getNativeReflection()->getMethods() as $methodReflection) { $declaringClass = $this->broker->getClass($methodReflection->getDeclaringClass()->getName()); $phpDocParameterTypes = []; $phpDocReturnType = null; if (!$declaringClass->getNativeReflection()->isAnonymous() && $declaringClass->getNativeReflection()->getFileName() !== false) { $typeMap = $this->fileTypeMapper->getTypeMap($declaringClass->getNativeReflection()->getFileName()); if ($methodReflection->getDocComment() !== false) { $phpDocParameterTypes = TypehintHelper::getPhpDocParameterTypesFromMethod($typeMap, array_map(function (\ReflectionParameter $parameterReflection) : string { return $parameterReflection->getName(); }, $methodReflection->getParameters()), $methodReflection->getDocComment()); } if ($methodReflection->getDocComment() !== false) { $phpDocReturnType = TypehintHelper::getPhpDocReturnTypeFromMethod($typeMap, $methodReflection->getDocComment()); } } $methods[strtolower($methodReflection->getName())] = $this->methodReflectionFactory->create($declaringClass, $methodReflection, $phpDocParameterTypes, $phpDocReturnType); } return $methods; }