mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Fix crashes when analysing aliased class instances
This commit is contained in:
parent
e89425ad68
commit
947e3bf0f1
@ -194,11 +194,7 @@ class Codebase
|
||||
$this->loadAnalyzer();
|
||||
|
||||
$this->functions = new Internal\Codebase\Functions($providers->file_storage_provider, $this->reflection);
|
||||
$this->methods = new Internal\Codebase\Methods(
|
||||
$config,
|
||||
$providers->classlike_storage_provider,
|
||||
$providers->file_reference_provider
|
||||
);
|
||||
|
||||
$this->properties = new Internal\Codebase\Properties(
|
||||
$providers->classlike_storage_provider,
|
||||
$providers->file_reference_provider
|
||||
@ -207,9 +203,16 @@ class Codebase
|
||||
$this->classlikes = new Internal\Codebase\ClassLikes(
|
||||
$this->config,
|
||||
$providers->classlike_storage_provider,
|
||||
$this->scanner,
|
||||
$this->methods
|
||||
$this->scanner
|
||||
);
|
||||
|
||||
$this->methods = new Internal\Codebase\Methods(
|
||||
$config,
|
||||
$providers->classlike_storage_provider,
|
||||
$providers->file_reference_provider,
|
||||
$this->classlikes
|
||||
);
|
||||
|
||||
$this->populator = new Internal\Codebase\Populator(
|
||||
$config,
|
||||
$providers->classlike_storage_provider,
|
||||
|
@ -1026,6 +1026,8 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
|
||||
$fq_class_name = strpos($method_id, '::') !== false ? explode('::', $method_id)[0] : null;
|
||||
|
||||
if ($fq_class_name) {
|
||||
$fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name);
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
if ($class_storage->user_defined || $class_storage->stubbed) {
|
||||
|
@ -439,7 +439,7 @@ class ProjectAnalyzer
|
||||
throw new \UnexpectedValueException('Should not be checking references');
|
||||
}
|
||||
|
||||
$this->codebase->classlikes->checkClassReferences();
|
||||
$this->codebase->classlikes->checkClassReferences($this->codebase->methods);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -587,6 +587,8 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
self::collectSpecialInformation($source, $stmt->name->name, $context);
|
||||
}
|
||||
|
||||
$fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name);
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
if ($class_storage->template_types) {
|
||||
|
@ -188,6 +188,8 @@ class CallAnalyzer
|
||||
|
||||
list($fq_class_name, $method_name) = explode('::', $method_id);
|
||||
|
||||
$fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name);
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
$method_storage = null;
|
||||
|
@ -96,11 +96,6 @@ class ClassLikes
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var Methods
|
||||
*/
|
||||
private $methods;
|
||||
|
||||
/**
|
||||
* @var Scanner
|
||||
*/
|
||||
@ -112,13 +107,11 @@ class ClassLikes
|
||||
public function __construct(
|
||||
Config $config,
|
||||
ClassLikeStorageProvider $storage_provider,
|
||||
Scanner $scanner,
|
||||
Methods $methods
|
||||
Scanner $scanner
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->classlike_storage_provider = $storage_provider;
|
||||
$this->scanner = $scanner;
|
||||
$this->methods = $methods;
|
||||
|
||||
$this->collectPredefinedClassLikes();
|
||||
}
|
||||
@ -657,7 +650,7 @@ class ClassLikes
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function checkClassReferences()
|
||||
public function checkClassReferences(Methods $methods)
|
||||
{
|
||||
foreach ($this->existing_classlikes_lc as $fq_class_name_lc => $_) {
|
||||
try {
|
||||
@ -680,7 +673,7 @@ class ClassLikes
|
||||
// fall through
|
||||
}
|
||||
} else {
|
||||
$this->checkMethodReferences($classlike_storage);
|
||||
$this->checkMethodReferences($classlike_storage, $methods);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -748,7 +741,7 @@ class ClassLikes
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function checkMethodReferences(ClassLikeStorage $classlike_storage)
|
||||
private function checkMethodReferences(ClassLikeStorage $classlike_storage, Methods $methods)
|
||||
{
|
||||
foreach ($classlike_storage->appearing_method_ids as $method_name => $appearing_method_id) {
|
||||
list($appearing_fq_classlike_name) = explode('::', $appearing_method_id);
|
||||
@ -789,7 +782,7 @@ class ClassLikes
|
||||
|
||||
if (isset($classlike_storage->overridden_method_ids[$method_name_lc])) {
|
||||
foreach ($classlike_storage->overridden_method_ids[$method_name_lc] as $parent_method_id) {
|
||||
$parent_method_storage = $this->methods->getStorage($parent_method_id);
|
||||
$parent_method_storage = $methods->getStorage($parent_method_id);
|
||||
|
||||
if (!$parent_method_storage->abstract || $parent_method_storage->referencing_locations) {
|
||||
$has_parent_references = true;
|
||||
@ -842,7 +835,7 @@ class ClassLikes
|
||||
|
||||
if (isset($classlike_storage->overridden_method_ids[$method_name_lc])) {
|
||||
foreach ($classlike_storage->overridden_method_ids[$method_name_lc] as $parent_method_id) {
|
||||
$parent_method_storage = $this->methods->getStorage($parent_method_id);
|
||||
$parent_method_storage = $methods->getStorage($parent_method_id);
|
||||
|
||||
if (!$parent_method_storage->abstract
|
||||
&& isset($parent_method_storage->used_params[$offset])
|
||||
|
@ -37,17 +37,24 @@ class Methods
|
||||
*/
|
||||
public $file_reference_provider;
|
||||
|
||||
/**
|
||||
* @var ClassLikes
|
||||
*/
|
||||
private $classlikes;
|
||||
|
||||
/**
|
||||
* @param ClassLikeStorageProvider $storage_provider
|
||||
*/
|
||||
public function __construct(
|
||||
\Psalm\Config $config,
|
||||
ClassLikeStorageProvider $storage_provider,
|
||||
FileReferenceProvider $file_reference_provider
|
||||
FileReferenceProvider $file_reference_provider,
|
||||
ClassLikes $classlikes
|
||||
) {
|
||||
$this->classlike_storage_provider = $storage_provider;
|
||||
$this->config = $config;
|
||||
$this->file_reference_provider = $file_reference_provider;
|
||||
$this->classlikes = $classlikes;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,6 +79,8 @@ class Methods
|
||||
|
||||
$old_method_id = null;
|
||||
|
||||
$fq_class_name = $this->classlikes->getUnAliasedName($fq_class_name);
|
||||
|
||||
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
if (isset($class_storage->declaring_method_ids[$method_name])) {
|
||||
@ -271,6 +280,8 @@ class Methods
|
||||
if ($this->config->use_phpdoc_method_without_magic_or_parent) {
|
||||
list($original_fq_class_name, $original_method_name) = explode('::', $method_id);
|
||||
|
||||
$original_fq_class_name = $this->classlikes->getUnAliasedName($original_fq_class_name);
|
||||
|
||||
$original_class_storage = $this->classlike_storage_provider->get($original_fq_class_name);
|
||||
|
||||
if (isset($original_class_storage->pseudo_methods[strtolower($original_method_name)])) {
|
||||
@ -289,6 +300,8 @@ class Methods
|
||||
if (!$checked_for_pseudo_method) {
|
||||
list($original_fq_class_name, $original_method_name) = explode('::', $method_id);
|
||||
|
||||
$original_fq_class_name = $this->classlikes->getUnAliasedName($original_fq_class_name);
|
||||
|
||||
$original_class_storage = $this->classlike_storage_provider->get($original_fq_class_name);
|
||||
|
||||
if (isset($original_class_storage->pseudo_methods[strtolower($original_method_name)])) {
|
||||
@ -301,6 +314,8 @@ class Methods
|
||||
if (!$appearing_method_id) {
|
||||
list($fq_class_name, $method_name) = explode('::', $method_id);
|
||||
|
||||
$fq_class_name = $this->classlikes->getUnAliasedName($fq_class_name);
|
||||
|
||||
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
if ($class_storage->abstract && isset($class_storage->overridden_method_ids[$method_name])) {
|
||||
@ -485,6 +500,8 @@ class Methods
|
||||
|
||||
list($fq_class_name, $method_name) = explode('::', $method_id);
|
||||
|
||||
$fq_class_name = $this->classlikes->getUnAliasedName($fq_class_name);
|
||||
|
||||
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
if (isset($class_storage->declaring_method_ids[$method_name])) {
|
||||
@ -509,6 +526,8 @@ class Methods
|
||||
|
||||
list($fq_class_name, $method_name) = explode('::', $method_id);
|
||||
|
||||
$fq_class_name = $this->classlikes->getUnAliasedName($fq_class_name);
|
||||
|
||||
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
if (isset($class_storage->appearing_method_ids[$method_name])) {
|
||||
|
@ -504,6 +504,10 @@ class Scanner
|
||||
$this->reflection->registerClass($reflected_class);
|
||||
$this->reflected_classlikes_lc[$fq_classlike_name_lc] = true;
|
||||
} elseif ($this->fileExistsForClassLike($classlikes, $fq_classlike_name)) {
|
||||
$fq_classlike_name_lc = strtolower($classlikes->getUnAliasedName(
|
||||
$fq_classlike_name_lc
|
||||
));
|
||||
|
||||
// even though we've checked this above, calling the method invalidates it
|
||||
if (isset($this->classlike_files[$fq_classlike_name_lc])) {
|
||||
/** @var string */
|
||||
|
@ -136,7 +136,7 @@ class DocumentationTest extends TestCase
|
||||
$this->analyzeFile($file_path, $context);
|
||||
|
||||
if ($check_references) {
|
||||
$this->project_analyzer->getCodebase()->classlikes->checkClassReferences();
|
||||
$this->project_analyzer->checkClassReferences();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ echo $a;';
|
||||
$file_contents
|
||||
);
|
||||
|
||||
$this->project_analyzer->getCodebase()->classlikes->checkClassReferences();
|
||||
$this->project_analyzer->checkClassReferences();
|
||||
|
||||
$this->analyzeFile('somefile.php', new Context());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user