1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-29 20:28:59 +01:00

Add support for checking DeprecatedTrait and DeprecatedConstant

This commit is contained in:
Matt Brown 2018-08-10 13:25:25 -04:00
parent 2fee699d25
commit cb63f4f70f
14 changed files with 102 additions and 0 deletions

View File

@ -20,7 +20,9 @@
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />

View File

@ -20,7 +20,9 @@
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />

View File

@ -20,7 +20,9 @@
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />

View File

@ -20,7 +20,9 @@
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />

View File

@ -20,7 +20,9 @@
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />

View File

@ -20,7 +20,9 @@
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />

View File

@ -117,9 +117,11 @@
<xs:element name="ContinueOutsideLoop" type="IssueHandlerType" minOccurs="0" />
<xs:element name="ConflictingReferenceConstraint" type="IssueHandlerType" minOccurs="0" />
<xs:element name="DeprecatedClass" type="ClassIssueHandlerType" minOccurs="0" />
<xs:element name="DeprecatedConstant" type="ClassIssueHandlerType" minOccurs="0" />
<xs:element name="DeprecatedInterface" type="IssueHandlerType" minOccurs="0" />
<xs:element name="DeprecatedMethod" type="MethodIssueHandlerType" minOccurs="0" />
<xs:element name="DeprecatedProperty" type="PropertyIssueHandlerType" minOccurs="0" />
<xs:element name="DeprecatedTrait" type="ClassIssueHandlerType" minOccurs="0" />
<xs:element name="DocblockTypeContradiction" type="IssueHandlerType" minOccurs="0" />
<xs:element name="DuplicateArrayKey" type="IssueHandlerType" minOccurs="0" />
<xs:element name="DuplicateParam" type="IssueHandlerType" minOccurs="0" />

View File

@ -80,6 +80,19 @@ class A {}
new A();
```
### DeprecatedConstant
Emitted when referring to a deprecated constant:
```php
class A {
/** @deprecated */
const FOO = 'foo';
}
echo A::FOO;
```
### DeprecatedInterface
Emitted when referring to a deprecated interface
@ -118,6 +131,18 @@ class A {
(new A())->foo = 5;
```
### DeprecatedTrait
Emitted when referring to a deprecated trait:
```php
/** @deprecated */
trait T {}
class A {
use T;
}
```
### DocblockTypeContradiction
Emitted when conditional doesn't make sense given the docblock types supplied.

View File

@ -10,6 +10,7 @@ use Psalm\Config;
use Psalm\Context;
use Psalm\Issue\DeprecatedClass;
use Psalm\Issue\DeprecatedInterface;
use Psalm\Issue\DeprecatedTrait;
use Psalm\Issue\InaccessibleMethod;
use Psalm\Issue\MissingConstructor;
use Psalm\Issue\MissingPropertyType;
@ -687,6 +688,20 @@ class ClassChecker extends ClassLikeChecker
continue;
}
$trait_storage = $codebase->classlike_storage_provider->get($fq_trait_name);
if ($trait_storage->deprecated) {
if (IssueBuffer::accepts(
new DeprecatedTrait(
'Trait ' . $fq_trait_name . ' is deprecated',
new CodeLocation($this, $trait_name)
),
array_merge($storage->suppressed_issues, $this->getSuppressedIssues())
)) {
return false;
}
}
$trait_file_checker = $project_checker->getFileCheckerForClassLike($fq_trait_name);
$trait_node = $codebase->classlikes->getTraitNode($fq_trait_name);
$trait_aliases = $codebase->classlikes->getTraitAliases($fq_trait_name);

View File

@ -9,6 +9,7 @@ use Psalm\Checker\TraitChecker;
use Psalm\Codebase;
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\Issue\DeprecatedConstant;
use Psalm\Issue\InaccessibleClassConstant;
use Psalm\Issue\ParentNotFound;
use Psalm\Issue\UndefinedConstant;
@ -204,6 +205,20 @@ class ConstFetchChecker
return false;
}
$class_const_storage = $codebase->classlike_storage_provider->get($fq_class_name);
if (isset($class_const_storage->deprecated_constants[$stmt->name->name])) {
if (IssueBuffer::accepts(
new DeprecatedConstant(
'Constant ' . $const_id . ' is deprecated',
new CodeLocation($statements_checker->getSource(), $stmt)
),
$statements_checker->getSuppressedIssues()
)) {
// fall through
}
}
if (isset($class_constants[$stmt->name->name]) && $first_part_lc !== 'static') {
$stmt->inferredType = clone $class_constants[$stmt->name->name];
} else {

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class DeprecatedConstant extends CodeIssue
{
}

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class DeprecatedTrait extends CodeIssue
{
}

View File

@ -70,6 +70,11 @@ class ClassLikeStorage
*/
public $deprecated = false;
/**
* @var array<string, bool>
*/
public $deprecated_constants = [];
/**
* @var bool
*/

View File

@ -1766,6 +1766,18 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
+ $storage->private_class_constants
+ $storage->public_class_constants;
$comment = $stmt->getDocComment();
$deprecated = false;
$config = $this->config;
if ($comment && $comment->getText() && ($config->use_docblock_types || $config->use_docblock_property_types)) {
$comments = CommentChecker::parseDocComment($comment->getText(), 0);
if (isset($comments['specials']['deprecated'])) {
$deprecated = true;
}
}
foreach ($stmt->consts as $const) {
$const_type = StatementsChecker::getSimpleType(
$this->codebase,
@ -1797,6 +1809,10 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
$storage->aliases = $this->aliases;
}
if ($deprecated) {
$storage->deprecated_constants[$const->name->name] = true;
}
}
}