Skip to content

Feature/deprecations #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9c20c6a
Add rules for checking deprecated functions and methods
iluuu1994 Dec 13, 2017
751c048
Implement rule to check deprecated properties
iluuu1994 Dec 13, 2017
96f3edb
Implement warning when implementing a deprecated interface
iluuu1994 Dec 15, 2017
ae9dbc8
Implement warnings when accessing deprecated static properties
iluuu1994 Dec 15, 2017
4809b5b
Also test traits in AccessDeprecatedStaticPropertyRule
iluuu1994 Dec 15, 2017
6d4c7b1
Add tests for deprecated properties from traits
iluuu1994 Dec 16, 2017
6fab32e
Add tests for deprecated methods from traits
iluuu1994 Dec 16, 2017
a2ef842
Fix spacing in deprecation tests
iluuu1994 Dec 16, 2017
e104c5b
Add rule to notify when inheriting from a deprecated class
iluuu1994 Dec 16, 2017
c140a25
Add rules to warn when instantiating deprecated classes
iluuu1994 Dec 16, 2017
2da52d1
Fix formatting and naming
iluuu1994 Dec 16, 2017
2ca155a
Add rule to notify when using a deprecated trait
iluuu1994 Dec 16, 2017
7c4da9b
Add support for parent static method calls in deprecation check
iluuu1994 Dec 16, 2017
31a8dc2
Add check for false positive in static parent method call
iluuu1994 Dec 16, 2017
40a2227
Fix possible null pointer in CallToDeprecatedStaticMethodRule
iluuu1994 Dec 16, 2017
49f3352
Add test to notify when fetching class constant of deprecated class
iluuu1994 Dec 16, 2017
b439ab4
Notify when calling method on deprecated class
iluuu1994 Dec 18, 2017
7ce5d3e
Fix phpcs errors
iluuu1994 May 6, 2018
74b25d0
Ignore all deprecation errors in deprecated scopes
iluuu1994 May 6, 2018
a46a26a
Remove `echo` in tests
iluuu1994 May 6, 2018
b9755b8
Fix incorrectly cased file name
iluuu1994 May 6, 2018
afc0d17
Fix errors reported by PHPStan
iluuu1994 May 6, 2018
5af1a6d
Move DeprecatedScopeHelper to Analyzer namespace
iluuu1994 May 6, 2018
e7d6aba
Add deprecation rules to rules.neon file
iluuu1994 May 6, 2018
e84b84b
Fix issues with new PhpParser version
iluuu1994 Jun 22, 2018
e5a4408
Fix code review issues for deprecation feature
iluuu1994 Jun 22, 2018
7a8f54b
Use RuleLevelHelper::findTypeToCheck when symbol is not a Name
iluuu1994 Jun 23, 2018
028e681
Extend DeprecatedScopeHelper to check traits
iluuu1994 Jun 23, 2018
0e86531
Add rule to check for inheritance of deprecated interfaces in interfaces
iluuu1994 Jun 23, 2018
6cd26a2
Add deprecation feature to README.md
iluuu1994 Jun 23, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* Always true `instanceof`, type-checking `is_*` functions and strict comparisons `===`/`!==`. These checks can be turned off by setting `checkAlwaysTrueInstanceof`/`checkAlwaysTrueCheckTypeFunctionCall`/`checkAlwaysTrueStrictComparison` to false.
* Correct case for referenced and called function names.
* Correct case for inherited and implemented method names.
* Disallows the usage of deprecated code.

Additional rules are coming in subsequent releases!

Expand Down
11 changes: 11 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ rules:
- PHPStan\Rules\BooleansInConditions\BooleanInElseIfConditionRule
- PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule
- PHPStan\Rules\BooleansInConditions\BooleanInTernaryOperatorRule
- 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\ImplementationOfDeprecatedInterfaceRule
- PHPStan\Rules\Deprecations\InheritanceOfDeprecatedClassRule
- PHPStan\Rules\Deprecations\InheritanceOfDeprecatedInterfaceRule
- PHPStan\Rules\Deprecations\InstantiationOfDeprecatedClassRule
- PHPStan\Rules\Deprecations\UsageOfDeprecatedTraitRule
- PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule
- PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule
- PHPStan\Rules\Functions\MissingFunctionParameterTypehintRule
Expand Down
74 changes: 74 additions & 0 deletions src/Rules/Deprecations/AccessDeprecatedPropertyRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?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\Broker;
use PHPStan\Reflection\DeprecatableReflection;
use PHPStan\Type\TypeUtils;

class AccessDeprecatedPropertyRule implements \PHPStan\Rules\Rule
{

/** @var Broker */
private $broker;

public function __construct(Broker $broker)
{
$this->broker = $broker;
}

public function getNodeType(): string
{
return PropertyFetch::class;
}

/**
* @param PropertyFetch $node
* @param \PHPStan\Analyser\Scope $scope
* @return string[] errors
*/
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 = TypeUtils::getDirectClassNames($propertyAccessedOnType);

foreach ($referencedClasses as $referencedClass) {
try {
$classReflection = $this->broker->getClass($referencedClass);
$propertyReflection = $classReflection->getProperty($propertyName, $scope);

if (!$propertyReflection instanceof DeprecatableReflection) {
continue;
}

if ($propertyReflection->isDeprecated()) {
return [sprintf(
'Access to deprecated property $%s of class %s.',
$propertyName,
$propertyReflection->getDeclaringClass()->getName()
)];
}
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
// Other rules will notify if the class is not found
} catch (\PHPStan\Reflection\MissingPropertyFromReflectionException $e) {
// Other rules will notify if the property is not found
}
}

return [];
}

}
95 changes: 95 additions & 0 deletions src/Rules/Deprecations/AccessDeprecatedStaticPropertyRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?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\Broker;
use PHPStan\Reflection\DeprecatableReflection;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Type;

class AccessDeprecatedStaticPropertyRule implements \PHPStan\Rules\Rule
{

/** @var Broker */
private $broker;

/** @var RuleLevelHelper */
private $ruleLevelHelper;

public function __construct(Broker $broker, RuleLevelHelper $ruleLevelHelper)
{
$this->broker = $broker;
$this->ruleLevelHelper = $ruleLevelHelper;
}

public function getNodeType(): string
{
return StaticPropertyFetch::class;
}

/**
* @param StaticPropertyFetch $node
* @param \PHPStan\Analyser\Scope $scope
* @return string[] errors
*/
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
function (Type $type) use ($propertyName) {
return $type->canAccessProperties()->yes() && $type->hasProperty($propertyName);
}
);

if ($classTypeResult->getType() instanceof ErrorType) {
return [];
}

$referencedClasses = $classTypeResult->getReferencedClasses();
}

foreach ($referencedClasses as $referencedClass) {
try {
$class = $this->broker->getClass($referencedClass);
$property = $class->getProperty($propertyName, $scope);
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
continue;
} catch (\PHPStan\Reflection\MissingPropertyFromReflectionException $e) {
continue;
}

if ($property instanceof DeprecatableReflection && $property->isDeprecated()) {
return [sprintf(
'Access to deprecated static property $%s of class %s.',
$propertyName,
$referencedClass
)];
}
}

return [];
}

}
58 changes: 58 additions & 0 deletions src/Rules/Deprecations/CallToDeprecatedFunctionRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Deprecations;

use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;

class CallToDeprecatedFunctionRule implements \PHPStan\Rules\Rule
{

/** @var Broker */
private $broker;

public function __construct(Broker $broker)
{
$this->broker = $broker;
}

public function getNodeType(): string
{
return FuncCall::class;
}

/**
* @param FuncCall $node
* @param \PHPStan\Analyser\Scope $scope
* @return string[] errors
*/
public function processNode(Node $node, Scope $scope): array
{
if (DeprecatedScopeHelper::isScopeDeprecated($scope)) {
return [];
}

if (!($node->name instanceof \PhpParser\Node\Name)) {
return [];
}

try {
$function = $this->broker->getFunction($node->name, $scope);
} catch (\PHPStan\Broker\FunctionNotFoundException $e) {
// Other rules will notify if the function is not found
return [];
}

if ($function->isDeprecated()) {
return [sprintf(
'Call to deprecated function %s().',
$function->getName()
)];
}

return [];
}

}
74 changes: 74 additions & 0 deletions src/Rules/Deprecations/CallToDeprecatedMethodRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?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\Broker;
use PHPStan\Reflection\DeprecatableReflection;
use PHPStan\Type\TypeUtils;

class CallToDeprecatedMethodRule implements \PHPStan\Rules\Rule
{

/** @var Broker */
private $broker;

public function __construct(Broker $broker)
{
$this->broker = $broker;
}

public function getNodeType(): string
{
return MethodCall::class;
}

/**
* @param MethodCall $node
* @param \PHPStan\Analyser\Scope $scope
* @return string[] errors
*/
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 = TypeUtils::getDirectClassNames($methodCalledOnType);

foreach ($referencedClasses as $referencedClass) {
try {
$classReflection = $this->broker->getClass($referencedClass);
$methodReflection = $classReflection->getMethod($methodName, $scope);

if (!$methodReflection instanceof DeprecatableReflection) {
continue;
}

if ($methodReflection->isDeprecated()) {
return [sprintf(
'Call to deprecated method %s() of class %s.',
$methodReflection->getName(),
$methodReflection->getDeclaringClass()->getName()
)];
}
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
// Other rules will notify if the class is not found
} catch (\PHPStan\Reflection\MissingMethodFromReflectionException $e) {
// Other rules will notify if the the method is not found
}
}

return [];
}

}
Loading