diff --git a/tests/PHPStan/Parser/CachedParserTest.php b/tests/PHPStan/Parser/CachedParserTest.php index 29ca21ee3a..df3097d3cb 100644 --- a/tests/PHPStan/Parser/CachedParserTest.php +++ b/tests/PHPStan/Parser/CachedParserTest.php @@ -5,6 +5,7 @@ use Generator; use PhpParser\Node; use PhpParser\Node\Stmt\Namespace_; +use PHPStan\BetterReflection\Reflection\ExprCacheHelper; use PHPStan\File\FileHelper; use PHPStan\File\FileReader; use PHPStan\Testing\PHPStanTestCase; @@ -123,4 +124,51 @@ public function testParseTheSameFileWithDifferentMethod(): void $this->assertSame(2, $stmts[0]->stmts[1]->expr->expr->class->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX)); } + public function testWithExprCacheHelper(): void + { + $fileHelper = self::getContainer()->getByType(FileHelper::class); + $pathRoutingParser = new PathRoutingParser( + $fileHelper, + self::getContainer()->getService('currentPhpVersionRichParser'), + self::getContainer()->getService('currentPhpVersionSimpleDirectParser'), + self::getContainer()->getService('php8Parser'), + null, + ); + $parser = new CachedParser($pathRoutingParser, 500); + $path = $fileHelper->normalizePath(__DIR__ . '/data/parser-cache-bug.php'); + $pathRoutingParser->setAnalysedFiles([$path]); + $contents = FileReader::read($path); + $stmts = $parser->parseString($contents); + + $this->assertInstanceOf(Namespace_::class, $stmts[0]); + $ns = $stmts[0]; + + $this->assertInstanceOf(Node\Stmt\Class_::class, $ns->stmts[1]); + $class = $ns->stmts[1]; + + $this->assertInstanceOf(Node\Stmt\Property::class, $class->stmts[0]); + $property = $class->stmts[0]; + $group = $property->attrGroups[0]; + $attribute = $group->attrs[0]; + + $expr = $attribute->args[0]->value; + $this->assertSame(['startLine' => 8, 'startTokenPos' => 21, 'startFilePos' => 88, 'endLine' => 8, 'endTokenPos' => 21, 'endFilePos' => 94, 'kind' => 1, 'rawValue' => "'hello'"], $expr->getAttributes()); + $exported = ExprCacheHelper::export($expr); + $reImported = ExprCacheHelper::import($exported); + $this->assertSame(['startLine' => 8, 'startTokenPos' => 21, 'startFilePos' => 88, 'endLine' => 8, 'endTokenPos' => 21, 'endFilePos' => 94, 'kind' => 1, 'rawValue' => "'hello'"], $reImported->getAttributes()); + + $this->assertInstanceOf(Node\Stmt\Property::class, $class->stmts[1]); + $property = $class->stmts[1]; + $group = $property->attrGroups[0]; + $attribute = $group->attrs[0]; + + $expr = $attribute->args[0]->value; + $this->assertSame(['startLine' => 10, 'startTokenPos' => 35, 'startFilePos' => 137, 'endLine' => 10, 'endTokenPos' => 35, 'endFilePos' => 143, 'kind' => 1, 'rawValue' => "'hello'"], $expr->getAttributes()); + $exported = ExprCacheHelper::export($expr); + unset($exported['attributes']['startLine']); // modify attributes + $reImported = ExprCacheHelper::import($exported); + // assert that we get back the default start-line instead of a stale cached startLine of previous same value expression + $this->assertSame(['startLine' => 1, 'startTokenPos' => 35, 'startFilePos' => 137, 'endLine' => 10, 'endTokenPos' => 35, 'endFilePos' => 143, 'kind' => 1, 'rawValue' => "'hello'"], $reImported->getAttributes()); + } + } diff --git a/tests/PHPStan/Parser/data/parser-cache-bug.php b/tests/PHPStan/Parser/data/parser-cache-bug.php new file mode 100644 index 0000000000..02957046da --- /dev/null +++ b/tests/PHPStan/Parser/data/parser-cache-bug.php @@ -0,0 +1,23 @@ +arg = $event; + } +}