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,27 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
[*.{php,phpt}]
indent_style = tab
indent_size = 4
[*.xml]
indent_style = tab
indent_size = 4
[*.neon]
indent_style = tab
indent_size = 4
[*.{yaml,yml}]
indent_style = space
indent_size = 2
[composer.json]
indent_style = tab
indent_size = 4

View File

@@ -0,0 +1,38 @@
# Rules for detecting usage of deprecated classes, methods, properties, constants and traits.
[![Build](https://github.com/phpstan/phpstan-deprecation-rules/workflows/Build/badge.svg)](https://github.com/phpstan/phpstan-deprecation-rules/actions)
[![Latest Stable Version](https://poser.pugx.org/phpstan/phpstan-deprecation-rules/v/stable)](https://packagist.org/packages/phpstan/phpstan-deprecation-rules)
[![License](https://poser.pugx.org/phpstan/phpstan-deprecation-rules/license)](https://packagist.org/packages/phpstan/phpstan-deprecation-rules)
* [PHPStan](https://phpstan.org/)
## Installation
To use this extension, require it in [Composer](https://getcomposer.org/):
```
composer require --dev phpstan/phpstan-deprecation-rules
```
If you also install [phpstan/extension-installer](https://github.com/phpstan/extension-installer) then you're all set!
<details>
<summary>Manual installation</summary>
If you don't want to use `phpstan/extension-installer`, include rules.neon in your project's PHPStan config:
```
includes:
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
```
</details>
## Deprecating code you don't own
This extension emits deprecation warnings on code, which uses properties/functions/methods/classes which are annotated as `@deprecated`.
In case you don't own the code which you want to be considered deprecated, use [PHPStan Stub Files](https://phpstan.org/user-guide/stub-files) to declare deprecations for vendor files like:
```
/** @deprecated */
class ThirdPartyClass {}
```

View File

@@ -0,0 +1,12 @@
{
"require-dev": {
"consistence-community/coding-standard": "^3.10",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"slevomat/coding-standard": "^7.0"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}

View File

@@ -0,0 +1,322 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4485bbedba7bcc71ace5f69dbb9b6c47",
"packages": [],
"packages-dev": [
{
"name": "consistence-community/coding-standard",
"version": "3.11.1",
"source": {
"type": "git",
"url": "https://github.com/consistence-community/coding-standard.git",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consistence-community/coding-standard/zipball/4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"shasum": ""
},
"require": {
"php": ">=7.4",
"slevomat/coding-standard": "~7.0",
"squizlabs/php_codesniffer": "~3.6.0"
},
"replace": {
"consistence/coding-standard": "3.10.*"
},
"require-dev": {
"phing/phing": "2.16.4",
"php-parallel-lint/php-parallel-lint": "1.3.0",
"phpunit/phpunit": "9.5.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Consistence\\": [
"Consistence"
]
},
"classmap": [
"Consistence"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Vašek Purchart",
"email": "me@vasekpurchart.cz",
"homepage": "http://vasekpurchart.cz"
}
],
"description": "Consistence - Coding Standard - PHP Code Sniffer rules",
"keywords": [
"Coding Standard",
"PHPCodeSniffer",
"codesniffer",
"coding",
"cs",
"phpcs",
"ruleset",
"sniffer",
"standard"
],
"support": {
"issues": "https://github.com/consistence-community/coding-standard/issues",
"source": "https://github.com/consistence-community/coding-standard/tree/3.11.1"
},
"time": "2021-05-03T18:13:22+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "981cc368a216c988e862a75e526b6076987d1b50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50",
"reference": "981cc368a216c988e862a75e526b6076987d1b50",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1"
},
"time": "2022-05-05T11:32:40+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.2.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.5.1",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.3",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.7.1",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0|1.1.1",
"phpstan/phpstan-strict-rules": "1.2.3",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.20"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.2.1"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-05-25T10:58:12+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.6.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2021-12-12T21:44:58+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

View File

@@ -0,0 +1,43 @@
{
"name": "phpstan/phpstan-deprecation-rules",
"type": "phpstan-extension",
"description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
"license": [
"MIT"
],
"require": {
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.10"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-php-parser": "^1.1",
"phpunit/phpunit": "^9.5"
},
"config": {
"platform": {
"php": "7.4.6"
},
"sort-packages": true
},
"extra": {
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"autoload": {
"psr-4": {
"PHPStan\\": "src/"
}
},
"autoload-dev": {
"classmap": [
"tests/"
]
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@@ -0,0 +1,24 @@
parameters:
deprecationRulesInstalled: true
services:
-
class: PHPStan\Rules\Deprecations\DeprecatedClassHelper
rules:
- PHPStan\Rules\Deprecations\AccessDeprecatedPropertyRule
- PHPStan\Rules\Deprecations\AccessDeprecatedStaticPropertyRule
- PHPStan\Rules\Deprecations\CallToDeprecatedFunctionRule
- PHPStan\Rules\Deprecations\CallToDeprecatedMethodRule
- PHPStan\Rules\Deprecations\CallToDeprecatedStaticMethodRule
- PHPStan\Rules\Deprecations\FetchingClassConstOfDeprecatedClassRule
- PHPStan\Rules\Deprecations\FetchingDeprecatedConstRule
- PHPStan\Rules\Deprecations\ImplementationOfDeprecatedInterfaceRule
- PHPStan\Rules\Deprecations\InheritanceOfDeprecatedClassRule
- PHPStan\Rules\Deprecations\InheritanceOfDeprecatedInterfaceRule
- PHPStan\Rules\Deprecations\InstantiationOfDeprecatedClassRule
- PHPStan\Rules\Deprecations\TypeHintDeprecatedInClassMethodSignatureRule
- PHPStan\Rules\Deprecations\TypeHintDeprecatedInClosureSignatureRule
- PHPStan\Rules\Deprecations\TypeHintDeprecatedInFunctionSignatureRule
- PHPStan\Rules\Deprecations\UsageOfDeprecatedCastRule
- PHPStan\Rules\Deprecations\UsageOfDeprecatedTraitRule

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;
}
}