Skip to content

Commit 51fb445

Browse files
committed
PhpParameterReflection - safe guards against nonexistent classes
1 parent a7de232 commit 51fb445

File tree

6 files changed

+66
-7
lines changed

6 files changed

+66
-7
lines changed

src/Reflection/Php/PhpFunctionReflection.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ private function getParameters(): array
145145
return array_map(function (\ReflectionParameter $reflection): PhpParameterReflection {
146146
return new PhpParameterReflection(
147147
$reflection,
148-
$this->phpDocParameterTypes[$reflection->getName()] ?? null
148+
$this->phpDocParameterTypes[$reflection->getName()] ?? null,
149+
null
149150
);
150151
}, $this->reflection->getParameters());
151152
}

src/Reflection/Php/PhpMethodReflection.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ private function getParameters(): array
244244
$this->parameters = array_map(function (\ReflectionParameter $reflection): PhpParameterReflection {
245245
return new PhpParameterReflection(
246246
$reflection,
247-
$this->phpDocParameterTypes[$reflection->getName()] ?? null
247+
$this->phpDocParameterTypes[$reflection->getName()] ?? null,
248+
$this->getDeclaringClass()->getName()
248249
);
249250
}, $this->reflection->getParameters());
250251
}

src/Reflection/Php/PhpParameterReflection.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,17 @@ class PhpParameterReflection implements ParameterReflectionWithPhpDocs
2020

2121
private ?\PHPStan\Type\Type $nativeType = null;
2222

23-
public function __construct(\ReflectionParameter $reflection, ?Type $phpDocType)
23+
private ?string $declaringClassName;
24+
25+
public function __construct(
26+
\ReflectionParameter $reflection,
27+
?Type $phpDocType,
28+
?string $declaringClassName
29+
)
2430
{
2531
$this->reflection = $reflection;
2632
$this->phpDocType = $phpDocType;
33+
$this->declaringClassName = $declaringClassName;
2734
}
2835

2936
public function isOptional(): bool
@@ -47,7 +54,7 @@ public function getType(): Type
4754
$this->type = TypehintHelper::decideTypeFromReflection(
4855
$this->reflection->getType(),
4956
$phpDocType,
50-
null,
57+
$this->declaringClassName,
5158
$this->isVariadic()
5259
);
5360
}
@@ -82,7 +89,7 @@ public function getNativeType(): Type
8289
$this->nativeType = TypehintHelper::decideTypeFromReflection(
8390
$this->reflection->getType(),
8491
null,
85-
$this->reflection->getDeclaringClass() !== null ? $this->reflection->getDeclaringClass()->getName() : null,
92+
$this->declaringClassName,
8693
$this->isVariadic()
8794
);
8895
}
@@ -93,7 +100,13 @@ public function getNativeType(): Type
93100
public function getDefaultValue(): ?Type
94101
{
95102
if ($this->reflection->isDefaultValueAvailable()) {
96-
return ConstantTypeHelper::getTypeFromValue($this->reflection->getDefaultValue());
103+
try {
104+
$defaultValue = $this->reflection->getDefaultValue();
105+
} catch (\Throwable $e) {
106+
return null;
107+
}
108+
109+
return ConstantTypeHelper::getTypeFromValue($defaultValue);
97110
}
98111

99112
return null;

src/Testing/RuleTestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static function (array $error) use ($strictlyTypedSprintf): string {
156156
static function (Error $error) use ($strictlyTypedSprintf): string {
157157
$line = $error->getLine();
158158
if ($line === null) {
159-
throw new \PHPStan\ShouldNotHappenException(sprintf('Error (%s) line should not be null.', $error->getMessage()));
159+
return $strictlyTypedSprintf(-1, $error->getMessage(), $error->getTip());
160160
}
161161
return $strictlyTypedSprintf($line, $error->getMessage(), $error->getTip());
162162
},

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,4 +1411,17 @@ public function testBug3415Two(): void
14111411
$this->analyse([__DIR__ . '/data/bug-3415-2.php'], []);
14121412
}
14131413

1414+
public function testBug3445(): void
1415+
{
1416+
$this->checkThisOnly = false;
1417+
$this->checkNullables = true;
1418+
$this->checkUnionTypes = true;
1419+
$this->analyse([__DIR__ . '/data/bug-3445.php'], [
1420+
[
1421+
'Parameter #1 $test of method Bug3445\Foo::doFoo() expects Bug3445\Foo, $this(Bug3445\Bar) given.',
1422+
26,
1423+
],
1424+
]);
1425+
}
1426+
14141427
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Bug3445;
4+
5+
class Foo
6+
{
7+
8+
public function doFoo(self $test): void
9+
{
10+
11+
}
12+
13+
public function doBar($test = UnknownClass::BAR): void
14+
{
15+
16+
}
17+
18+
}
19+
20+
class Bar
21+
{
22+
23+
public function doFoo(Foo $foo)
24+
{
25+
$foo->doFoo(new Foo());
26+
$foo->doFoo($this);
27+
28+
$foo->doBar(new \stdClass());
29+
}
30+
31+
}

0 commit comments

Comments
 (0)