Deprecate the GetLocale class and replace with ACL\Login locales set

If ACL\Login is used, the loginGetLocale() call should be used to fetch
the locale data set during login

Language\L10n now has new encoding/charset optional parameter 4
If the locale does not have a charset set the defautl charset is UTF-8
unless set via the new parameter or setOverrideEncoding()

Because of the deprecation of the getLocales call the following methods
do no longer need $locales
- Admin\Backend
- Admin\EditBase
- Output\Form\Generate
- Template\SmartyExtend

They all use the new l10n->getLocaleAsArray() call to set all the local
variables

* Admin\EditBase has new parameter "options" to set
- cache_id
- compile_id
which must be passed on the SmartyExtend class init
This commit is contained in:
Clemens Schwaighofer
2023-03-10 13:43:43 +09:00
parent ea503fffe9
commit 90a8c5540f
85 changed files with 2943 additions and 164 deletions

View File

@@ -0,0 +1,80 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\MissingPropertyFromReflectionException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<PropertyFetch>
*/
class AccessDeprecatedPropertyRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return PropertyFetch::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if (!$node->name instanceof Identifier) {
return [];
}
$propertyName = $node->name->name;
$propertyAccessedOnType = $scope->getType($node->var);
$referencedClasses = $propertyAccessedOnType->getObjectClassNames();
foreach ($referencedClasses as $referencedClass) {
try {
$classReflection = $this->reflectionProvider->getClass($referencedClass);
$propertyReflection = $classReflection->getProperty($propertyName, $scope);
if ($propertyReflection->isDeprecated()->yes()) {
$description = $propertyReflection->getDeprecatedDescription();
if ($description === null) {
return [sprintf(
'Access to deprecated property $%s of class %s.',
$propertyName,
$propertyReflection->getDeclaringClass()->getName()
)];
}
return [sprintf(
"Access to deprecated property $%s of class %s:\n%s",
$propertyName,
$propertyReflection->getDeclaringClass()->getName(),
$description
)];
}
} catch (ClassNotFoundException $e) {
// Other rules will notify if the class is not found
} catch (MissingPropertyFromReflectionException $e) {
// Other rules will notify if the property is not found
}
}
return [];
}
}

View File

@@ -0,0 +1,106 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\MissingPropertyFromReflectionException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Type;
use function sprintf;
/**
* @implements Rule<StaticPropertyFetch>
*/
class AccessDeprecatedStaticPropertyRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper)
{
$this->reflectionProvider = $reflectionProvider;
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function getNodeType(): string
{
return StaticPropertyFetch::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if (!$node->name instanceof Identifier) {
return [];
}
$propertyName = $node->name->name;
$referencedClasses = [];
if ($node->class instanceof Name) {
$referencedClasses[] = (string) $node->class;
} else {
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$node->class,
'', // We don't care about the error message
static function (Type $type) use ($propertyName): bool {
return $type->canAccessProperties()->yes() && $type->hasProperty($propertyName)->yes();
}
);
if ($classTypeResult->getType() instanceof ErrorType) {
return [];
}
$referencedClasses = $classTypeResult->getReferencedClasses();
}
foreach ($referencedClasses as $referencedClass) {
try {
$class = $this->reflectionProvider->getClass($referencedClass);
$property = $class->getProperty($propertyName, $scope);
} catch (ClassNotFoundException $e) {
continue;
} catch (MissingPropertyFromReflectionException $e) {
continue;
}
if ($property->isDeprecated()->yes()) {
$description = $property->getDeprecatedDescription();
if ($description === null) {
return [sprintf(
'Access to deprecated static property $%s of class %s.',
$propertyName,
$referencedClass
)];
}
return [sprintf(
"Access to deprecated static property $%s of class %s:\n%s",
$propertyName,
$referencedClass,
$description
)];
}
}
return [];
}
}

View File

@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\FunctionNotFoundException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<FuncCall>
*/
class CallToDeprecatedFunctionRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return FuncCall::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if (!($node->name instanceof Name)) {
return [];
}
try {
$function = $this->reflectionProvider->getFunction($node->name, $scope);
} catch (FunctionNotFoundException $e) {
// Other rules will notify if the function is not found
return [];
}
if ($function->isDeprecated()->yes()) {
$description = $function->getDeprecatedDescription();
if ($description === null) {
return [sprintf(
'Call to deprecated function %s().',
$function->getName()
)];
}
return [sprintf(
"Call to deprecated function %s():\n%s",
$function->getName(),
$description
)];
}
return [];
}
}

View File

@@ -0,0 +1,82 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\MissingMethodFromReflectionException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<MethodCall>
*/
class CallToDeprecatedMethodRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return MethodCall::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if (!$node->name instanceof Identifier) {
return [];
}
$methodName = $node->name->name;
$methodCalledOnType = $scope->getType($node->var);
$referencedClasses = $methodCalledOnType->getObjectClassNames();
foreach ($referencedClasses as $referencedClass) {
try {
$classReflection = $this->reflectionProvider->getClass($referencedClass);
$methodReflection = $classReflection->getMethod($methodName, $scope);
if (!$methodReflection->isDeprecated()->yes()) {
continue;
}
$description = $methodReflection->getDeprecatedDescription();
if ($description === null) {
return [sprintf(
'Call to deprecated method %s() of class %s.',
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName()
)];
}
return [sprintf(
"Call to deprecated method %s() of class %s:\n%s",
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName(),
$description
)];
} catch (ClassNotFoundException $e) {
// Other rules will notify if the class is not found
} catch (MissingMethodFromReflectionException $e) {
// Other rules will notify if the the method is not found
}
}
return [];
}
}

View File

@@ -0,0 +1,128 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\MissingMethodFromReflectionException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Type;
use function sprintf;
/**
* @implements Rule<StaticCall>
*/
class CallToDeprecatedStaticMethodRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper)
{
$this->reflectionProvider = $reflectionProvider;
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function getNodeType(): string
{
return StaticCall::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if (!$node->name instanceof Identifier) {
return [];
}
$methodName = $node->name->name;
$referencedClasses = [];
if ($node->class instanceof Name) {
$referencedClasses[] = $scope->resolveName($node->class);
} else {
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$node->class,
'', // We don't care about the error message
static function (Type $type) use ($methodName): bool {
return $type->canCallMethods()->yes() && $type->hasMethod($methodName)->yes();
}
);
if ($classTypeResult->getType() instanceof ErrorType) {
return [];
}
$referencedClasses = $classTypeResult->getReferencedClasses();
}
$errors = [];
foreach ($referencedClasses as $referencedClass) {
try {
$class = $this->reflectionProvider->getClass($referencedClass);
$methodReflection = $class->getMethod($methodName, $scope);
} catch (ClassNotFoundException $e) {
continue;
} catch (MissingMethodFromReflectionException $e) {
continue;
}
if ($class->isDeprecated()) {
$classDescription = $class->getDeprecatedDescription();
if ($classDescription === null) {
$errors[] = sprintf(
'Call to method %s() of deprecated class %s.',
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName()
);
} else {
$errors[] = sprintf(
"Call to method %s() of deprecated class %s:\n%s",
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName(),
$classDescription
);
}
}
if (!$methodReflection->isDeprecated()->yes()) {
continue;
}
$description = $methodReflection->getDeprecatedDescription();
if ($description === null) {
$errors[] = sprintf(
'Call to deprecated method %s() of class %s.',
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName()
);
} else {
$errors[] = sprintf(
"Call to deprecated method %s() of class %s:\n%s",
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName(),
$description
);
}
}
return $errors;
}
}

View File

@@ -0,0 +1,64 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\ReflectionProvider;
use function sprintf;
class DeprecatedClassHelper
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getClassType(ClassReflection $class): string
{
if ($class->isInterface()) {
return 'interface';
}
return 'class';
}
public function getClassDeprecationDescription(ClassReflection $class): string
{
$description = $class->getDeprecatedDescription();
if ($description === null) {
return '.';
}
return sprintf(":\n%s", $description);
}
/**
* @param string[] $referencedClasses
* @return ClassReflection[]
*/
public function filterDeprecatedClasses(array $referencedClasses): array
{
$deprecatedClasses = [];
foreach ($referencedClasses as $referencedClass) {
try {
$class = $this->reflectionProvider->getClass($referencedClass);
} catch (ClassNotFoundException $e) {
continue;
}
if (!$class->isDeprecated()) {
continue;
}
$deprecatedClasses[] = $class;
}
return $deprecatedClasses;
}
}

View File

@@ -0,0 +1,30 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PHPStan\Analyser\Scope;
class DeprecatedScopeHelper
{
public static function isScopeDeprecated(Scope $scope): bool
{
$class = $scope->getClassReflection();
if ($class !== null && $class->isDeprecated()) {
return true;
}
$trait = $scope->getTraitReflection();
if ($trait !== null && $trait->isDeprecated()) {
return true;
}
$function = $scope->getFunction();
if ($function !== null && $function->isDeprecated()->yes()) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,135 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Type;
use function sprintf;
use function strtolower;
/**
* @implements Rule<ClassConstFetch>
*/
class FetchingClassConstOfDeprecatedClassRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper)
{
$this->reflectionProvider = $reflectionProvider;
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function getNodeType(): string
{
return ClassConstFetch::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if (!$node->name instanceof Identifier) {
return [];
}
$constantName = $node->name->name;
$referencedClasses = [];
if ($node->class instanceof Name) {
$referencedClasses[] = $scope->resolveName($node->class);
} else {
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$node->class,
'', // We don't care about the error message
static function (Type $type) use ($constantName): bool {
return $type->canAccessConstants()->yes() && $type->hasConstant($constantName)->yes();
}
);
if ($classTypeResult->getType() instanceof ErrorType) {
return [];
}
$referencedClasses = $classTypeResult->getReferencedClasses();
}
$errors = [];
foreach ($referencedClasses as $referencedClass) {
try {
$class = $this->reflectionProvider->getClass($referencedClass);
} catch (ClassNotFoundException $e) {
continue;
}
if ($class->isDeprecated()) {
$classDescription = $class->getDeprecatedDescription();
if ($classDescription === null) {
$errors[] = sprintf(
'Fetching class constant %s of deprecated class %s.',
$constantName,
$referencedClass
);
} else {
$errors[] = sprintf(
"Fetching class constant %s of deprecated class %s:\n%s",
$constantName,
$referencedClass,
$classDescription
);
}
}
if (strtolower($constantName) === 'class') {
continue;
}
if (!$class->hasConstant($constantName)) {
continue;
}
$constantReflection = $class->getConstant($constantName);
if (!$constantReflection->isDeprecated()->yes()) {
continue;
}
$description = $constantReflection->getDeprecatedDescription();
if ($description === null) {
$errors[] = sprintf(
'Fetching deprecated class constant %s of class %s.',
$constantName,
$referencedClass
);
} else {
$errors[] = sprintf(
"Fetching deprecated class constant %s of class %s:\n%s",
$constantName,
$referencedClass,
$description
);
}
}
return $errors;
}
}

View File

@@ -0,0 +1,70 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\ConstFetch;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use function sprintf;
use const PHP_VERSION_ID;
/**
* @implements Rule<ConstFetch>
*/
class FetchingDeprecatedConstRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
/** @var array<string,string> */
private $deprecatedConstants = [];
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
// phpcs:ignore SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed
if (PHP_VERSION_ID >= 70300) {
$this->deprecatedConstants['FILTER_FLAG_SCHEME_REQUIRED'] = 'Use of constant %s is deprecated since PHP 7.3.';
$this->deprecatedConstants['FILTER_FLAG_HOST_REQUIRED'] = 'Use of constant %s is deprecated since PHP 7.3.';
}
}
public function getNodeType(): string
{
return ConstFetch::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if (!$this->reflectionProvider->hasConstant($node->name, $scope)) {
return [];
}
$constantReflection = $this->reflectionProvider->getConstant($node->name, $scope);
if ($constantReflection->isDeprecated()->yes()) {
return [sprintf(
$constantReflection->getDeprecatedDescription() ?? 'Use of constant %s is deprecated.',
$constantReflection->getName()
)];
}
if (isset($this->deprecatedConstants[$constantReflection->getName()])) {
return [sprintf(
$this->deprecatedConstants[$constantReflection->getName()],
$constantReflection->getName()
)];
}
return [];
}
}

View File

@@ -0,0 +1,100 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<Class_>
*/
class ImplementationOfDeprecatedInterfaceRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return Class_::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
$errors = [];
$className = isset($node->namespacedName)
? (string) $node->namespacedName
: (string) $node->name;
try {
$class = $this->reflectionProvider->getClass($className);
} catch (ClassNotFoundException $e) {
return [];
}
if ($class->isDeprecated()) {
return [];
}
foreach ($node->implements as $implement) {
$interfaceName = (string) $implement;
try {
$interface = $this->reflectionProvider->getClass($interfaceName);
if ($interface->isDeprecated()) {
$description = $interface->getDeprecatedDescription();
if (!$class->isAnonymous()) {
if ($description === null) {
$errors[] = sprintf(
'Class %s implements deprecated interface %s.',
$className,
$interfaceName
);
} else {
$errors[] = sprintf(
"Class %s implements deprecated interface %s:\n%s",
$className,
$interfaceName,
$description
);
}
} else {
if ($description === null) {
$errors[] = sprintf(
'Anonymous class implements deprecated interface %s.',
$interfaceName
);
} else {
$errors[] = sprintf(
"Anonymous class implements deprecated interface %s:\n%s",
$interfaceName,
$description
);
}
}
}
} catch (ClassNotFoundException $e) {
// Other rules will notify if the interface is not found
}
}
return $errors;
}
}

View File

@@ -0,0 +1,97 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<Class_>
*/
class InheritanceOfDeprecatedClassRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return Class_::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
if ($node->extends === null) {
return [];
}
$errors = [];
$className = isset($node->namespacedName)
? (string) $node->namespacedName
: (string) $node->name;
try {
$class = $this->reflectionProvider->getClass($className);
} catch (ClassNotFoundException $e) {
return [];
}
$parentClassName = (string) $node->extends;
try {
$parentClass = $this->reflectionProvider->getClass($parentClassName);
$description = $parentClass->getDeprecatedDescription();
if ($parentClass->isDeprecated()) {
if (!$class->isAnonymous()) {
if ($description === null) {
$errors[] = sprintf(
'Class %s extends deprecated class %s.',
$className,
$parentClassName
);
} else {
$errors[] = sprintf(
"Class %s extends deprecated class %s:\n%s",
$className,
$parentClassName,
$description
);
}
} else {
if ($description === null) {
$errors[] = sprintf(
'Anonymous class extends deprecated class %s.',
$parentClassName
);
} else {
$errors[] = sprintf(
"Anonymous class extends deprecated class %s:\n%s",
$parentClassName,
$description
);
}
}
}
} catch (ClassNotFoundException $e) {
// Other rules will notify if the interface is not found
}
return $errors;
}
}

View File

@@ -0,0 +1,87 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Stmt\Interface_;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<Interface_>
*/
class InheritanceOfDeprecatedInterfaceRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return Interface_::class;
}
public function processNode(Node $node, Scope $scope): array
{
if ($node->extends === null) {
return [];
}
$interfaceName = isset($node->namespacedName)
? (string) $node->namespacedName
: (string) $node->name;
try {
$interface = $this->reflectionProvider->getClass($interfaceName);
} catch (ClassNotFoundException $e) {
return [];
}
if ($interface->isDeprecated()) {
return [];
}
$errors = [];
foreach ($node->extends as $parentInterfaceName) {
$parentInterfaceName = (string) $parentInterfaceName;
try {
$parentInterface = $this->reflectionProvider->getClass($parentInterfaceName);
if (!$parentInterface->isDeprecated()) {
continue;
}
$description = $parentInterface->getDeprecatedDescription();
if ($description === null) {
$errors[] = sprintf(
'Interface %s extends deprecated interface %s.',
$interfaceName,
$parentInterfaceName
);
} else {
$errors[] = sprintf(
"Interface %s extends deprecated interface %s:\n%s",
$interfaceName,
$parentInterfaceName,
$description
);
}
} catch (ClassNotFoundException $e) {
// Other rules will notify if the interface is not found
}
}
return $errors;
}
}

View File

@@ -0,0 +1,104 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use function sprintf;
/**
* @implements Rule<New_>
*/
class InstantiationOfDeprecatedClassRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
/** @var RuleLevelHelper */
private $ruleLevelHelper;
public function __construct(ReflectionProvider $reflectionProvider, RuleLevelHelper $ruleLevelHelper)
{
$this->reflectionProvider = $reflectionProvider;
$this->ruleLevelHelper = $ruleLevelHelper;
}
public function getNodeType(): string
{
return New_::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
$referencedClasses = [];
if ($node->class instanceof Name) {
$referencedClasses[] = $scope->resolveName($node->class);
} elseif ($node->class instanceof Class_) {
if (!isset($node->class->namespacedName)) {
return [];
}
$referencedClasses[] = $scope->resolveName($node->class->namespacedName);
} else {
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$node->class,
'', // We don't care about the error message
static function (): bool {
return true;
}
);
if ($classTypeResult->getType() instanceof ErrorType) {
return [];
}
$referencedClasses = $classTypeResult->getReferencedClasses();
}
$errors = [];
foreach ($referencedClasses as $referencedClass) {
try {
$class = $this->reflectionProvider->getClass($referencedClass);
} catch (ClassNotFoundException $e) {
continue;
}
if (!$class->isDeprecated()) {
continue;
}
$description = $class->getDeprecatedDescription();
if ($description === null) {
$errors[] = sprintf(
'Instantiation of deprecated class %s.',
$referencedClass
);
} else {
$errors[] = sprintf(
"Instantiation of deprecated class %s:\n%s",
$referencedClass,
$description
);
}
}
return $errors;
}
}

View File

@@ -0,0 +1,92 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassMethodNode;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<InClassMethodNode>
*/
class TypeHintDeprecatedInClassMethodSignatureRule implements Rule
{
/** @var DeprecatedClassHelper */
private $deprecatedClassHelper;
public function __construct(DeprecatedClassHelper $deprecatedClassHelper)
{
$this->deprecatedClassHelper = $deprecatedClassHelper;
}
public function getNodeType(): string
{
return InClassMethodNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
$method = $node->getMethodReflection();
$methodSignature = ParametersAcceptorSelector::selectSingle($method->getVariants());
$errors = [];
foreach ($methodSignature->getParameters() as $parameter) {
$deprecatedClasses = $this->deprecatedClassHelper->filterDeprecatedClasses($parameter->getType()->getReferencedClasses());
foreach ($deprecatedClasses as $deprecatedClass) {
if ($method->getDeclaringClass()->isAnonymous()) {
$errors[] = sprintf(
'Parameter $%s of method %s() in anonymous class has typehint with deprecated %s %s%s',
$parameter->getName(),
$method->getName(),
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
} else {
$errors[] = sprintf(
'Parameter $%s of method %s::%s() has typehint with deprecated %s %s%s',
$parameter->getName(),
$method->getDeclaringClass()->getName(),
$method->getName(),
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
}
}
}
$deprecatedClasses = $this->deprecatedClassHelper->filterDeprecatedClasses($methodSignature->getReturnType()->getReferencedClasses());
foreach ($deprecatedClasses as $deprecatedClass) {
if ($method->getDeclaringClass()->isAnonymous()) {
$errors[] = sprintf(
'Return type of method %s() in anonymous class has typehint with deprecated %s %s%s',
$method->getName(),
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
} else {
$errors[] = sprintf(
'Return type of method %s::%s() has typehint with deprecated %s %s%s',
$method->getDeclaringClass()->getName(),
$method->getName(),
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
}
}
return $errors;
}
}

View File

@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClosureNode;
use PHPStan\Rules\Rule;
use PHPStan\ShouldNotHappenException;
use function sprintf;
/**
* @implements Rule<InClosureNode>
*/
class TypeHintDeprecatedInClosureSignatureRule implements Rule
{
/** @var DeprecatedClassHelper */
private $deprecatedClassHelper;
public function __construct(DeprecatedClassHelper $deprecatedClassHelper)
{
$this->deprecatedClassHelper = $deprecatedClassHelper;
}
public function getNodeType(): string
{
return InClosureNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
$functionSignature = $scope->getAnonymousFunctionReflection();
if ($functionSignature === null) {
throw new ShouldNotHappenException();
}
$errors = [];
foreach ($functionSignature->getParameters() as $parameter) {
$deprecatedClasses = $this->deprecatedClassHelper->filterDeprecatedClasses($parameter->getType()->getReferencedClasses());
foreach ($deprecatedClasses as $deprecatedClass) {
$errors[] = sprintf(
'Parameter $%s of anonymous function has typehint with deprecated %s %s%s',
$parameter->getName(),
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
}
}
$deprecatedClasses = $this->deprecatedClassHelper->filterDeprecatedClasses($functionSignature->getReturnType()->getReferencedClasses());
foreach ($deprecatedClasses as $deprecatedClass) {
$errors[] = sprintf(
'Return type of anonymous function has typehint with deprecated %s %s%s',
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
}
return $errors;
}
}

View File

@@ -0,0 +1,73 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InFunctionNode;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Rules\Rule;
use PHPStan\ShouldNotHappenException;
use function sprintf;
/**
* @implements Rule<InFunctionNode>
*/
class TypeHintDeprecatedInFunctionSignatureRule implements Rule
{
/** @var DeprecatedClassHelper */
private $deprecatedClassHelper;
public function __construct(DeprecatedClassHelper $deprecatedClassHelper)
{
$this->deprecatedClassHelper = $deprecatedClassHelper;
}
public function getNodeType(): string
{
return InFunctionNode::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
$function = $scope->getFunction();
if ($function === null) {
throw new ShouldNotHappenException();
}
$functionSignature = ParametersAcceptorSelector::selectSingle($function->getVariants());
$errors = [];
foreach ($functionSignature->getParameters() as $parameter) {
$deprecatedClasses = $this->deprecatedClassHelper->filterDeprecatedClasses($parameter->getType()->getReferencedClasses());
foreach ($deprecatedClasses as $deprecatedClass) {
$errors[] = sprintf(
'Parameter $%s of function %s() has typehint with deprecated %s %s%s',
$parameter->getName(),
$function->getName(),
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
}
}
$deprecatedClasses = $this->deprecatedClassHelper->filterDeprecatedClasses($functionSignature->getReturnType()->getReferencedClasses());
foreach ($deprecatedClasses as $deprecatedClass) {
$errors[] = sprintf(
'Return type of function %s() has typehint with deprecated %s %s%s',
$function->getName(),
$this->deprecatedClassHelper->getClassType($deprecatedClass),
$deprecatedClass->getName(),
$this->deprecatedClassHelper->getClassDeprecationDescription($deprecatedClass)
);
}
return $errors;
}
}

View File

@@ -0,0 +1,52 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Expr\Cast;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use function sprintf;
/**
* @implements Rule<Cast>
*/
class UsageOfDeprecatedCastRule implements Rule
{
public function getNodeType(): string
{
return Cast::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
$castedType = $scope->getType($node->expr);
if (! $castedType->hasMethod('__toString')->yes()) {
return [];
}
$method = $castedType->getMethod('__toString', $scope);
if (! $method->isDeprecated()->yes()) {
return [];
}
$description = $method->getDeprecatedDescription();
if ($description === null) {
return [sprintf(
'Casting class %s to string is deprecated.',
$method->getDeclaringClass()->getName()
)];
}
return [sprintf(
"Casting class %s to string is deprecated.:\n%s",
$method->getDeclaringClass()->getName(),
$description
)];
}
}

View File

@@ -0,0 +1,79 @@
<?php declare(strict_types = 1);
namespace PHPStan\Rules\Deprecations;
use PhpParser\Node;
use PhpParser\Node\Stmt\TraitUse;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\ShouldNotHappenException;
use function sprintf;
/**
* @implements Rule<TraitUse>
*/
class UsageOfDeprecatedTraitRule implements Rule
{
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider)
{
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType(): string
{
return TraitUse::class;
}
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}
$classReflection = $scope->getClassReflection();
if ($classReflection === null) {
throw new ShouldNotHappenException();
}
$errors = [];
$className = $classReflection->getName();
foreach ($node->traits as $traitNameNode) {
$traitName = (string) $traitNameNode;
try {
$trait = $this->reflectionProvider->getClass($traitName);
if (!$trait->isDeprecated()) {
continue;
}
$description = $trait->getDeprecatedDescription();
if ($description === null) {
$errors[] = sprintf(
'Usage of deprecated trait %s in class %s.',
$traitName,
$className
);
} else {
$errors[] = sprintf(
"Usage of deprecated trait %s in class %s:\n%s",
$traitName,
$className,
$description
);
}
} catch (ClassNotFoundException $e) {
continue;
}
}
return $errors;
}
}