mirror of
https://github.com/danog/psalm.git
synced 2024-11-29 20:28:59 +01:00
Improve --diff checks by including trait-using classes in dependents
This commit is contained in:
parent
7639e179c4
commit
f141f7c526
@ -82,6 +82,7 @@ class TemplateAnalyzer extends Psalm\Internal\Analyzer\FileAnalyzer
|
||||
$this,
|
||||
$class,
|
||||
new CodeLocation($this, $stmt),
|
||||
null,
|
||||
[],
|
||||
true
|
||||
) === false
|
||||
|
@ -225,6 +225,7 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
$this->getSource(),
|
||||
$parent_fq_class_name,
|
||||
$parent_reference_location,
|
||||
null,
|
||||
$storage->suppressed_issues + $this->getSuppressedIssues(),
|
||||
false
|
||||
) === false) {
|
||||
@ -379,6 +380,7 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
$this,
|
||||
$fq_interface_name,
|
||||
$interface_location,
|
||||
null,
|
||||
$this->getSuppressedIssues(),
|
||||
false
|
||||
) === false) {
|
||||
|
@ -210,6 +210,7 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer implements StatementsSou
|
||||
StatementsSource $statements_source,
|
||||
string $fq_class_name,
|
||||
CodeLocation $code_location,
|
||||
?string $calling_fq_class_name,
|
||||
array $suppressed_issues,
|
||||
bool $inferred = true,
|
||||
bool $allow_trait = false,
|
||||
@ -262,11 +263,13 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer implements StatementsSou
|
||||
|
||||
$class_exists = $codebase->classlikes->classExists(
|
||||
$fq_class_name,
|
||||
!$inferred ? $code_location : null
|
||||
!$inferred ? $code_location : null,
|
||||
$calling_fq_class_name
|
||||
);
|
||||
$interface_exists = $codebase->classlikes->interfaceExists(
|
||||
$fq_class_name,
|
||||
!$inferred ? $code_location : null
|
||||
!$inferred ? $code_location : null,
|
||||
$calling_fq_class_name
|
||||
);
|
||||
|
||||
if (!$class_exists && !$interface_exists) {
|
||||
|
@ -652,6 +652,7 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
$statements_analyzer,
|
||||
$expected_exception,
|
||||
$storage->throw_locations[$expected_exception],
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false,
|
||||
false,
|
||||
|
@ -557,6 +557,7 @@ class ForeachAnalyzer
|
||||
$statements_analyzer,
|
||||
$iterator_atomic_type->value,
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt->expr),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues()
|
||||
) === false) {
|
||||
return false;
|
||||
|
@ -223,6 +223,7 @@ class TryAnalyzer
|
||||
$statements_analyzer,
|
||||
$fq_catch_class,
|
||||
new CodeLocation($statements_analyzer->getSource(), $catch_type, $context->include_location),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false
|
||||
) === false) {
|
||||
|
@ -895,6 +895,7 @@ class AssertionFinder
|
||||
$source,
|
||||
$var_type,
|
||||
new CodeLocation($source, $whichclass_expr),
|
||||
null,
|
||||
$source->getSuppressedIssues(),
|
||||
false
|
||||
) === false
|
||||
@ -1510,6 +1511,7 @@ class AssertionFinder
|
||||
$source,
|
||||
$var_type,
|
||||
new CodeLocation($source, $whichclass_expr),
|
||||
null,
|
||||
$source->getSuppressedIssues(),
|
||||
false
|
||||
) === false
|
||||
|
@ -633,6 +633,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($source, $stmt->var),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
true,
|
||||
false,
|
||||
|
@ -295,6 +295,7 @@ class NewAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\CallAna
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false
|
||||
) === false) {
|
||||
|
@ -150,6 +150,7 @@ class StaticCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($source, $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false,
|
||||
false,
|
||||
@ -209,6 +210,7 @@ class StaticCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($source, $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
$stmt->class instanceof PhpParser\Node\Name
|
||||
&& count($stmt->class->parts) === 1
|
||||
@ -227,6 +229,7 @@ class StaticCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($source, $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false
|
||||
)) {
|
||||
@ -255,6 +258,7 @@ class StaticCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($source, $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false
|
||||
)) {
|
||||
|
@ -2821,6 +2821,7 @@ class CallAnalyzer
|
||||
$statements_analyzer,
|
||||
$input_expr->value,
|
||||
$code_location,
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues()
|
||||
) === false
|
||||
) {
|
||||
@ -2837,6 +2838,7 @@ class CallAnalyzer
|
||||
$statements_analyzer,
|
||||
$item->value->value,
|
||||
$code_location,
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues()
|
||||
) === false
|
||||
) {
|
||||
@ -2885,6 +2887,7 @@ class CallAnalyzer
|
||||
$statements_analyzer,
|
||||
$callable_fq_class_name,
|
||||
$code_location,
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues()
|
||||
) === false
|
||||
) {
|
||||
|
@ -79,6 +79,7 @@ class ClassConstFetchAnalyzer
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false,
|
||||
true
|
||||
|
@ -1016,6 +1016,7 @@ class PropertyFetchAnalyzer
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false
|
||||
) !== true) {
|
||||
|
@ -699,6 +699,7 @@ class ExpressionAnalyzer
|
||||
$statements_analyzer,
|
||||
$fq_class_name,
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt->class),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
false
|
||||
) === false) {
|
||||
|
@ -330,6 +330,7 @@ class ReturnAnalyzer
|
||||
$statements_analyzer,
|
||||
$stmt->expr->value,
|
||||
new CodeLocation($source, $stmt->expr),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues()
|
||||
) === false
|
||||
) {
|
||||
@ -348,6 +349,7 @@ class ReturnAnalyzer
|
||||
$statements_analyzer,
|
||||
$item->value->value,
|
||||
new CodeLocation($source, $item->value),
|
||||
$context->self,
|
||||
$statements_analyzer->getSuppressedIssues()
|
||||
) === false
|
||||
) {
|
||||
|
@ -303,8 +303,11 @@ class ClassLikes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasFullyQualifiedClassName($fq_class_name, CodeLocation $code_location = null)
|
||||
{
|
||||
public function hasFullyQualifiedClassName(
|
||||
$fq_class_name,
|
||||
CodeLocation $code_location = null,
|
||||
?string $calling_fq_class_name = null
|
||||
) {
|
||||
$fq_class_name_lc = strtolower($fq_class_name);
|
||||
|
||||
if (isset($this->classlike_aliases[$fq_class_name_lc])) {
|
||||
@ -338,6 +341,19 @@ class ClassLikes
|
||||
$code_location->file_path,
|
||||
$fq_class_name_lc
|
||||
);
|
||||
|
||||
if ($calling_fq_class_name) {
|
||||
$class_storage = $this->classlike_storage_provider->get($calling_fq_class_name);
|
||||
|
||||
if ($class_storage->location
|
||||
&& $class_storage->location->file_path !== $code_location->file_path
|
||||
) {
|
||||
$this->file_reference_provider->addFileReferenceToClass(
|
||||
$class_storage->location->file_path,
|
||||
$fq_class_name_lc
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->collect_locations && $code_location) {
|
||||
@ -355,8 +371,11 @@ class ClassLikes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasFullyQualifiedInterfaceName($fq_class_name, CodeLocation $code_location = null)
|
||||
{
|
||||
public function hasFullyQualifiedInterfaceName(
|
||||
$fq_class_name,
|
||||
CodeLocation $code_location = null,
|
||||
?string $calling_fq_class_name = null
|
||||
) {
|
||||
$fq_class_name_lc = strtolower($fq_class_name);
|
||||
|
||||
if (isset($this->classlike_aliases[$fq_class_name_lc])) {
|
||||
@ -390,6 +409,19 @@ class ClassLikes
|
||||
$code_location->file_path,
|
||||
$fq_class_name_lc
|
||||
);
|
||||
|
||||
if ($calling_fq_class_name) {
|
||||
$class_storage = $this->classlike_storage_provider->get($calling_fq_class_name);
|
||||
|
||||
if ($class_storage->location
|
||||
&& $class_storage->location->file_path !== $code_location->file_path
|
||||
) {
|
||||
$this->file_reference_provider->addFileReferenceToClass(
|
||||
$class_storage->location->file_path,
|
||||
$fq_class_name_lc
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->collect_locations && $code_location) {
|
||||
@ -441,10 +473,11 @@ class ClassLikes
|
||||
*/
|
||||
public function classOrInterfaceExists(
|
||||
$fq_class_name,
|
||||
CodeLocation $code_location = null
|
||||
CodeLocation $code_location = null,
|
||||
?string $calling_fq_class_name = null
|
||||
) {
|
||||
if (!$this->classExists($fq_class_name, $code_location)
|
||||
&& !$this->interfaceExists($fq_class_name, $code_location)
|
||||
if (!$this->classExists($fq_class_name, $code_location, $calling_fq_class_name)
|
||||
&& !$this->interfaceExists($fq_class_name, $code_location, $calling_fq_class_name)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@ -459,8 +492,11 @@ class ClassLikes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function classExists($fq_class_name, CodeLocation $code_location = null)
|
||||
{
|
||||
public function classExists(
|
||||
$fq_class_name,
|
||||
CodeLocation $code_location = null,
|
||||
?string $calling_fq_class_name = null
|
||||
) {
|
||||
if (isset(ClassLikeAnalyzer::SPECIAL_TYPES[$fq_class_name])) {
|
||||
return false;
|
||||
}
|
||||
@ -469,7 +505,7 @@ class ClassLikes
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->hasFullyQualifiedClassName($fq_class_name, $code_location);
|
||||
return $this->hasFullyQualifiedClassName($fq_class_name, $code_location, $calling_fq_class_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -548,13 +584,20 @@ class ClassLikes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function interfaceExists($fq_interface_name, CodeLocation $code_location = null)
|
||||
{
|
||||
public function interfaceExists(
|
||||
$fq_interface_name,
|
||||
CodeLocation $code_location = null,
|
||||
?string $calling_fq_class_name = null
|
||||
) {
|
||||
if (isset(ClassLikeAnalyzer::SPECIAL_TYPES[strtolower($fq_interface_name)])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->hasFullyQualifiedInterfaceName($fq_interface_name, $code_location);
|
||||
return $this->hasFullyQualifiedInterfaceName(
|
||||
$fq_interface_name,
|
||||
$code_location,
|
||||
$calling_fq_class_name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,9 +313,11 @@ class FileReferenceProvider
|
||||
|
||||
foreach ($file_classes as $file_class_lc => $_) {
|
||||
if (isset(self::$file_references_to_classes[$file_class_lc])) {
|
||||
$new_files = array_keys(self::$file_references_to_classes[$file_class_lc]);
|
||||
|
||||
$referenced_files = array_merge(
|
||||
$referenced_files,
|
||||
array_keys(self::$file_references_to_classes[$file_class_lc])
|
||||
$new_files
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +163,7 @@ trait HasIntersectionTrait
|
||||
$source,
|
||||
$extra_type->value,
|
||||
$code_location,
|
||||
null,
|
||||
$suppressed_issues,
|
||||
$inferred,
|
||||
false,
|
||||
|
@ -148,6 +148,7 @@ class TClassString extends TString
|
||||
$source,
|
||||
$this->as,
|
||||
$code_location,
|
||||
null,
|
||||
$suppressed_issues,
|
||||
$inferred,
|
||||
false,
|
||||
|
@ -140,6 +140,7 @@ class TLiteralClassString extends TLiteralString
|
||||
$source,
|
||||
$this->value,
|
||||
$code_location,
|
||||
null,
|
||||
$suppressed_issues,
|
||||
$inferred,
|
||||
false,
|
||||
|
@ -181,6 +181,7 @@ class TNamedObject extends Atomic
|
||||
$source,
|
||||
$this->value,
|
||||
$code_location,
|
||||
null,
|
||||
$suppressed_issues,
|
||||
$inferred,
|
||||
false,
|
||||
|
@ -134,6 +134,7 @@ class TScalarClassConstant extends Scalar
|
||||
$source,
|
||||
$fq_classlike_name,
|
||||
$code_location,
|
||||
null,
|
||||
$suppressed_issues,
|
||||
$inferred,
|
||||
false,
|
||||
|
Loading…
Reference in New Issue
Block a user