Skip to content

Commit

Permalink
Remove Context::getPossibleTemplateDefiners in favor ClosureAnalyzer:…
Browse files Browse the repository at this point in the history
…:getPossibleTemplateDefiners
  • Loading branch information
klimick committed Apr 29, 2024
1 parent e766b0d commit 2a9d663
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 55 deletions.
24 changes: 0 additions & 24 deletions src/Psalm/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -857,28 +857,4 @@ public function insideUse(): bool
|| $this->inside_throw
|| $this->inside_isset;
}

/**
* Returns all possible template definers in context (class, function or method).
*
* @return array<string, true>
*/
public function getPossibleTemplateDefiners(): array
{
$who_can_define_templates = [];

if ($this->calling_function_id !== null) {
$who_can_define_templates['fn-' . $this->calling_function_id] = true;
}

if ($this->calling_method_id !== null) {
$who_can_define_templates['fn-' . $this->calling_method_id] = true;
}

if ($this->self !== null) {
$who_can_define_templates[$this->self] = true;
}

return $who_can_define_templates;
}
}
89 changes: 58 additions & 31 deletions src/Psalm/Internal/Analyzer/ClosureAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use PhpParser;
use Psalm\CodeLocation;
use Psalm\Codebase;
use Psalm\Context;
use Psalm\Internal\Codebase\VariableUseGraph;
use Psalm\Internal\DataFlow\DataFlowNode;
Expand All @@ -18,6 +17,8 @@
use Psalm\Issue\PossiblyUndefinedVariable;
use Psalm\Issue\UndefinedVariable;
use Psalm\IssueBuffer;
use Psalm\Storage\FunctionStorage;
use Psalm\Storage\MethodStorage;
use Psalm\Storage\UnserializeMemoryUsageSuppressionTrait;
use Psalm\Type;
use Psalm\Type\Atomic\TNamedObject;
Expand Down Expand Up @@ -369,6 +370,8 @@ private static function inferParamTypesFromContextualTypeAndGetPossibleReturnTyp
$closure_analyzer->getClosureId(),
);

$possible_template_definers = self::getPossibleTemplateDefiners($statements_analyzer);

foreach ($calling_closure_storage->params as $param_index => $calling_param) {
$contextual_param_type = $contextual_callable_type->params[$param_index]->type ?? null;

Expand All @@ -382,49 +385,73 @@ private static function inferParamTypesFromContextualTypeAndGetPossibleReturnTyp
continue;
}

$contextual_param_type = self::expandContextualType($codebase, $context, $contextual_param_type);
$expanded_contextual_param_type = TypeExpander::expandUnion(
codebase: $codebase,
return_type: $contextual_param_type,
self_class: null,
static_class_type: null,
parent_class: null,
expand_templates: true,
do_not_expand_template_defined_at: $possible_template_definers,
);

if ($calling_param->type === null) {
$calling_param->type = $expanded_contextual_param_type;
$calling_param->type_inferred = true;

continue;
}

$type_comparison_result = new TypeComparisonResult();

if ($calling_param->type === null
|| UnionTypeComparator::isContainedBy(
$codebase,
$contextual_param_type,
$calling_param->type,
false,
false,
$type_comparison_result,
)
) {
if (UnionTypeComparator::isContainedBy(
codebase: $codebase,
input_type: $expanded_contextual_param_type,
container_type: $calling_param->type,
union_comparison_result: $type_comparison_result,
)) {
if ($type_comparison_result->to_string_cast) {
continue;
}

$calling_param->type = $contextual_param_type;
$calling_param->type = $expanded_contextual_param_type;
$calling_param->type_inferred = true;
}
}

return $contextual_callable_type->return_type;
}

private static function expandContextualType(Codebase $codebase, Context $context, Union $contextual_type): Union
/**
* @return array<string, true>
*/
private static function getPossibleTemplateDefiners(StatementsAnalyzer $statements_analyzer): array
{
$expand_templates = true;
$do_not_expand_template_defined_at = $context->getPossibleTemplateDefiners();

return TypeExpander::expandUnion(
$codebase,
$contextual_type,
null,
null,
null,
true,
false,
false,
false,
$expand_templates,
false,
$do_not_expand_template_defined_at,
);
do {
$statements_analyzer = $statements_analyzer->getSource();

if ($statements_analyzer instanceof FunctionAnalyzer
&& $statements_analyzer->storage instanceof FunctionStorage
) {
$function_name = $statements_analyzer->storage->cased_name;

return $function_name !== null
? ['fn-' . strtolower($function_name) => true]
: [];
}

if ($statements_analyzer instanceof MethodAnalyzer
&& $statements_analyzer->storage instanceof MethodStorage
) {
$class_name = $statements_analyzer->storage->defining_fqcln;
$method_name = $statements_analyzer->storage->cased_name;

return $class_name !== null && $method_name !== null
? ['fn-' . strtolower($class_name).'::'.strtolower($method_name) => true, $class_name => true]
: [];
}
} while (!$statements_analyzer instanceof FileAnalyzer);

return [];
}
}

0 comments on commit 2a9d663

Please sign in to comment.