private function checkParametersAcceptor(ParametersAcceptor $parametersAcceptor, string $parameterMessage, string $returnMessage) : array
 {
     $errors = [];
     foreach ($parametersAcceptor->getParameters() as $parameter) {
         $type = $parameter->getType();
         if ($type->getClass() !== null && !$this->broker->hasClass($type->getClass())) {
             $errors[] = sprintf($parameterMessage, $parameter->getName(), $type->getClass());
         } elseif ($type instanceof ArrayType) {
             $nestedItemType = $type->getNestedItemType();
             if ($nestedItemType->getItemType()->getClass() !== null && !$this->broker->hasClass($nestedItemType->getItemType()->getClass())) {
                 $errors[] = sprintf($parameterMessage, $parameter->getName(), $type->describe());
             }
         }
     }
     $returnType = $parametersAcceptor->getReturnType();
     if ($returnType->getClass() !== null && !$this->broker->hasClass($returnType->getClass())) {
         $errors[] = sprintf($returnMessage, $returnType->getClass());
     } elseif ($returnType instanceof ArrayType) {
         $nestedItemType = $returnType->getNestedItemType();
         if ($nestedItemType->getItemType()->getClass() !== null && !$this->broker->hasClass($nestedItemType->getItemType()->getClass())) {
             $errors[] = sprintf($returnMessage, $returnType->describe());
         }
     }
     return $errors;
 }
 /**
  * @param \PhpParser\Node\Stmt\ClassMethod $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if ($node->name !== '__construct') {
         return [];
     }
     $className = $scope->getClass();
     if ($className === null) {
         return [];
         // anonymous class
     }
     $classReflection = $this->broker->getClass($className);
     if ($classReflection->isInterface()) {
         return [];
     }
     if ($this->callsParentConstruct($node)) {
         if ($classReflection->getParentClass() === false) {
             return [sprintf('%s::__construct() calls parent constructor but does not extend any class.', $className)];
         }
         if ($this->getParentConstructorClass($classReflection) === false) {
             return [sprintf('%s::__construct() calls parent constructor but parent does not have one.', $className)];
         }
     } else {
         $parentClass = $this->getParentConstructorClass($classReflection);
         if ($parentClass !== false) {
             return [sprintf('%s::__construct() does not call parent constructor from %s.', $className, $parentClass->getName())];
         }
     }
     return [];
 }
Beispiel #3
0
 /**
  * @param \PhpParser\Node\Expr\New_ $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if (!$node->class instanceof \PhpParser\Node\Name) {
         return [];
     }
     $class = (string) $node->class;
     if ($class === 'static') {
         return [];
     }
     if ($class === 'self') {
         $class = $scope->getClass();
         if ($class === null) {
             return [];
         }
     }
     if (!$this->broker->hasClass($class)) {
         return [sprintf('Instantiated class %s not found.', $class)];
     }
     $classReflection = $this->broker->getClass($class);
     if ($classReflection->isInterface()) {
         return [sprintf('Cannot instantiate interface %s.', $classReflection->getName())];
     }
     if ($classReflection->isAbstract()) {
         return [sprintf('Instantiated class %s is abstract.', $classReflection->getName())];
     }
     if (!$classReflection->hasMethod('__construct') && !$classReflection->hasMethod($class)) {
         if (count($node->args) > 0) {
             return [sprintf('Class %s does not have a constructor and must be instantiated without any parameters.', $classReflection->getName())];
         }
         return [];
     }
     return $this->check->check($classReflection->hasMethod('__construct') ? $classReflection->getMethod('__construct') : $classReflection->getMethod($class), $node, ['Class ' . $classReflection->getName() . ' constructor invoked with %d parameter, %d required.', 'Class ' . $classReflection->getName() . ' constructor invoked with %d parameters, %d required.', 'Class ' . $classReflection->getName() . ' constructor invoked with %d parameter, at least %d required.', 'Class ' . $classReflection->getName() . ' constructor invoked with %d parameters, at least %d required.', 'Class ' . $classReflection->getName() . ' constructor invoked with %d parameter, %d-%d required.', 'Class ' . $classReflection->getName() . ' constructor invoked with %d parameters, %d-%d required.']);
 }
 /**
  * @param \PhpParser\Node\Expr\StaticCall $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if (!is_string($node->name)) {
         return [];
     }
     $name = $node->name;
     $currentClass = $scope->getClass();
     if ($currentClass === null) {
         return [];
     }
     $currentClassReflection = $this->broker->getClass($currentClass);
     if (!$node->class instanceof Name) {
         return [];
     }
     $class = (string) $node->class;
     if ($class === 'self' || $class === 'static') {
         $class = $currentClass;
     }
     if ($class === 'parent') {
         if ($currentClassReflection->getParentClass() === false) {
             return [sprintf('%s::%s() calls to parent::%s() but %s does not extend any class.', $currentClass, $scope->getFunctionName(), $name, $currentClass)];
         }
         $currentMethodReflection = $currentClassReflection->getMethod($scope->getFunctionName());
         if (!$currentMethodReflection->isStatic()) {
             if ($name === '__construct' && $currentClassReflection->getParentClass()->hasMethod('__construct')) {
                 return $this->check->check($currentClassReflection->getParentClass()->getMethod('__construct'), $node, ['Parent constructor invoked with %d parameter, %d required.', 'Parent constructor invoked with %d parameters, %d required.', 'Parent constructor invoked with %d parameter, at least %d required.', 'Parent constructor invoked with %d parameters, at least %d required.', 'Parent constructor invoked with %d parameter, %d-%d required.', 'Parent constructor invoked with %d parameters, %d-%d required.']);
             }
             return [];
         }
         $class = $currentClassReflection->getParentClass()->getName();
     }
     $classReflection = $this->broker->getClass($class);
     if (!$classReflection->hasMethod($name)) {
         return [sprintf('Call to an undefined static method %s::%s().', $class, $name)];
     }
     $method = $classReflection->getMethod($name);
     if (!$method->isStatic()) {
         return [sprintf('Static call to instance method %s::%s().', $class, $method->getName())];
     }
     if ($currentClass !== null && $method->getDeclaringClass()->getName() !== $currentClass) {
         if (in_array($method->getDeclaringClass()->getName(), $currentClassReflection->getParentClassesNames(), true)) {
             if ($method->isPrivate()) {
                 return [sprintf('Call to private static method %s() of class %s.', $method->getName(), $method->getDeclaringClass()->getName())];
             }
         } else {
             if (!$method->isPublic()) {
                 return [sprintf('Call to %s static method %s() of class %s.', $method->isPrivate() ? 'private' : 'protected', $method->getName(), $method->getDeclaringClass()->getName())];
             }
         }
     }
     $methodName = $class . '::' . $method->getName() . '()';
     $errors = $this->check->check($method, $node, ['Static method ' . $methodName . ' invoked with %d parameter, %d required.', 'Static method ' . $methodName . ' invoked with %d parameters, %d required.', 'Static method ' . $methodName . ' invoked with %d parameter, at least %d required.', 'Static method ' . $methodName . ' invoked with %d parameters, at least %d required.', 'Static method ' . $methodName . ' invoked with %d parameter, %d-%d required.', 'Static method ' . $methodName . ' invoked with %d parameters, %d-%d required.']);
     if ($method->getName() !== $name) {
         $errors[] = sprintf('Call to static method %s with incorrect case: %s', $methodName, $name);
     }
     return $errors;
 }
 /**
  * @param \PhpParser\Node\Expr\FuncCall $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if (!$node->name instanceof \PhpParser\Node\Name) {
         return [];
     }
     if (!$this->broker->hasFunction($node->name, $scope)) {
         return [];
     }
     $function = $this->broker->getFunction($node->name, $scope);
     return $this->check->check($function, $node, ['Function ' . $function->getName() . ' invoked with %d parameter, %d required.', 'Function ' . $function->getName() . ' invoked with %d parameters, %d required.', 'Function ' . $function->getName() . ' invoked with %d parameter, at least %d required.', 'Function ' . $function->getName() . ' invoked with %d parameters, at least %d required.', 'Function ' . $function->getName() . ' invoked with %d parameter, %d-%d required.', 'Function ' . $function->getName() . ' invoked with %d parameters, %d-%d required.']);
 }
 public function getMethod(ClassReflection $classReflection, string $methodName) : MethodReflection
 {
     $metadata = $this->metadataSource->getMetadataForClass($classReflection->getNativeReflection());
     $sentryMethodSearchResult = $metadata->getSentryMethodByNameAndRequiredVisibility($methodName, Visibility::get(Visibility::VISIBILITY_PRIVATE));
     $property = $sentryMethodSearchResult->getProperty();
     $sentryMethod = $sentryMethodSearchResult->getSentryMethod();
     $sentryAccess = $sentryMethod->getSentryAccess();
     $isSetter = $sentryAccess->equals(new SentryAccess('set'));
     $methodHasParameter = $isSetter || $sentryAccess->equals(new SentryAccess('add')) || $sentryAccess->equals(new SentryAccess('remove')) || $sentryAccess->equals(new SentryAccess('contains'));
     $propertyClass = $this->broker->getClass($property->getClassName());
     return new SentryMethodReflection($methodName, $propertyClass, $sentryMethod->getMethodVisibility(), $this->phpClassReflectionExtension->getProperty($propertyClass, $property->getName())->getType(), $methodHasParameter ? $isSetter ? $property->isNullable() : false : null);
 }
 /**
  * @param \PhpParser\Node\Expr\FuncCall $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if (!$node->name instanceof \PhpParser\Node\Name) {
         return [];
     }
     if (!$this->broker->hasFunction($node->name, $scope)) {
         return [sprintf('Function %s not found.', (string) $node->name)];
     }
     $function = $this->broker->getFunction($node->name, $scope);
     $name = (string) $node->name;
     if ($function->getName() !== $this->broker->resolveFunctionName($node->name, $scope)) {
         return [sprintf('Call to function %s() with incorrect case: %s', $function->getName(), $name)];
     }
     return [];
 }
Beispiel #8
0
 /**
  * @param \PhpParser\Node\Expr\ClassConstFetch $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     $class = $node->class;
     if ($class instanceof \PhpParser\Node\Name) {
         $className = (string) $class;
     } else {
         $classType = $scope->getType($class);
         if ($classType->getClass() !== null) {
             $className = $classType->getClass();
         } else {
             return [];
         }
     }
     if ($className === 'self' || $className === 'static') {
         if ($scope->getClass() === null && !$scope->isInAnonymousClass()) {
             return [sprintf('Using %s outside of class scope.', $className)];
         }
         if ($className === 'static') {
             return [];
         }
         if ($className === 'self') {
             $className = $scope->getClass();
         }
     }
     $constantName = $node->name;
     if ($scope->getClass() !== null && $className === 'parent') {
         $currentClassReflection = $this->broker->getClass($scope->getClass());
         if ($currentClassReflection->getParentClass() === false) {
             return [sprintf('Access to parent::%s but %s does not extend any class.', $constantName, $scope->getClass())];
         }
         $className = $currentClassReflection->getParentClass()->getName();
     }
     if (!$this->broker->hasClass($className)) {
         return [sprintf('Class %s not found.', $className)];
     }
     if ($constantName === 'class') {
         return [];
     }
     $classReflection = $this->broker->getClass($className);
     if (!$classReflection->hasConstant($constantName)) {
         return [sprintf('Access to undefined constant %s::%s.', $classReflection->getName(), $constantName)];
     }
     $constantReflection = $classReflection->getConstant($constantName);
     if (!$scope->canAccessConstant($constantReflection)) {
         return [sprintf('Cannot access constant %s::%s from current scope.', $constantReflection->getDeclaringClass()->getName(), $constantName)];
     }
     return [];
 }
 /**
  * @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;
 }
 /**
  * @param \PhpParser\Node\Stmt\Catch_ $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     $classes = $node->types;
     $errors = [];
     foreach ($classes as $className) {
         $class = (string) $className;
         if (!$this->broker->hasClass($class)) {
             $errors[] = sprintf('Catched class %s not found.', $class);
             continue;
         }
         $classReflection = $this->broker->getClass($class);
         if (!$classReflection->isInterface() && !$classReflection->getNativeReflection()->implementsInterface(\Throwable::class)) {
             $errors[] = sprintf('Catched class %s is not an exception.', $class);
         }
     }
     return $errors;
 }
Beispiel #11
0
 /**
  * @param \PhpParser\Node\Expr\MethodCall $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if (!is_string($node->name)) {
         return [];
     }
     if ($this->checkThisOnly && !$this->ruleLevelHelper->isThis($node->var)) {
         return [];
     }
     $type = $scope->getType($node->var);
     if (!$type->canCallMethods()) {
         return [sprintf('Cannot call method %s() on %s.', $node->name, $type->describe())];
     }
     $methodClass = $type->getClass();
     if ($methodClass === null) {
         return [];
     }
     $name = (string) $node->name;
     if (!$this->broker->hasClass($methodClass)) {
         return [sprintf('Call to method %s() on an unknown class %s.', $name, $methodClass)];
     }
     $methodClassReflection = $this->broker->getClass($methodClass);
     if (!$methodClassReflection->hasMethod($name)) {
         $parentClassReflection = $methodClassReflection->getParentClass();
         while ($parentClassReflection !== false) {
             if ($parentClassReflection->hasMethod($name)) {
                 return [sprintf('Call to private method %s() of parent class %s.', $parentClassReflection->getMethod($name)->getName(), $parentClassReflection->getName())];
             }
             $parentClassReflection = $parentClassReflection->getParentClass();
         }
         return [sprintf('Call to an undefined method %s::%s().', $methodClassReflection->getName(), $name)];
     }
     $methodReflection = $methodClassReflection->getMethod($name);
     $messagesMethodName = $methodReflection->getDeclaringClass()->getName() . '::' . $methodReflection->getName() . '()';
     if (!$scope->canCallMethod($methodReflection)) {
         return [sprintf('Cannot call method %s from current scope.', $messagesMethodName)];
     }
     $errors = $this->check->check($methodReflection, $node, ['Method ' . $messagesMethodName . ' invoked with %d parameter, %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameter, at least %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameters, at least %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameter, %d-%d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d-%d required.']);
     if ($methodReflection->getName() !== $name) {
         $errors[] = sprintf('Call to method %s with incorrect case: %s', $messagesMethodName, $name);
     }
     return $errors;
 }
 /**
  * @param \PhpParser\Node\Expr\StaticPropertyFetch $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if (!is_string($node->name) || !$node->class instanceof Node\Name) {
         return [];
     }
     $name = $node->name;
     $currentClass = $scope->getClass();
     if ($currentClass === null) {
         return [];
     }
     $currentClassReflection = $this->broker->getClass($currentClass);
     $class = (string) $node->class;
     if ($class === 'self' || $class === 'static') {
         $class = $currentClass;
     }
     if ($class === 'parent') {
         if ($currentClassReflection->getParentClass() === false) {
             return [sprintf('%s::%s() accesses parent::$%s but %s does not extend any class.', $currentClass, $scope->getFunctionName(), $name, $currentClass)];
         }
         $currentMethodReflection = $currentClassReflection->getMethod($scope->getFunctionName());
         if (!$currentMethodReflection->isStatic()) {
             // calling parent::method() from instance method
             return [];
         }
         $class = $currentClassReflection->getParentClass()->getName();
     }
     if (!$this->broker->hasClass($class)) {
         return [sprintf('Access to static property $%s on an unknown class %s.', $name, $class)];
     }
     $classReflection = $this->broker->getClass($class);
     if (!$classReflection->hasProperty($name)) {
         return [sprintf('Access to an undefined static property %s::$%s.', $classReflection->getName(), $name)];
     }
     $property = $classReflection->getProperty($name, $scope);
     if (!$property->isStatic()) {
         return [sprintf('Static access to instance property %s::$%s.', $property->getDeclaringClass()->getName(), $name)];
     }
     if (!$scope->canAccessProperty($property)) {
         return [sprintf('Cannot access property %s::$%s from current scope.', $property->getDeclaringClass()->getName(), $name)];
     }
     return [];
 }
 /**
  * @param \PhpParser\Node\Stmt\Property $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     if ($scope->getClass() === null || !$this->broker->hasClass($scope->getClass())) {
         return [];
     }
     $classReflection = $this->broker->getClass($scope->getClass());
     $errors = [];
     foreach ($node->props as $property) {
         if ($property->default === null) {
             continue;
         }
         $propertyReflection = $classReflection->getProperty($property->name);
         $propertyType = $propertyReflection->getType();
         $defaultValueType = $scope->getType($property->default);
         if ($propertyType->accepts($defaultValueType)) {
             continue;
         }
         $errors[] = sprintf('%s %s::$%s (%s) does not accept default value of type %s.', $node->isStatic() ? 'Static property' : 'Property', $scope->getClass(), $property->name, $propertyType->describe(), $defaultValueType->describe());
     }
     return $errors;
 }
Beispiel #14
0
 public function getConstant(string $name) : ClassConstantReflection
 {
     if (!isset($this->constants[$name])) {
         if (PHP_VERSION_ID < 70100) {
             $this->constants[$name] = new ObsoleteClassConstantReflection($this, $name, $this->getNativeReflection()->getConstant($name));
         } else {
             $reflectionConstant = $this->getNativeReflection()->getReflectionConstant($name);
             $this->constants[$name] = new ClassConstantWithVisibilityReflection($this->broker->getClass($reflectionConstant->getDeclaringClass()->getName()), $reflectionConstant);
         }
     }
     return $this->constants[$name];
 }
 /**
  * @param \PhpParser\Node\Expr\PropertyFetch $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(\PhpParser\Node $node, Scope $scope) : array
 {
     if (!is_string($node->name)) {
         return [];
     }
     if ($this->checkThisOnly && !$this->ruleLevelHelper->isThis($node->var)) {
         return [];
     }
     $type = $scope->getType($node->var);
     if (!$type->canAccessProperties()) {
         return [sprintf('Cannot access property $%s on %s.', $node->name, $type->describe())];
     }
     $propertyClass = $type->getClass();
     if ($propertyClass === null) {
         return [];
     }
     $name = (string) $node->name;
     if (!$this->broker->hasClass($propertyClass)) {
         return [sprintf('Access to property $%s on an unknown class %s.', $name, $propertyClass)];
     }
     $propertyClassReflection = $this->broker->getClass($propertyClass);
     if (!$propertyClassReflection->hasProperty($name)) {
         if ($scope->isSpecified($node)) {
             return [];
         }
         $parentClassReflection = $propertyClassReflection->getParentClass();
         while ($parentClassReflection !== false) {
             if ($parentClassReflection->hasProperty($name)) {
                 return [sprintf('Access to private property $%s of parent class %s.', $name, $parentClassReflection->getName())];
             }
             $parentClassReflection = $parentClassReflection->getParentClass();
         }
         return [sprintf('Access to an undefined property %s::$%s.', $propertyClass, $name)];
     }
     $propertyReflection = $propertyClassReflection->getProperty($name, $scope);
     if (!$scope->canAccessProperty($propertyReflection)) {
         return [sprintf('Cannot access property %s::$%s from current scope.', $propertyReflection->getDeclaringClass()->getName(), $name)];
     }
     return [];
 }
 /**
  * @param \PhpParser\Node\Stmt\PropertyProperty $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     $className = $scope->getClass();
     if ($className === null) {
         return [];
     }
     $classReflection = $this->broker->getClass($className);
     $propertyType = $classReflection->getProperty($node->name, $scope)->getType();
     if ($propertyType instanceof ArrayType) {
         $nestedItemType = $propertyType->getNestedItemType();
         if ($nestedItemType->getItemType()->getClass() !== null && !$this->broker->hasClass($nestedItemType->getItemType()->getClass())) {
             return [sprintf('Property %s::$%s has unknown class %s as its array type.', $className, $node->name, $propertyType->describe())];
         }
     }
     if ($propertyType->getClass() === null) {
         return [];
     }
     if (!$this->broker->hasClass($propertyType->getClass())) {
         return [sprintf('Property %s::$%s has unknown class %s as its type.', $className, $node->name, $propertyType->getClass())];
     }
     return [];
 }
 /**
  * @param \PhpParser\Node\Expr\Instanceof_ $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     $class = $node->class;
     if (!$class instanceof \PhpParser\Node\Name) {
         return [];
     }
     $name = (string) $class;
     if ($name === 'self' || $name === 'static') {
         if ($scope->getClass() === null && !$scope->isInAnonymousClass()) {
             return [sprintf('Using %s outside of class scope.', $name)];
         }
         if ($name === 'static') {
             return [];
         }
         if ($name === 'self') {
             $name = $scope->getClass();
         }
     }
     if (!$this->broker->hasClass($name)) {
         return [sprintf('Class %s not found.', $name)];
     }
     return [];
 }
Beispiel #18
0
 /**
  * @param \PhpParser\Node\Expr\ClassConstFetch $node
  * @param \PHPStan\Analyser\Scope $scope
  * @return string[]
  */
 public function processNode(Node $node, Scope $scope) : array
 {
     $class = $node->class;
     if ($class instanceof \PhpParser\Node\Name) {
         $className = (string) $class;
     } else {
         $classType = $scope->getType($class);
         if ($classType->getClass() !== null) {
             $className = $classType->getClass();
         } else {
             return [];
         }
     }
     if ($className === 'self' || $className === 'static') {
         if ($scope->getClass() === null && !$scope->isInAnonymousClass()) {
             return [sprintf('Using %s outside of class scope.', $className)];
         }
         if ($className === 'static') {
             return [];
         }
         if ($className === 'self') {
             $className = $scope->getClass();
         }
     }
     if (!$this->broker->hasClass($className)) {
         return [sprintf('Class %s not found.', $className)];
     }
     $constantName = $node->name;
     if ($constantName === 'class') {
         return [];
     }
     $classReflection = $this->broker->getClass($className);
     if (!$classReflection->hasConstant($constantName)) {
         return [sprintf('Access to undefined constant %s::%s.', $className, $constantName)];
     }
     return [];
 }
Beispiel #19
0
 /**
  * @param \PhpParser\Node\Expr $functionCall
  * @param \PHPStan\Analyser\Scope $scope
  * @return null|\PHPStan\Reflection\ParameterReflection[]
  */
 private function findParametersInFunctionCall(Expr $functionCall, Scope $scope)
 {
     if ($functionCall instanceof FuncCall && $functionCall->name instanceof Name) {
         if ($this->broker->hasFunction($functionCall->name, $scope)) {
             return $this->broker->getFunction($functionCall->name, $scope)->getParameters();
         }
     } elseif ($functionCall instanceof MethodCall && is_string($functionCall->name)) {
         $type = $scope->getType($functionCall->var);
         if ($type->getClass() !== null && $this->broker->hasClass($type->getClass())) {
             $classReflection = $this->broker->getClass($type->getClass());
             $methodName = $functionCall->name;
             if ($classReflection->hasMethod((string) $methodName)) {
                 return $classReflection->getMethod((string) $methodName)->getParameters();
             }
         }
     }
     return null;
 }
Beispiel #20
0
 private function processTraitUse(Node\Stmt\TraitUse $node, Scope $classScope, \Closure $nodeCallback)
 {
     foreach ($node->traits as $trait) {
         $traitName = (string) $trait;
         if (!$this->broker->hasClass($traitName)) {
             continue;
         }
         $traitReflection = $this->broker->getClass($traitName);
         $fileName = $traitReflection->getNativeReflection()->getFileName();
         $parserNodes = $this->parser->parseFile($fileName);
         $classScope = $classScope->changeAnalysedContextFile(sprintf('%s (in context of %s)', $fileName, $classScope->getClass() !== null ? sprintf('class %s', $classScope->getClass()) : 'anonymous class'));
         $this->processNodes($parserNodes, new Scope($this->broker, $this->printer, $fileName), function (\PhpParser\Node $node) use($traitName, $classScope, $nodeCallback) {
             if ($node instanceof Node\Stmt\Trait_ && $traitName === (string) $node->namespacedName) {
                 $this->processNodes($node->stmts, $classScope, $nodeCallback);
             }
         });
     }
 }
Beispiel #21
0
 private function canAccessClassMember(ClassMemberReflection $classMemberReflection) : bool
 {
     if ($classMemberReflection->isPublic()) {
         return true;
     }
     $class = $this->inClosureBindScopeClass !== null ? $this->inClosureBindScopeClass : $this->getClass();
     if ($class === null) {
         return false;
     }
     if (!$this->broker->hasClass($class)) {
         return false;
     }
     $classReflectionName = $classMemberReflection->getDeclaringClass()->getName();
     if ($classMemberReflection->isPrivate()) {
         return $class === $classReflectionName;
     }
     $currentClassReflection = $this->broker->getClass($class);
     // protected
     return $currentClassReflection->getName() === $classReflectionName || $currentClassReflection->isSubclassOf($classReflectionName);
 }
 /**
  * @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;
 }
Beispiel #23
0
 /**
  * @return \PHPStan\Reflection\ClassReflection[]
  */
 public function getInterfaces() : array
 {
     return array_map(function (\ReflectionClass $interface) {
         return $this->broker->getClass($interface->getName());
     }, $this->getNativeReflection()->getInterfaces());
 }