Skip to content

Commit c7c28d4

Browse files
SanderMullerclaude
authored andcommitted
Cache parsed ASTs behind the path routing, one cache per parser
CachedParser keys ASTs by source code, and it sat in front of PathRoutingParser. A file outside the analysed paths goes to the cleaning parser, which strips function bodies. When such a file has the same bytes as an analysed file and is parsed first, the analysed file gets the stripped AST from the cache, and every method in it is reported as return.missing. PathRoutingParser now wraps one CachedParser for the rich parser and one for the cleaning parser, and defaultAnalysisParser is the router. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 9c49ae3 commit c7c28d4

7 files changed

Lines changed: 78 additions & 4 deletions

File tree

‎.github/workflows/e2e-tests.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ jobs:
243243
- script: |
244244
cd e2e/bug-15102b
245245
../../bin/phpstan analyze
246+
- script: |
247+
cd e2e/bug-15231
248+
../../bin/phpstan analyze
246249
- script: |
247250
cd e2e/bug-15102
248251
composer install

‎conf/parsers.neon‎

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ services:
5252
pathRoutingParser:
5353
class: PHPStan\Parser\PathRoutingParser
5454
arguments:
55-
currentPhpVersionRichParser: @currentPhpVersionRichParser
56-
currentPhpVersionSimpleParser: @currentPhpVersionSimpleParser
55+
currentPhpVersionRichParser: @cachedRichParser
56+
currentPhpVersionSimpleParser: @cachedSimpleParser
5757
php8Parser: @php8Parser
5858
singleReflectionFile: %singleReflectionFile%
5959
autowired: false
@@ -64,14 +64,29 @@ services:
6464
wrappedParser: @defaultAnalysisParser
6565
autowired: false
6666

67-
defaultAnalysisParser:
67+
# the cache sits behind the routing: CachedParser keys by source code, so
68+
# one cache in front of it would hand the body-stripped AST of a file
69+
# outside the analysed paths to an analysed file with the same contents
70+
cachedRichParser:
71+
class: PHPStan\Parser\CachedParser
72+
arguments:
73+
originalParser: @currentPhpVersionRichParser
74+
cachedNodesByStringCountMax: %cache.nodesByStringCountMax%
75+
cachedSourceBytesMax: %cache.nodesByStringSourceBytesMax%
76+
autowired: false
77+
78+
cachedSimpleParser:
6879
class: PHPStan\Parser\CachedParser
6980
arguments:
70-
originalParser: @pathRoutingParser
81+
originalParser: @currentPhpVersionSimpleParser
7182
cachedNodesByStringCountMax: %cache.nodesByStringCountMax%
7283
cachedSourceBytesMax: %cache.nodesByStringSourceBytesMax%
7384
autowired: false
7485

86+
defaultAnalysisParser:
87+
factory: @pathRoutingParser
88+
autowired: false
89+
7590
freshStubParser:
7691
class: PHPStan\Parser\StubParser
7792
arguments:

‎e2e/bug-15231/autoload.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
spl_autoload_register(function (string $class): void {
4+
if ($class === 'Demo\\Zeta') {
5+
require __DIR__ . '/lib/Zeta.php';
6+
}
7+
});

‎e2e/bug-15231/lib/Zeta.php‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Demo;
4+
5+
class Zeta
6+
{
7+
public function name(): string
8+
{
9+
return 'zeta';
10+
}
11+
12+
public function size(): int
13+
{
14+
return 1;
15+
}
16+
}

‎e2e/bug-15231/phpstan.dist.neon‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
parameters:
2+
level: 7
3+
bootstrapFiles:
4+
- autoload.php
5+
paths:
6+
- src

‎e2e/bug-15231/src/Alpha.php‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Demo;
4+
5+
class Alpha
6+
{
7+
public function label(): string
8+
{
9+
return (new Zeta)->name();
10+
}
11+
}

‎e2e/bug-15231/src/Zeta.php‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Demo;
4+
5+
class Zeta
6+
{
7+
public function name(): string
8+
{
9+
return 'zeta';
10+
}
11+
12+
public function size(): int
13+
{
14+
return 1;
15+
}
16+
}

0 commit comments

Comments
 (0)