diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 00957c803b..b05d89840b 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -134,6 +134,20 @@ jobs: mv src/Bar.php.orig src/Bar.php echo -n > phpstan-baseline.neon ../../bin/phpstan -vvv + - script: | + cd e2e/bug10449 + ../../bin/phpstan analyze + git apply patch.diff + rm phpstan-baseline.neon + mv after-phpstan-baseline.neon phpstan-baseline.neon + ../../bin/phpstan analyze -vvv + - script: | + cd e2e/bug10449b + ../../bin/phpstan analyze + git apply patch.diff + rm phpstan-baseline.neon + mv after-phpstan-baseline.neon phpstan-baseline.neon + ../../bin/phpstan analyze -vvv - script: | cd e2e/bug-9622 echo -n > phpstan-baseline.neon diff --git a/e2e/bug10449/.gitignore b/e2e/bug10449/.gitignore new file mode 100644 index 0000000000..57872d0f1e --- /dev/null +++ b/e2e/bug10449/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/e2e/bug10449/after-phpstan-baseline.neon b/e2e/bug10449/after-phpstan-baseline.neon new file mode 100644 index 0000000000..257ff5844d --- /dev/null +++ b/e2e/bug10449/after-phpstan-baseline.neon @@ -0,0 +1,11 @@ +parameters: + ignoreErrors: + - + message: "#^Method App\\\\Example\\:\\:__invoke\\(\\) should return string but returns int\\.$#" + count: 1 + path: src/Example.php + + - + message: "#^Parameter \\#1 \\$s of method App\\\\Example\\:\\:needsString\\(\\) expects string, int given\\.$#" + count: 1 + path: src/Example.php diff --git a/e2e/bug10449/composer.json b/e2e/bug10449/composer.json new file mode 100644 index 0000000000..829038d1b8 --- /dev/null +++ b/e2e/bug10449/composer.json @@ -0,0 +1,16 @@ +{ + "name": "devnix/phpstan-reproducer-10449", + "type": "project", + "license": "MIT", + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "authors": [ + { + "name": "Pablo Largo Mohedano", + "email": "devnix.code@gmail.com" + } + ] +} diff --git a/e2e/bug10449/composer.lock b/e2e/bug10449/composer.lock new file mode 100644 index 0000000000..b3a0c80ec5 --- /dev/null +++ b/e2e/bug10449/composer.lock @@ -0,0 +1,83 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "6f47c32416fc8e4551ac72cd87f0d0f4", + "packages": [], + "packages-dev": [ + { + "name": "phpstan/phpstan", + "version": "1.10.57", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "1627b1d03446904aaa77593f370c5201d2ecc34e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1627b1d03446904aaa77593f370c5201d2ecc34e", + "reference": "1627b1d03446904aaa77593f370c5201d2ecc34e", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2024-01-24T11:51:34+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/e2e/bug10449/patch.diff b/e2e/bug10449/patch.diff new file mode 100644 index 0000000000..a27b509243 --- /dev/null +++ b/e2e/bug10449/patch.diff @@ -0,0 +1,21 @@ +diff --git a/e2e/bug10449/src/Query/ExampleQueryHandler.php b/e2e/bug10449/src/Query/ExampleQueryHandler.php +index e9bc1d59f..f5d1c07bf 100644 +--- a/e2e/bug10449/src/Query/ExampleQueryHandler.php ++++ b/e2e/bug10449/src/Query/ExampleQueryHandler.php +@@ -7,13 +7,13 @@ namespace App\Query; + use App\Bus\QueryHandlerInterface; + + /** +- * @phpstan-type Return string ++ * @phpstan-type Return int + */ + final class ExampleQueryHandler implements QueryHandlerInterface + { + /** @return Return */ + public function __invoke(ExampleQuery $exampleQuery) + { +- return '1'; ++ return 1; + } + } +\ No newline at end of file diff --git a/e2e/bug10449/phpstan-baseline.neon b/e2e/bug10449/phpstan-baseline.neon new file mode 100644 index 0000000000..aab4991158 --- /dev/null +++ b/e2e/bug10449/phpstan-baseline.neon @@ -0,0 +1,2 @@ +parameters: + ignoreErrors: [] diff --git a/e2e/bug10449/phpstan.dist.neon b/e2e/bug10449/phpstan.dist.neon new file mode 100644 index 0000000000..b217109006 --- /dev/null +++ b/e2e/bug10449/phpstan.dist.neon @@ -0,0 +1,7 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 9 + paths: + - src \ No newline at end of file diff --git a/e2e/bug10449/src/Bus/QueryBusInterface.php b/e2e/bug10449/src/Bus/QueryBusInterface.php new file mode 100644 index 0000000000..28a95e41b6 --- /dev/null +++ b/e2e/bug10449/src/Bus/QueryBusInterface.php @@ -0,0 +1,17 @@ + $query + * + * @return T + */ + public function handle(QueryInterface $query); +} \ No newline at end of file diff --git a/e2e/bug10449/src/Bus/QueryHandlerInterface.php b/e2e/bug10449/src/Bus/QueryHandlerInterface.php new file mode 100644 index 0000000000..88faa0164a --- /dev/null +++ b/e2e/bug10449/src/Bus/QueryHandlerInterface.php @@ -0,0 +1,9 @@ +queryBus->handle(new Query\ExampleQuery()); + $this->needsString($value); + return $value; + } + + private function needsString(string $s):void {} +} \ No newline at end of file diff --git a/e2e/bug10449/src/Query/ExampleQuery.php b/e2e/bug10449/src/Query/ExampleQuery.php new file mode 100644 index 0000000000..a5c7637793 --- /dev/null +++ b/e2e/bug10449/src/Query/ExampleQuery.php @@ -0,0 +1,15 @@ + + */ +final class ExampleQuery implements QueryInterface +{ +} \ No newline at end of file diff --git a/e2e/bug10449/src/Query/ExampleQueryHandler.php b/e2e/bug10449/src/Query/ExampleQueryHandler.php new file mode 100644 index 0000000000..e9bc1d59f0 --- /dev/null +++ b/e2e/bug10449/src/Query/ExampleQueryHandler.php @@ -0,0 +1,19 @@ + $query + * + * @return T + */ + public function handle(QueryInterface $query); +} \ No newline at end of file diff --git a/e2e/bug10449b/src/Bus/QueryHandlerInterface.php b/e2e/bug10449b/src/Bus/QueryHandlerInterface.php new file mode 100644 index 0000000000..88faa0164a --- /dev/null +++ b/e2e/bug10449b/src/Bus/QueryHandlerInterface.php @@ -0,0 +1,9 @@ +queryBus->handle($x); + $this->needsString($value); + return $value; + } + + return 'hello'; + } + + private function needsString(string $s):void {} +} \ No newline at end of file diff --git a/e2e/bug10449b/src/Query/ExampleQuery.php b/e2e/bug10449b/src/Query/ExampleQuery.php new file mode 100644 index 0000000000..a5c7637793 --- /dev/null +++ b/e2e/bug10449b/src/Query/ExampleQuery.php @@ -0,0 +1,15 @@ + + */ +final class ExampleQuery implements QueryInterface +{ +} \ No newline at end of file diff --git a/e2e/bug10449b/src/Query/ExampleQueryHandler.php b/e2e/bug10449b/src/Query/ExampleQueryHandler.php new file mode 100644 index 0000000000..e9bc1d59f0 --- /dev/null +++ b/e2e/bug10449b/src/Query/ExampleQueryHandler.php @@ -0,0 +1,19 @@ +getDocComment(); - if ($docComment !== null) { - $phpDoc = $this->fileTypeMapper->getResolvedPhpDoc( - $scope->getFile(), - $scope->isInClass() ? $scope->getClassReflection()->getName() : null, - $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null, - null, - $docComment->getText(), - ); - foreach ($phpDoc->getTypeAliasImportTags() as $importTag) { - $this->addClassToDependencies($importTag->getImportedFrom(), $dependenciesReflections); - } - } - } - if ($node instanceof Node\Stmt\Class_) { if ($node->namespacedName !== null) { $this->addClassToDependencies($node->namespacedName->toString(), $dependenciesReflections); @@ -595,6 +577,13 @@ private function addClassToDependencies(string $className, array &$dependenciesR } } + $phpDoc = $classReflection->getResolvedPhpDoc(); + if ($phpDoc !== null) { + foreach ($phpDoc->getTypeAliasImportTags() as $importTag) { + $dependenciesReflections[] = $this->reflectionProvider->getClass($importTag->getImportedFrom()); + } + } + $classReflection = $classReflection->getParentClass(); } while ($classReflection !== null); }