diff --git a/src/Psalm/DocComment.php b/src/Psalm/DocComment.php index 2a04279f4..79547e777 100644 --- a/src/Psalm/DocComment.php +++ b/src/Psalm/DocComment.php @@ -40,13 +40,17 @@ final class DocComment /** * Parse a docblock comment into its parts. */ - public static function parsePreservingLength(Doc $docblock): ParsedDocblock + public static function parsePreservingLength(Doc $docblock, bool $no_psalm_error = false): ParsedDocblock { $parsed_docblock = DocblockParser::parse( $docblock->getText(), $docblock->getStartFilePos(), ); + if ($no_psalm_error) { + return $parsed_docblock; + } + foreach ($parsed_docblock->tags as $special_key => $_) { if (strpos($special_key, 'psalm-') === 0) { $special_key = substr($special_key, 6); diff --git a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index 4f89f5de1..caf95b380 100644 --- a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -802,6 +802,14 @@ final class StatementsAnalyzer extends SourceAnalyzer $this->parsed_docblock = null; } + if ($this->parsed_docblock === null) { + try { + $this->parsed_docblock = DocComment::parsePreservingLength($docblock, true); + } catch (DocblockParseException $e) { + // already reported above + } + } + $comments = $this->parsed_docblock; if (isset($comments->tags['psalm-scope-this'])) { diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php index 25fcb44bf..ad3f0a4a0 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockParser.php @@ -53,7 +53,8 @@ final class FunctionLikeDocblockParser CodeLocation $code_location, string $cased_function_id ): FunctionDocblockComment { - $parsed_docblock = DocComment::parsePreservingLength($comment); + // invalid @psalm annotations are already reported by the StatementsAnalyzer + $parsed_docblock = DocComment::parsePreservingLength($comment, true); $comment_text = $comment->getText(); diff --git a/tests/AnnotationTest.php b/tests/AnnotationTest.php index 7a7345bd5..f059c4d5c 100644 --- a/tests/AnnotationTest.php +++ b/tests/AnnotationTest.php @@ -535,6 +535,45 @@ class AnnotationTest extends TestCase '$_===' => 'list', ], ], + 'invalidPsalmForMethodShouldNotBreakDocblock' => [ + 'code' => 'foo("hello"); + ', + 'assertions' => [ + '$_===' => 'non-falsy-string', + ], + 'ignored_issues' => ['InvalidDocblock'], + ], + 'invalidPsalmForFunctionShouldNotBreakDocblock' => [ + 'code' => ' [ + '$_===' => 'non-falsy-string', + ], + 'ignored_issues' => ['InvalidDocblock'], + ], 'builtInClassInAShape' => [ 'code' => '