/** * @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\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 []; }