From 4a2cf93d7a2b3733d467bdc267dba55785f0af90 Mon Sep 17 00:00:00 2001
From: Bruce Weirdan <weirdan@gmail.com>
Date: Mon, 11 Mar 2024 01:41:52 +0100
Subject: [PATCH] Don't crash on invalid templates

Fixes vimeo/psalm#9596
---
 .../PhpVisitor/Reflector/ClassLikeNodeScanner.php      |  6 ++++--
 tests/Template/ClassTemplateTest.php                   | 10 ++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php
index b0f4003c49a..325fd4e77a5 100644
--- a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php
+++ b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php
@@ -434,9 +434,11 @@ public function start(PhpParser\Node\Stmt\ClassLike $node): ?bool
                             try {
                                 $type_string = CommentAnalyzer::splitDocLine($type_string)[0];
                             } catch (DocblockParseException $e) {
-                                throw new DocblockParseException(
-                                    $type_string . ' is not a valid type: ' . $e->getMessage(),
+                                $storage->docblock_issues[] = new InvalidDocblock(
+                                    $e->getMessage() . ' in docblock for ' . $fq_classlike_name,
+                                    $name_location ?? $class_location,
                                 );
+                                continue;
                             }
                             $type_string = CommentAnalyzer::sanitizeDocblockType($type_string);
                             try {
diff --git a/tests/Template/ClassTemplateTest.php b/tests/Template/ClassTemplateTest.php
index 12c0025461a..b7dcf2c582f 100644
--- a/tests/Template/ClassTemplateTest.php
+++ b/tests/Template/ClassTemplateTest.php
@@ -5025,6 +5025,16 @@ function getMixedCollection(MyCollection $c): MyCollection {
                     }',
                 'error_message' => 'InvalidReturnStatement',
             ],
+            'noCrashOnBrokenTemplate' => [
+                'code' => <<<'PHP'
+                <?php
+                /**
+                 * @template TValidationRule of callable>|string
+                 */
+                class C {}
+                PHP,
+                'error_message' => 'InvalidDocblock',
+            ],
         ];
     }
 }