Skip to content

Commit

Permalink
Fix 4949, support closure bind with class-string
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek committed Jan 31, 2022
1 parent 39a5313 commit 5ef1b3f
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 9 deletions.
16 changes: 8 additions & 8 deletions src/Analyser/NodeScopeResolver.php
Expand Up @@ -118,6 +118,7 @@
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\Generic\GenericClassStringType;
use PHPStan\Type\Generic\TemplateTypeHelper;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\IntegerType;
Expand All @@ -132,6 +133,7 @@
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use PHPStan\Type\VoidType;
use Throwable;
Expand Down Expand Up @@ -2065,17 +2067,15 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
if (count($directClassNames) === 1) {
$scopeClass = $directClassNames[0];
$thisType = new ObjectType($scopeClass);
} elseif (
$argValue instanceof Expr\ClassConstFetch
&& $argValue->name instanceof Node\Identifier
&& strtolower($argValue->name->name) === 'class'
&& $argValue->class instanceof Name
) {
$scopeClass = $scope->resolveName($argValue->class);
$thisType = new ObjectType($scopeClass);
} elseif ($argValueType instanceof ConstantStringType) {
$scopeClass = $argValueType->getValue();
$thisType = new ObjectType($scopeClass);
} elseif (
$argValueType instanceof GenericClassStringType
&& $argValueType->getGenericType() instanceof TypeWithClassName
) {
$scopeClass = $argValueType->getGenericType()->getClassName();
$thisType = $argValueType->getGenericType();
}
}
$closureBindScope = $scope->enterClosureBind($thisType, $scopeClass);
Expand Down
6 changes: 5 additions & 1 deletion tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php
Expand Up @@ -873,7 +873,11 @@ public function testClosureBind(): void
],
[
'Call to an undefined method CallClosureBind\Foo::nonexistentMethod().',
39,
38,
],
[
'Call to an undefined method CallClosureBind\Foo::nonexistentMethod().',
44,
],
]);
}
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Methods/data/closure-bind.php
Expand Up @@ -33,6 +33,11 @@ public function fooMethod(): Foo
$foo->nonexistentMethod();
}, null, new Foo());

\Closure::bind(function (Foo $foo) {
$foo->privateMethod();
$foo->nonexistentMethod();
}, null, get_class(new Foo()));

\Closure::bind(function () {
// $this is Foo
$this->privateMethod();
Expand Down

0 comments on commit 5ef1b3f

Please sign in to comment.