vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.57k stars 660 forks source link

Misplaced variable causes IncorrectDocblockException #11001

Open janisint opened 5 months ago

janisint commented 5 months ago

Psalm runs in a IncorrectDocblockException when handling a misplaced variable in a PhpDoc block. Example:

<?php

class Foo {
    public function __construct(
        /** @var $bar string[] */
        public array $bar
    )
    {
    }
}

Output Stacktrace:

Uncaught Exception: Psalm\Exception\IncorrectDocblockException Misplaced variable
@php -d memory_limit=-1 vendor/bin/psalm
Target PHP version: 8.2 (inferred from composer.json) Enabled extensions: dom, simplexml.
Scanning files...
Uncaught Exception: Psalm\Exception\IncorrectDocblockException Misplaced variable
Emitted in /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CommentAnalyzer.php:129
Stack trace in the forked worker:
#0 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/CommentAnalyzer.php(63): Psalm\Internal\Analyzer\CommentAnalyzer::arrayToDocblocks(Object(PhpParser\Comment\Doc), Object(Psalm\Internal\Scanner\ParsedDocblock), Object(Psalm\Internal\Scanner\FileScanner), Object(Psalm\Aliases), Array, Array)
#1 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php(599): Psalm\Internal\Analyzer\CommentAnalyzer::getTypeFromComment(Object(PhpParser\Comment\Doc), Object(Psalm\Internal\Scanner\FileScanner), Object(Psalm\Aliases), Array, Array)
#2 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php(207): Psalm\Internal\PhpVisitor\Reflector\FunctionLikeNodeScanner->start(Object(PhpParser\Node\Stmt\ClassMethod))
#3 /var/www/html/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(200): Psalm\Internal\PhpVisitor\ReflectorVisitor->enterNode(Object(PhpParser\Node\Stmt\ClassMethod))
#4 /var/www/html/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(114): PhpParser\NodeTraverser->traverseArray(Array)
#5 /var/www/html/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(223): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Class_))
#6 /var/www/html/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(114): PhpParser\NodeTraverser->traverseArray(Array)
#7 /var/www/html/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(223): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Namespace_))
#8 /var/www/html/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(91): PhpParser\NodeTraverser->traverseArray(Array)
#9 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Scanner/FileScanner.php(79): PhpParser\NodeTraverser->traverse(Array)
#10 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(554): Psalm\Internal\Scanner\FileScanner->scan(Object(Psalm\Codebase), Object(Psalm\Storage\FileStorage), false, Object(Psalm\Progress\DefaultProgress))   
#11 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(782): Psalm\Internal\Codebase\Scanner->scanFile('/var/www/html/p...', Array, true)
#12 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Fork/Pool.php(191): Psalm\Internal\Codebase\Scanner->scanAPath(162, '/var/www/html/p...')
#13 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(332): Psalm\Internal\Fork\Pool->__construct(Object(Psalm\Config), Array, Object(Closure), Object(Closure), Object(Closure))
#14 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(280): Psalm\Internal\Codebase\Scanner->scanFilePaths(3.0)
#15 /var/www/html/vendor/vimeo/psalm/src/Psalm/Codebase.php(505): Psalm\Internal\Codebase\Scanner->scanFiles(Object(Psalm\Internal\Codebase\ClassLikes), 15)
#16 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(510): Psalm\Codebase->scanFiles(15)
#17 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php(374): Psalm\Internal\Analyzer\ProjectAnalyzer->check('/var/www/html', true)
#18 /var/www/html/vendor/vimeo/psalm/psalm(9): Psalm\Internal\Cli\Psalm::run(Array)
#19 /var/www/html/vendor/bin/psalm(119): include('/var/www/html/v...')
#20 {main} in /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Fork/Pool.php:379
Stack trace:
#0 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Fork/Pool.php(413): Psalm\Internal\Fork\Pool->readResultsFromChildren()
#1 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(384): Psalm\Internal\Fork\Pool->wait()
#2 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Scanner.php(280): Psalm\Internal\Codebase\Scanner->scanFilePaths(3.0)
#3 /var/www/html/vendor/vimeo/psalm/src/Psalm/Codebase.php(505): Psalm\Internal\Codebase\Scanner->scanFiles(Object(Psalm\Internal\Codebase\ClassLikes), 15)
#4 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(510): Psalm\Codebase->scanFiles(15)
#5 /var/www/html/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php(374): Psalm\Internal\Analyzer\ProjectAnalyzer->check('/var/www/html', true)
#6 /var/www/html/vendor/vimeo/psalm/psalm(9): Psalm\Internal\Cli\Psalm::run(Array)
#7 /var/www/html/vendor/bin/psalm(119): include('/var/www/html/v...')
#8 {main}
(Psalm 5.23.1@8471a896ccea3526b26d082f4461eeea467f10a4 crashed due to an uncaught Throwable

Correct code:

<?php

class Foo {
    public function __construct(
        /** @var string[] $bar */
        public array $bar
    )
    {
    }
}

No issues!

Snippet: https://psalm.dev/r/a47e3d3a03 Psalm version: 5.24.0 (latest as of this time)

Seems to be related to https://github.com/vimeo/psalm/issues/9809, however I don't think that issue truly grasps what went wrong and that this error should be fixed.


Hint to developers facing this issue:

Use vendor/bin/psalm --debug to find out where the error occurs.

psalm-github-bot[bot] commented 5 months ago

I found these snippets:

https://psalm.dev/r/a47e3d3a03 ```php