mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Fix #358, don’t emit PropertyNotSetInConstructor on public final classes/methods
This commit is contained in:
parent
0c2b2b69b3
commit
0ea6540018
@ -1150,7 +1150,7 @@ class CallChecker
|
||||
$class_checker = $source->getSource();
|
||||
|
||||
if ($class_checker instanceof ClassLikeChecker &&
|
||||
$method_storage->visibility === ClassLikeChecker::VISIBILITY_PRIVATE
|
||||
($method_storage->visibility === ClassLikeChecker::VISIBILITY_PRIVATE || $method_storage->final)
|
||||
) {
|
||||
$local_vars_in_scope = [];
|
||||
$local_vars_possibly_in_scope = [];
|
||||
|
@ -105,6 +105,11 @@ class ClassLikeStorage
|
||||
*/
|
||||
public $abstract = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $final = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
|
@ -22,4 +22,9 @@ class MethodStorage extends FunctionLikeStorage
|
||||
* @var int
|
||||
*/
|
||||
public $visibility;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $final;
|
||||
}
|
||||
|
@ -237,6 +237,7 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
|
||||
if ($node instanceof PhpParser\Node\Stmt\Class_) {
|
||||
$storage->abstract = (bool)$node->isAbstract();
|
||||
$storage->final = (bool)$node->isFinal();
|
||||
|
||||
$this->project_checker->addFullyQualifiedClassName($fq_classlike_name, $this->file_path);
|
||||
|
||||
@ -588,6 +589,8 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
/** @var bool */
|
||||
$storage->abstract = $stmt->isAbstract();
|
||||
|
||||
$storage->final = $class_storage->final || $stmt->isFinal();
|
||||
|
||||
if ($stmt->isPrivate()) {
|
||||
$storage->visibility = ClassLikeChecker::VISIBILITY_PRIVATE;
|
||||
} elseif ($stmt->isProtected()) {
|
||||
|
@ -441,49 +441,49 @@ class PropertyTypeTest extends TestCase
|
||||
],
|
||||
'extendsClassWithPrivateConstructorSet' => [
|
||||
'<?php
|
||||
namespace Q;
|
||||
namespace Q;
|
||||
|
||||
class Base
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $aString;
|
||||
class Base
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $aString;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->aString = "aa";
|
||||
echo($this->aString);
|
||||
}
|
||||
}
|
||||
public function __construct()
|
||||
{
|
||||
$this->aString = "aa";
|
||||
echo($this->aString);
|
||||
}
|
||||
}
|
||||
|
||||
class Descendant extends Base
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $aBool;
|
||||
class Descendant extends Base
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $aBool;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->aBool = true;
|
||||
}
|
||||
}',
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->aBool = true;
|
||||
}
|
||||
}',
|
||||
],
|
||||
'extendsClassWithPrivateAndException' => [
|
||||
'<?php
|
||||
abstract class A extends \Exception {
|
||||
/** @var string **/
|
||||
private $p;
|
||||
abstract class A extends \Exception {
|
||||
/** @var string **/
|
||||
private $p;
|
||||
|
||||
/** @param string $p **/
|
||||
final public function __construct($p) {
|
||||
$this->p = $p;
|
||||
}
|
||||
}
|
||||
/** @param string $p **/
|
||||
final public function __construct($p) {
|
||||
$this->p = $p;
|
||||
}
|
||||
}
|
||||
|
||||
final class B extends A {}',
|
||||
final class B extends A {}',
|
||||
],
|
||||
'setInAbstractMethod' => [
|
||||
'<?php
|
||||
@ -511,6 +511,74 @@ final class B extends A {}',
|
||||
'PropertyNotSetInConstructor' => Config::REPORT_INFO,
|
||||
],
|
||||
],
|
||||
'setInFinalMethod' => [
|
||||
'<?php
|
||||
class C
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $a;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $b;
|
||||
|
||||
/**
|
||||
* @param string[] $opts
|
||||
* @psalm-param array{a:string,b:string} $opts
|
||||
*/
|
||||
public function __construct(array $opts)
|
||||
{
|
||||
$this->setOptions($opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $opts
|
||||
* @psalm-param array{a:string,b:string} $opts
|
||||
*/
|
||||
final public function setOptions(array $opts): void
|
||||
{
|
||||
$this->a = $opts["a"] ?? "defaultA";
|
||||
$this->b = $opts["b"] ?? "defaultB";
|
||||
}
|
||||
}',
|
||||
],
|
||||
'setInFinalClass' => [
|
||||
'<?php
|
||||
final class C
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $a;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $b;
|
||||
|
||||
/**
|
||||
* @param string[] $opts
|
||||
* @psalm-param array{a:string,b:string} $opts
|
||||
*/
|
||||
public function __construct(array $opts)
|
||||
{
|
||||
$this->setOptions($opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $opts
|
||||
* @psalm-param array{a:string,b:string} $opts
|
||||
*/
|
||||
public function setOptions(array $opts): void
|
||||
{
|
||||
$this->a = $opts["a"] ?? "defaultA";
|
||||
$this->b = $opts["b"] ?? "defaultB";
|
||||
}
|
||||
}',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user