Skip to content

Commit 51a867f

Browse files
committed
Infer types of StaticCall with dynamic name
1 parent 6037f78 commit 51a867f

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

Diff for: src/Analyser/MutatingScope.php

+41-30
Original file line numberDiff line numberDiff line change
@@ -2077,23 +2077,50 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
20772077
);
20782078
}
20792079

2080-
if ($node instanceof Expr\StaticCall && $node->name instanceof Node\Identifier) {
2081-
if ($this->nativeTypesPromoted) {
2080+
if ($node instanceof Expr\StaticCall) {
2081+
if ($node->name instanceof Node\Identifier) {
2082+
if ($this->nativeTypesPromoted) {
2083+
$typeCallback = function () use ($node): Type {
2084+
if ($node->class instanceof Name) {
2085+
$staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($node->class, $node->name);
2086+
} else {
2087+
$staticMethodCalledOnType = $this->getNativeType($node->class);
2088+
}
2089+
$methodReflection = $this->getMethodReflection(
2090+
$staticMethodCalledOnType,
2091+
$node->name->name,
2092+
);
2093+
if ($methodReflection === null) {
2094+
return new ErrorType();
2095+
}
2096+
2097+
return ParametersAcceptorSelector::combineAcceptors($methodReflection->getVariants())->getNativeReturnType();
2098+
};
2099+
2100+
$callType = $typeCallback();
2101+
if ($node->class instanceof Expr) {
2102+
return $this->getNullsafeShortCircuitingType($node->class, $callType);
2103+
}
2104+
2105+
return $callType;
2106+
}
2107+
20822108
$typeCallback = function () use ($node): Type {
20832109
if ($node->class instanceof Name) {
20842110
$staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($node->class, $node->name);
20852111
} else {
2086-
$staticMethodCalledOnType = $this->getNativeType($node->class);
2112+
$staticMethodCalledOnType = TypeCombinator::removeNull($this->getType($node->class))->getObjectTypeOrClassStringObjectType();
20872113
}
2088-
$methodReflection = $this->getMethodReflection(
2114+
2115+
$returnType = $this->methodCallReturnType(
20892116
$staticMethodCalledOnType,
2090-
$node->name->name,
2117+
$node->name->toString(),
2118+
$node,
20912119
);
2092-
if ($methodReflection === null) {
2120+
if ($returnType === null) {
20932121
return new ErrorType();
20942122
}
2095-
2096-
return ParametersAcceptorSelector::combineAcceptors($methodReflection->getVariants())->getNativeReturnType();
2123+
return $returnType;
20972124
};
20982125

20992126
$callType = $typeCallback();
@@ -2104,30 +2131,14 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
21042131
return $callType;
21052132
}
21062133

2107-
$typeCallback = function () use ($node): Type {
2108-
if ($node->class instanceof Name) {
2109-
$staticMethodCalledOnType = $this->resolveTypeByNameWithLateStaticBinding($node->class, $node->name);
2110-
} else {
2111-
$staticMethodCalledOnType = TypeCombinator::removeNull($this->getType($node->class))->getObjectTypeOrClassStringObjectType();
2112-
}
2113-
2114-
$returnType = $this->methodCallReturnType(
2115-
$staticMethodCalledOnType,
2116-
$node->name->toString(),
2117-
$node,
2134+
$nameType = $this->getType($node->name);
2135+
if (count($nameType->getConstantStrings()) > 0) {
2136+
return TypeCombinator::union(
2137+
...array_map(fn ($constantString) => $this
2138+
->filterByTruthyValue(new BinaryOp\Identical($node->name, new String_($constantString->getValue())))
2139+
->getType(new Expr\StaticCall($node->class, new Identifier($constantString->getValue()), $node->args)), $nameType->getConstantStrings()),
21182140
);
2119-
if ($returnType === null) {
2120-
return new ErrorType();
2121-
}
2122-
return $returnType;
2123-
};
2124-
2125-
$callType = $typeCallback();
2126-
if ($node->class instanceof Expr) {
2127-
return $this->getNullsafeShortCircuitingType($node->class, $callType);
21282141
}
2129-
2130-
return $callType;
21312142
}
21322143

21332144
if ($node instanceof PropertyFetch) {

0 commit comments

Comments
 (0)