1
0
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:
Matthew Brown 2018-12-21 11:32:44 -05:00
parent e89425ad68
commit 947e3bf0f1
10 changed files with 49 additions and 24 deletions

View File

@ -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,

View File

@ -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) {

View File

@ -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);
}
/**

View File

@ -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) {

View File

@ -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;

View File

@ -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])

View File

@ -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])) {

View File

@ -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 */

View File

@ -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();
}
}

View File

@ -88,7 +88,7 @@ echo $a;';
$file_contents
);
$this->project_analyzer->getCodebase()->classlikes->checkClassReferences();
$this->project_analyzer->checkClassReferences();
$this->analyzeFile('somefile.php', new Context());