Skip to content
Permalink
Browse files

Fix #2508 - don’t replace templated types with generic ones inside ow…

…n function
  • Loading branch information
muglug committed Dec 28, 2019
1 parent 37496e9 commit 55c2f7faa2a3803739ca5f6024012e5b4d06082e
Showing with 230 additions and 168 deletions.
  1. +3 −3 src/Psalm/Codebase.php
  2. +1 −1 src/Psalm/Context.php
  3. +7 −6 src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php
  4. +4 −4 src/Psalm/Internal/Analyzer/MethodAnalyzer.php
  5. +1 −1 src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php
  6. +1 −1 src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php
  7. +1 −1 src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php
  8. +6 −6 src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/PropertyAssignmentAnalyzer.php
  9. +2 −2 src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php
  10. +3 −1 src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php
  11. +7 −7 src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php
  12. +4 −4 src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php
  13. +10 −10 src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php
  14. +21 −18 src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php
  15. +1 −1 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php
  16. +3 −3 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ClassConstFetchAnalyzer.php
  17. +9 −9 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/PropertyFetchAnalyzer.php
  18. +2 −2 src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php
  19. +3 −3 src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php
  20. +1 −1 src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php
  21. +1 −1 src/Psalm/Internal/Analyzer/StatementsAnalyzer.php
  22. +26 −6 src/Psalm/Internal/Analyzer/TypeAnalyzer.php
  23. +8 −8 src/Psalm/Internal/Codebase/ClassLikes.php
  24. +17 −17 src/Psalm/Internal/Codebase/Methods.php
  25. +4 −4 src/Psalm/Internal/Codebase/Properties.php
  26. +6 −6 src/Psalm/Internal/Provider/FileReferenceProvider.php
  27. +1 −1 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php
  28. +1 −1 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php
  29. +4 −4 src/Psalm/Internal/Type/TemplateResult.php
  30. +13 −11 src/Psalm/Internal/Type/UnionTemplateHandler.php
  31. +2 −2 src/Psalm/Internal/Visitor/ReflectorVisitor.php
  32. +7 −1 src/Psalm/Storage/Assertion.php
  33. +4 −2 src/Psalm/Type.php
  34. +2 −2 src/Psalm/Type/Atomic/CallableTrait.php
  35. +5 −2 src/Psalm/Type/Atomic/TTemplateIndexedAccess.php
  36. +5 −2 src/Psalm/Type/Atomic/TTemplateKeyOf.php
  37. +6 −3 src/Psalm/Type/Atomic/TTemplateParam.php
  38. +5 −4 src/Psalm/Type/Atomic/TTemplateParamClass.php
  39. +8 −6 src/Psalm/Type/Union.php
  40. +14 −0 tests/Template/FunctionTemplateTest.php
  41. +1 −1 tests/TypeParseTest.php
@@ -814,19 +814,19 @@ public function traitHasCorrectCase($fq_trait_name)
*
* @param string $method_id
* @param CodeLocation|null $code_location
* @param string $calling_method_id
* @param string $calling_function_id
*
* @return bool
*/
public function methodExists(
string $method_id,
CodeLocation $code_location = null,
$calling_method_id = null,
$calling_function_id = null,
string $file_path = null
) {
return $this->methods->methodExists(
$method_id,
$calling_method_id,
$calling_function_id,
$code_location,
null,
$file_path
@@ -305,7 +305,7 @@ class Context
/**
* @var string|null
*/
public $calling_method_id;
public $calling_function_id;

/**
* @var bool
@@ -318,9 +318,10 @@ public function analyze(

MethodAnalyzer::checkMethodSignatureMustOmitReturnType($storage, $codeLocation);

$context->calling_method_id = strtolower($method_id);
$context->calling_function_id = strtolower($method_id);
} elseif ($this->function instanceof Function_) {
$cased_method_id = $this->function->name->name;
$context->calling_function_id = strtolower($cased_method_id);
} else { // Closure
if ($storage->return_type) {
$closure_return_type = ExpressionAnalyzer::fleshOutType(
@@ -662,7 +663,7 @@ function (FunctionLikeParameter $p) {
$this,
$input_type,
$storage->throw_locations[$expected_exception],
$context->calling_method_id
$context->calling_function_id
);
}
}
@@ -1169,7 +1170,7 @@ private function alterParams(
$this,
$param_name_node,
$resolved_name,
$context->calling_method_id,
$context->calling_function_id,
false,
true
);
@@ -1203,7 +1204,7 @@ private function alterParams(
$this,
$return_name_node,
$resolved_name,
$context->calling_method_id,
$context->calling_function_id,
false,
true
);
@@ -1228,7 +1229,7 @@ private function alterParams(
$this,
$replace_type,
$storage->return_type_location,
$context->calling_method_id
$context->calling_function_id
);
}

@@ -1252,7 +1253,7 @@ private function alterParams(
$this,
$replace_type,
$function_param->type_location,
$context->calling_method_id
$context->calling_function_id
);
}
}
@@ -145,7 +145,7 @@ public static function checkStatic(
* @param string $method_id
* @param CodeLocation $code_location
* @param string[] $suppressed_issues
* @param string|null $calling_method_id
* @param string|null $calling_function_id
*
* @return bool|null
*/
@@ -154,12 +154,12 @@ public static function checkMethodExists(
$method_id,
CodeLocation $code_location,
array $suppressed_issues,
$calling_method_id = null
$calling_function_id = null
) {
if ($codebase->methods->methodExists(
$method_id,
$calling_method_id,
$calling_method_id !== $method_id ? $code_location : null,
$calling_function_id,
$calling_function_id !== $method_id ? $code_location : null,
null,
$code_location->file_path
)) {
@@ -141,7 +141,7 @@ public static function analyze(
$statements_analyzer,
$comment_type,
$type_location,
$context->calling_method_id
$context->calling_function_id
);
}
}
@@ -210,7 +210,7 @@ public static function analyze(
$statements_analyzer,
$catch_type,
$fq_catch_class,
$context->calling_method_id
$context->calling_function_id
);
}

@@ -565,7 +565,7 @@ public static function updateArrayType(
[],
[
$offset_type_part->param_name => [
($offset_type_part->defining_class ?? '') => [
$offset_type_part->defining_class => [
new Type\Union([
new Type\Atomic\TTemplateParam(
$class_string_map->param_name,
@@ -163,7 +163,7 @@ public static function analyzeInstance(
if ($stmt->name instanceof PhpParser\Node\Identifier) {
$codebase->analyzer->addMixedMemberName(
'$' . $stmt->name->name,
$context->calling_method_id ?: $statements_analyzer->getFileName()
$context->calling_function_id ?: $statements_analyzer->getFileName()
);
}

@@ -639,9 +639,9 @@ public static function analyzeInstance(
&& !($context->self
&& ($appearing_property_class === $context->self
|| $codebase->classExtends($context->self, $appearing_property_class))
&& (!$context->calling_method_id
|| \strpos($context->calling_method_id, '::__construct')
|| \strpos($context->calling_method_id, '::unserialize')
&& (!$context->calling_function_id
|| \strpos($context->calling_function_id, '::__construct')
|| \strpos($context->calling_function_id, '::unserialize')
|| $property_pure_compatible)
)
) {
@@ -1087,7 +1087,7 @@ public static function analyzeStatic(
if ($fq_class_name && !$context->ignore_variable_property) {
$codebase->analyzer->addMixedMemberName(
strtolower($fq_class_name) . '::$',
$context->calling_method_id ?: $statements_analyzer->getFileName()
$context->calling_function_id ?: $statements_analyzer->getFileName()
);
}

@@ -1134,7 +1134,7 @@ public static function analyzeStatic(
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
$context->calling_function_id
);

if (!$moved_class) {
@@ -162,7 +162,7 @@ public static function analyze(
$statements_analyzer,
$var_comment_type,
$type_location,
$context->calling_method_id
$context->calling_function_id
);
}
}
@@ -720,7 +720,7 @@ public static function analyze(
if ($type instanceof Type\Atomic\TNamedObject) {
$codebase->analyzer->addMixedMemberName(
strtolower($type->value) . '::$',
$context->calling_method_id ?: $statements_analyzer->getFileName()
$context->calling_function_id ?: $statements_analyzer->getFileName()
);
}
}
@@ -488,7 +488,9 @@ public static function analyze(
if ($function_storage && $function_storage->template_types) {
foreach ($function_storage->template_types as $template_name => $_) {
if (!isset($template_result->generic_params[$template_name])) {
$template_result->generic_params[$template_name] = ['' => [Type::getEmpty(), 0]];
$template_result->generic_params[$template_name] = [
'fn-' . $function_id => [Type::getEmpty(), 0]
];
}
}
}
@@ -524,7 +524,7 @@ private static function analyzeAtomicCall(
if ($stmt->name instanceof PhpParser\Node\Identifier) {
$codebase->analyzer->addMixedMemberName(
strtolower($stmt->name->name),
$context->calling_method_id ?: $statements_analyzer->getFileName()
$context->calling_function_id ?: $statements_analyzer->getFileName()
);
}

@@ -682,7 +682,7 @@ private static function analyzeAtomicCall(
if (!$context->ignore_variable_method) {
$codebase->analyzer->addMixedMemberName(
strtolower($fq_class_name) . '::',
$context->calling_method_id ?: $statements_analyzer->getFileName()
$context->calling_function_id ?: $statements_analyzer->getFileName()
);
}

@@ -705,7 +705,7 @@ private static function analyzeAtomicCall(

if (!$codebase->methods->methodExists(
$method_id,
$context->calling_method_id,
$context->calling_function_id,
$codebase->collect_references ? new CodeLocation($source, $stmt->name) : null,
null,
$statements_analyzer->getFilePath()
@@ -734,7 +734,7 @@ private static function analyzeAtomicCall(
if (!$interface_has_method
&& $codebase->methods->methodExists(
$fq_class_name . '::__call',
$context->calling_method_id
$context->calling_function_id
)
) {
if (isset($class_storage->pseudo_methods[$method_name_lc])) {
@@ -866,7 +866,7 @@ function (PhpParser\Node\Arg $arg) {

if (!$codebase->methods->methodExists(
$method_id,
$context->calling_method_id,
$context->calling_function_id,
$method_id !== $source_method_id ? new CodeLocation($source, $stmt->name) : null
)
|| ($config->use_phpdoc_method_without_magic_or_parent
@@ -973,8 +973,8 @@ function (PhpParser\Node\Arg $arg) {
);
}

if ($context->collect_initializations && $context->calling_method_id) {
list($calling_method_class) = explode('::', $context->calling_method_id);
if ($context->collect_initializations && $context->calling_function_id) {
list($calling_method_class) = explode('::', $context->calling_function_id);
$codebase->file_reference_provider->addMethodReferenceToClassMember(
$calling_method_class . '::__construct',
strtolower($method_id)
@@ -57,11 +57,11 @@ public static function analyze(
if (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)) {
$aliases = $statements_analyzer->getAliases();

if ($context->calling_method_id
if ($context->calling_function_id
&& !$stmt->class instanceof PhpParser\Node\Name\FullyQualified
) {
$codebase->file_reference_provider->addMethodReferenceToClassMember(
$context->calling_method_id,
$context->calling_function_id,
'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())
);
}
@@ -282,7 +282,7 @@ public static function analyze(
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
$context->calling_function_id
);
}

@@ -381,7 +381,7 @@ public static function analyze(

if ($codebase->methods->methodExists(
$fq_class_name . '::__construct',
$context->calling_method_id,
$context->calling_function_id,
$context->collect_references ? new CodeLocation($statements_analyzer->getSource(), $stmt) : null,
null,
$statements_analyzer->getFilePath()
@@ -116,11 +116,11 @@ public static function analyze(
} elseif ($context->check_classes) {
$aliases = $statements_analyzer->getAliases();

if ($context->calling_method_id
if ($context->calling_function_id
&& !$stmt->class instanceof PhpParser\Node\Name\FullyQualified
) {
$codebase->file_reference_provider->addMethodReferenceToClassMember(
$context->calling_method_id,
$context->calling_function_id,
'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())
);
}
@@ -297,7 +297,7 @@ public static function analyze(
if ($stmt->name instanceof PhpParser\Node\Identifier) {
$codebase->analyzer->addMixedMemberName(
strtolower($stmt->name->name),
$context->calling_method_id ?: $statements_analyzer->getFileName()
$context->calling_function_id ?: $statements_analyzer->getFileName()
);
}

@@ -400,7 +400,7 @@ public static function analyze(

if (!$codebase->methods->methodExists(
$method_id,
$context->calling_method_id,
$context->calling_function_id,
$codebase->collect_references ? new CodeLocation($source, $stmt->name) : null,
null,
$statements_analyzer->getFilePath()
@@ -413,7 +413,7 @@ public static function analyze(
) {
if ($codebase->methods->methodExists(
$fq_class_name . '::__callStatic',
$context->calling_method_id,
$context->calling_function_id,
$codebase->collect_references ? new CodeLocation($source, $stmt->name) : null,
null,
$statements_analyzer->getFilePath()
@@ -524,7 +524,7 @@ function (PhpParser\Node\Arg $arg) {
$method_id,
new CodeLocation($source, $stmt),
$statements_analyzer->getSuppressedIssues(),
$context->calling_method_id
$context->calling_function_id
);

if (!$does_method_exist) {
@@ -544,7 +544,7 @@ function (PhpParser\Node\Arg $arg) {
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
$context->calling_function_id
);
}

@@ -1010,7 +1010,7 @@ function (Assertion $assertion) use ($generic_params) : Assertion {
$statements_analyzer,
$stmt->class,
$new_fq_class_name,
$context->calling_method_id,
$context->calling_function_id,
strtolower($old_declaring_fq_class_name) !== strtolower($new_fq_class_name),
$stmt->class->parts[0] === 'self'
)) {
@@ -1102,7 +1102,7 @@ function (Assertion $assertion) use ($generic_params) : Assertion {
if (!$context->ignore_variable_method) {
$codebase->analyzer->addMixedMemberName(
strtolower($fq_class_name) . '::',
$context->calling_method_id ?: $statements_analyzer->getFileName()
$context->calling_function_id ?: $statements_analyzer->getFileName()
);
}

@@ -1128,7 +1128,7 @@ function (Assertion $assertion) use ($generic_params) : Assertion {
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id,
$context->calling_function_id,
false,
$stmt->class->parts[0] === 'self'
);

0 comments on commit 55c2f7f

Please sign in to comment.
You can’t perform that action at this time.