Skip to content

Commit 28ed924

Browse files
rainbow-alexondrejmirtes
authored andcommitted
constant arrays without an explicit class string should not resolve the class name
1 parent bd36d6d commit 28ed924

3 files changed

Lines changed: 83 additions & 1 deletion

File tree

src/Type/Constant/ConstantArrayType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ private function findTypeAndMethodName(): ?ConstantArrayTypeAndMethod
352352
return ConstantArrayTypeAndMethod::createUnknown();
353353
}
354354

355-
if ($classOrObject instanceof ConstantStringType) {
355+
if ($classOrObject instanceof ConstantStringType && $classOrObject->isClassString()) {
356356
$broker = Broker::getInstance();
357357
if (!$broker->hasClass($classOrObject->getValue())) {
358358
return ConstantArrayTypeAndMethod::createUnknown();

src/Type/Constant/ConstantStringType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public function getValue(): string
4545
return $this->value;
4646
}
4747

48+
public function isClassString(): bool
49+
{
50+
return $this->isClassString;
51+
}
52+
4853
public function describe(VerbosityLevel $level): string
4954
{
5055
return $level->handle(

tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,4 +589,81 @@ public function testResolveTemplateTypes(Type $received, Type $template, array $
589589
);
590590
}
591591

592+
/**
593+
* @dataProvider dataIsCallable
594+
* @group solo
595+
*/
596+
public function testIsCallable(ConstantArrayType $type, TrinaryLogic $expectedResult): void
597+
{
598+
$actualResult = $type->isCallable();
599+
$this->assertSame(
600+
$expectedResult->describe(),
601+
$actualResult->describe(),
602+
sprintf('%s -> isCallable()', $type->describe(VerbosityLevel::precise()))
603+
);
604+
}
605+
606+
public function dataIsCallable(): iterable
607+
{
608+
yield 'zero items' => [
609+
new ConstantArrayType([], []),
610+
TrinaryLogic::createNo(),
611+
];
612+
613+
yield 'function name' => [
614+
new ConstantArrayType([
615+
new ConstantIntegerType(0),
616+
], [
617+
new ConstantStringType('strlen'),
618+
]),
619+
TrinaryLogic::createNo(),
620+
];
621+
622+
yield 'existing static method' => [
623+
new ConstantArrayType([
624+
new ConstantIntegerType(0),
625+
new ConstantIntegerType(1),
626+
], [
627+
new ConstantStringType(\Closure::class, true),
628+
new ConstantStringType('bind'),
629+
]),
630+
TrinaryLogic::createYes(),
631+
];
632+
633+
yield 'non-existing static method' => [
634+
new ConstantArrayType([
635+
new ConstantIntegerType(0),
636+
new ConstantIntegerType(1),
637+
], [
638+
new ConstantStringType(\Closure::class, true),
639+
new ConstantStringType('foobar'),
640+
]),
641+
TrinaryLogic::createNo(),
642+
];
643+
644+
/**
645+
* @see https://github.com/phpstan/phpstan/issues/3428
646+
*/
647+
yield 'existing static method but not a class string' => [
648+
new ConstantArrayType([
649+
new ConstantIntegerType(0),
650+
new ConstantIntegerType(1),
651+
], [
652+
new ConstantStringType('Closure'),
653+
new ConstantStringType('foobar'),
654+
]),
655+
TrinaryLogic::createMaybe(),
656+
];
657+
658+
yield 'existing static method but with string keys' => [
659+
new ConstantArrayType([
660+
new ConstantStringType('a'),
661+
new ConstantStringType('b'),
662+
], [
663+
new ConstantStringType(\Closure::class, true),
664+
new ConstantStringType('bind'),
665+
]),
666+
TrinaryLogic::createNo(),
667+
];
668+
}
592669
}

0 commit comments

Comments
 (0)