/** * @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.']); }
/** * @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; }