1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Check deprecated properties on $this->prop reads

Fixes vimeo/psalm#6118
This commit is contained in:
Bruce Weirdan 2021-07-17 01:20:35 +03:00
parent f015c30a43
commit af5cdb4dd4
No known key found for this signature in database
GPG Key ID: CFC3AAB181751B0D
3 changed files with 84 additions and 13 deletions

View File

@ -344,6 +344,9 @@ class AtomicPropertyFetchAnalyzer
}
}
// FIXME: the following line look superfluous, but removing it makes
// Psalm\Tests\PropertyTypeTest::testValidCode with data set "callInParentContext"
// fail
$declaring_property_class = $codebase->properties->getDeclaringClassForProperty(
$property_id,
true,
@ -380,20 +383,9 @@ class AtomicPropertyFetchAnalyzer
);
if (isset($declaring_class_storage->properties[$prop_name])) {
$property_storage = $declaring_class_storage->properties[$prop_name];
self::checkPropertyDeprecation($prop_name, $declaring_property_class, $stmt, $statements_analyzer);
if ($property_storage->deprecated) {
if (IssueBuffer::accepts(
new DeprecatedProperty(
$property_id . ' is marked deprecated',
new CodeLocation($statements_analyzer->getSource(), $stmt),
$property_id
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
}
$property_storage = $declaring_class_storage->properties[$prop_name];
if ($context->self && !NamespaceAnalyzer::isWithin($context->self, $property_storage->internal)) {
if (IssueBuffer::accepts(
@ -481,6 +473,36 @@ class AtomicPropertyFetchAnalyzer
}
}
public static function checkPropertyDeprecation(
string $prop_name,
string $declaring_property_class,
PhpParser\Node\Expr\PropertyFetch $stmt,
StatementsAnalyzer $statements_analyzer
): void {
$property_id = $declaring_property_class . '::$' . $prop_name;
$codebase = $statements_analyzer->getCodebase();
$declaring_class_storage = $codebase->classlike_storage_provider->get(
$declaring_property_class
);
if (isset($declaring_class_storage->properties[$prop_name])) {
$property_storage = $declaring_class_storage->properties[$prop_name];
if ($property_storage->deprecated) {
if (IssueBuffer::accepts(
new DeprecatedProperty(
$property_id . ' is marked deprecated',
new CodeLocation($statements_analyzer->getSource(), $stmt),
$property_id
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
}
}
}
private static function propertyFetchCanBeAnalyzed(
StatementsAnalyzer $statements_analyzer,
\Psalm\Codebase $codebase,

View File

@ -391,6 +391,7 @@ class InstancePropertyFetchAnalyzer
}
}
if (($stmt_var_type = $statements_analyzer->node_data->getType($stmt->var))
&& $stmt_var_type->hasObjectType()
&& $stmt->name instanceof PhpParser\Node\Identifier
@ -404,6 +405,7 @@ class InstancePropertyFetchAnalyzer
$property_id = $lhs_type_part->value . '::$' . $stmt->name->name;
$class_storage = $codebase->classlike_storage_provider->get($lhs_type_part->value);
AtomicPropertyFetchAnalyzer::processTaints(
@ -415,6 +417,21 @@ class InstancePropertyFetchAnalyzer
$in_assignment
);
$declaring_property_class = $codebase->properties->getDeclaringClassForProperty(
$property_id,
true,
$statements_analyzer
);
if ($declaring_property_class) {
AtomicPropertyFetchAnalyzer::checkPropertyDeprecation(
$stmt->name->name,
$declaring_property_class,
$stmt,
$statements_analyzer
);
}
$codebase->properties->propertyExists(
$property_id,
true,

View File

@ -168,6 +168,38 @@ class DeprecatedAnnotationTest extends TestCase
$a->foo = 5;',
'error_message' => 'DeprecatedProperty',
],
'deprecatedPropertyGetFromInsideTheClass' => [
'<?php
class A{
/**
* @deprecated
* @var ?int
*/
public $foo;
public function bar(): void
{
echo $this->foo;
}
}
',
'error_message' => 'DeprecatedProperty',
],
'deprecatedPropertySetFromInsideTheClass' => [
'<?php
class A{
/**
* @deprecated
* @var ?int
*/
public $foo;
public function bar(int $p): void
{
$this->foo = $p;
}
}
',
'error_message' => 'DeprecatedProperty',
],
'deprecatedClassConstant' => [
'<?php
/**