Skip to content

Commit 8c2b2b4

Browse files
authored
Merge branch refs/heads/2.1.x into 2.2.x
2 parents 7dfcbf1 + f018b6e commit 8c2b2b4

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

tests/PHPStan/Parser/CachedParserTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Generator;
66
use PhpParser\Node;
77
use PhpParser\Node\Stmt\Namespace_;
8+
use PHPStan\BetterReflection\Reflection\ExprCacheHelper;
89
use PHPStan\File\FileHelper;
910
use PHPStan\File\FileReader;
1011
use PHPStan\Testing\PHPStanTestCase;
@@ -123,4 +124,51 @@ public function testParseTheSameFileWithDifferentMethod(): void
123124
$this->assertSame(2, $stmts[0]->stmts[1]->expr->expr->class->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX));
124125
}
125126

127+
public function testWithExprCacheHelper(): void
128+
{
129+
$fileHelper = self::getContainer()->getByType(FileHelper::class);
130+
$pathRoutingParser = new PathRoutingParser(
131+
$fileHelper,
132+
self::getContainer()->getService('currentPhpVersionRichParser'),
133+
self::getContainer()->getService('currentPhpVersionSimpleDirectParser'),
134+
self::getContainer()->getService('php8Parser'),
135+
null,
136+
);
137+
$parser = new CachedParser($pathRoutingParser, 500);
138+
$path = $fileHelper->normalizePath(__DIR__ . '/data/parser-cache-bug.php');
139+
$pathRoutingParser->setAnalysedFiles([$path]);
140+
$contents = FileReader::read($path);
141+
$stmts = $parser->parseString($contents);
142+
143+
$this->assertInstanceOf(Namespace_::class, $stmts[0]);
144+
$ns = $stmts[0];
145+
146+
$this->assertInstanceOf(Node\Stmt\Class_::class, $ns->stmts[1]);
147+
$class = $ns->stmts[1];
148+
149+
$this->assertInstanceOf(Node\Stmt\Property::class, $class->stmts[0]);
150+
$property = $class->stmts[0];
151+
$group = $property->attrGroups[0];
152+
$attribute = $group->attrs[0];
153+
154+
$expr = $attribute->args[0]->value;
155+
$this->assertSame(['startLine' => 8, 'startTokenPos' => 21, 'startFilePos' => 88, 'endLine' => 8, 'endTokenPos' => 21, 'endFilePos' => 94, 'kind' => 1, 'rawValue' => "'hello'"], $expr->getAttributes());
156+
$exported = ExprCacheHelper::export($expr);
157+
$reImported = ExprCacheHelper::import($exported);
158+
$this->assertSame(['startLine' => 8, 'startTokenPos' => 21, 'startFilePos' => 88, 'endLine' => 8, 'endTokenPos' => 21, 'endFilePos' => 94, 'kind' => 1, 'rawValue' => "'hello'"], $reImported->getAttributes());
159+
160+
$this->assertInstanceOf(Node\Stmt\Property::class, $class->stmts[1]);
161+
$property = $class->stmts[1];
162+
$group = $property->attrGroups[0];
163+
$attribute = $group->attrs[0];
164+
165+
$expr = $attribute->args[0]->value;
166+
$this->assertSame(['startLine' => 10, 'startTokenPos' => 35, 'startFilePos' => 137, 'endLine' => 10, 'endTokenPos' => 35, 'endFilePos' => 143, 'kind' => 1, 'rawValue' => "'hello'"], $expr->getAttributes());
167+
$exported = ExprCacheHelper::export($expr);
168+
unset($exported['attributes']['startLine']); // modify attributes
169+
$reImported = ExprCacheHelper::import($exported);
170+
// assert that we get back the default start-line instead of a stale cached startLine of previous same value expression
171+
$this->assertSame(['startLine' => 1, 'startTokenPos' => 35, 'startFilePos' => 137, 'endLine' => 10, 'endTokenPos' => 35, 'endFilePos' => 143, 'kind' => 1, 'rawValue' => "'hello'"], $reImported->getAttributes());
172+
}
173+
126174
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace ParserCacheBug;
4+
5+
use Attribute;
6+
7+
class ParserCacheBug {
8+
#[MyAttribute('hello')]
9+
protected string $foo;
10+
#[MyAttribute('hello')]
11+
protected string $bar;
12+
}
13+
14+
#[Attribute]
15+
class MyAttribute
16+
{
17+
public string $arg;
18+
19+
public function __construct(string $event)
20+
{
21+
$this->arg = $event;
22+
}
23+
}

0 commit comments

Comments
 (0)