Skip to content

Commit

Permalink
PhpParameterReflection - safe guards against nonexistent classes
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jun 11, 2020
1 parent a7de232 commit 51fb445
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 7 deletions.
3 changes: 2 additions & 1 deletion src/Reflection/Php/PhpFunctionReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ private function getParameters(): array
return array_map(function (\ReflectionParameter $reflection): PhpParameterReflection {
return new PhpParameterReflection(
$reflection,
$this->phpDocParameterTypes[$reflection->getName()] ?? null
$this->phpDocParameterTypes[$reflection->getName()] ?? null,
null
);
}, $this->reflection->getParameters());
}
Expand Down
3 changes: 2 additions & 1 deletion src/Reflection/Php/PhpMethodReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ private function getParameters(): array
$this->parameters = array_map(function (\ReflectionParameter $reflection): PhpParameterReflection {
return new PhpParameterReflection(
$reflection,
$this->phpDocParameterTypes[$reflection->getName()] ?? null
$this->phpDocParameterTypes[$reflection->getName()] ?? null,
$this->getDeclaringClass()->getName()
);
}, $this->reflection->getParameters());
}
Expand Down
21 changes: 17 additions & 4 deletions src/Reflection/Php/PhpParameterReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,17 @@ class PhpParameterReflection implements ParameterReflectionWithPhpDocs

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

public function __construct(\ReflectionParameter $reflection, ?Type $phpDocType)
private ?string $declaringClassName;

public function __construct(
\ReflectionParameter $reflection,
?Type $phpDocType,
?string $declaringClassName
)
{
$this->reflection = $reflection;
$this->phpDocType = $phpDocType;
$this->declaringClassName = $declaringClassName;
}

public function isOptional(): bool
Expand All @@ -47,7 +54,7 @@ public function getType(): Type
$this->type = TypehintHelper::decideTypeFromReflection(
$this->reflection->getType(),
$phpDocType,
null,
$this->declaringClassName,
$this->isVariadic()
);
}
Expand Down Expand Up @@ -82,7 +89,7 @@ public function getNativeType(): Type
$this->nativeType = TypehintHelper::decideTypeFromReflection(
$this->reflection->getType(),
null,
$this->reflection->getDeclaringClass() !== null ? $this->reflection->getDeclaringClass()->getName() : null,
$this->declaringClassName,
$this->isVariadic()
);
}
Expand All @@ -93,7 +100,13 @@ public function getNativeType(): Type
public function getDefaultValue(): ?Type
{
if ($this->reflection->isDefaultValueAvailable()) {
return ConstantTypeHelper::getTypeFromValue($this->reflection->getDefaultValue());
try {
$defaultValue = $this->reflection->getDefaultValue();
} catch (\Throwable $e) {
return null;
}

return ConstantTypeHelper::getTypeFromValue($defaultValue);
}

return null;
Expand Down
2 changes: 1 addition & 1 deletion src/Testing/RuleTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static function (array $error) use ($strictlyTypedSprintf): string {
static function (Error $error) use ($strictlyTypedSprintf): string {
$line = $error->getLine();
if ($line === null) {
throw new \PHPStan\ShouldNotHappenException(sprintf('Error (%s) line should not be null.', $error->getMessage()));
return $strictlyTypedSprintf(-1, $error->getMessage(), $error->getTip());
}
return $strictlyTypedSprintf($line, $error->getMessage(), $error->getTip());
},
Expand Down
13 changes: 13 additions & 0 deletions tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1411,4 +1411,17 @@ public function testBug3415Two(): void
$this->analyse([__DIR__ . '/data/bug-3415-2.php'], []);
}

public function testBug3445(): void
{
$this->checkThisOnly = false;
$this->checkNullables = true;
$this->checkUnionTypes = true;
$this->analyse([__DIR__ . '/data/bug-3445.php'], [
[
'Parameter #1 $test of method Bug3445\Foo::doFoo() expects Bug3445\Foo, $this(Bug3445\Bar) given.',
26,
],
]);
}

}
31 changes: 31 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-3445.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Bug3445;

class Foo
{

public function doFoo(self $test): void
{

}

public function doBar($test = UnknownClass::BAR): void
{

}

}

class Bar
{

public function doFoo(Foo $foo)
{
$foo->doFoo(new Foo());
$foo->doFoo($this);

$foo->doBar(new \stdClass());
}

}

0 comments on commit 51fb445

Please sign in to comment.