Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions build/enum-adapter-errors.neon
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ parameters:

-
message: "#^Call to method getName\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#"
count: 3
count: 4
path: ../src/Reflection/Php/PhpClassReflectionExtension.php

-
Expand All @@ -277,7 +277,7 @@ parameters:

-
message: "#^Call to method isTrait\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#"
count: 1
count: 2
path: ../src/Reflection/Php/PhpClassReflectionExtension.php

-
Expand Down Expand Up @@ -335,6 +335,11 @@ parameters:
count: 1
path: ../tests/PHPStan/Analyser/AnalyserIntegrationTest.php

-
message: "#^Call to method getProperty\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#"
count: 1
path: ../src/PhpDoc/PhpDocInheritanceResolver.php

-
message: "#^Call to method getName\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#"
count: 1
Expand Down
10 changes: 10 additions & 0 deletions src/PhpDoc/PhpDocInheritanceResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ private function docBlockToResolvedDocBlock(PhpDocBlock $phpDocBlock, ?string $t

if ($propertyName !== null && $classReflection->getNativeReflection()->hasProperty($propertyName)) {
$stub = $this->stubPhpDocProvider->findPropertyPhpDoc($classReflection->getName(), $propertyName);

if ($stub === null) {
$propertyReflection = $classReflection->getNativeReflection()->getProperty($propertyName);

$propertyDeclaringClass = $propertyReflection->getBetterReflection()->getDeclaringClass();

if ($propertyDeclaringClass->isTrait() && (! $propertyReflection->getDeclaringClass()->isTrait() || $propertyReflection->getDeclaringClass()->getName() !== $propertyDeclaringClass->getName())) {
$stub = $this->stubPhpDocProvider->findPropertyPhpDoc($propertyDeclaringClass->getName(), $propertyName);
}
}
if ($stub !== null) {
return $stub;
}
Expand Down
18 changes: 18 additions & 0 deletions src/Reflection/Php/PhpClassReflectionExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,24 @@ private function createMethod(
$resolvedPhpDoc = null;
$stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($declaringClass, $methodReflection->getName(), array_map(static fn (ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters()));
$phpDocBlockClassReflection = $declaringClass;

if ($methodReflection->getReflection() !== null) {
$methodDeclaringClass = $methodReflection->getReflection()->getBetterReflection()->getDeclaringClass();

if ($stubPhpDocPair === null && $methodDeclaringClass->isTrait()) {
if (! $methodReflection->getDeclaringClass()->isTrait() || $methodDeclaringClass->getName() !== $methodReflection->getDeclaringClass()->getName()) {
$stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors(
$this->reflectionProviderProvider->getReflectionProvider()->getClass($methodDeclaringClass->getName()),
$methodReflection->getName(),
array_map(
static fn (ReflectionParameter $parameter): string => $parameter->getName(),
$methodReflection->getParameters(),
),
);
}
}
}

if ($stubPhpDocPair !== null) {
[$resolvedPhpDoc, $phpDocBlockClassReflection] = $stubPhpDocPair;
}
Expand Down
35 changes: 35 additions & 0 deletions tests/PHPStan/Analyser/TraitStubFilesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);

namespace PHPStan\Analyser;

use PHPStan\Testing\TypeInferenceTestCase;

class TraitStubFilesTest extends TypeInferenceTestCase
{

public function dataFileAsserts(): iterable
{
yield from $this->gatherAssertTypes(__DIR__ . '/data/trait-stubs.php');
}

/**
* @dataProvider dataFileAsserts
* @param mixed ...$args
*/
public function testFileAsserts(
string $assertType,
string $file,
...$args,
): void
{
$this->assertFileAsserts($assertType, $file, ...$args);
}

public static function getAdditionalConfigFiles(): array
{
return [
__DIR__ . '/trait-stubs.neon',
];
}

}
28 changes: 28 additions & 0 deletions tests/PHPStan/Analyser/data/trait-stubs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace TraitStubs;

use function PHPStan\Testing\assertType;

trait TraitA
{
public $notTypedFoo;

/**
* @param int $int
*
* @return int
*/
public function doFoo($int)
{
return rand($int, $int + 100);
}
}

class Bar
{
use TraitA;
}

assertType('string', (new Bar)->doFoo(5));
assertType('int', (new Bar)->notTypedFoo);
17 changes: 17 additions & 0 deletions tests/PHPStan/Analyser/data/trait-stubs.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace TraitStubs;

trait TraitA
{

/** @var int */
public $notTypedFoo;

/**
* @param string $int
*
* @return string
*/
public function doFoo($int) {}
}
3 changes: 3 additions & 0 deletions tests/PHPStan/Analyser/trait-stubs.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
parameters:
stubFiles:
- data/trait-stubs.stub
5 changes: 5 additions & 0 deletions tests/PHPStan/Levels/data/stubs-methods-5.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,10 @@
"message": "Parameter #1 $j of method StubsIntegrationTest\\YetYetAnotherFoo::doFoo() expects int, string given.",
"line": 226,
"ignorable": true
},
{
"message": "Parameter #1 $int of method StubsIntegrationTest\\ClassUsingStubbedTrait::doFoo() expects int, string given.",
"line": 243,
"ignorable": true
}
]
17 changes: 17 additions & 0 deletions tests/PHPStan/Levels/data/stubs-methods.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,20 @@ function (YetYetAnotherFoo $foo): void {
$string = $foo->doFoo('test');
$foo->doFoo($string);
};

trait StubbedTrait
{
public function doFoo($int)
{

}
}

class ClassUsingStubbedTrait
{
use StubbedTrait;
}

function (ClassUsingStubbedTrait $foo): void {
$foo->doFoo('string');
};
13 changes: 13 additions & 0 deletions tests/notAutoloaded/stubs-methods.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,16 @@ public function doFoo($i)
}

}

trait StubbedTrait
{
/**
* @param int $int
*
* @return void
*/
public function doFoo($int)
{

}
}