Skip to content

Commit 53433f8

Browse files
SanderMullerclaude
andcommitted
Re-analyse only the files using a symbol whose stub PHPDoc changed
A changed project stub file invalidated the whole result cache. Now a file that uses a class or a function declared in a project stub file records a dependency on that stub file, as it does for a scanned file. When the stub file changes, the restore compares its exported nodes, and only the files that depend on it are analysed again. When the stub file declares other symbols than before, or nothing depends on it, the whole cache is still invalidated: the files using a newly stubbed symbol have no dependency on the stub file yet. After a stub file changes, all project stub files are validated again, because stub validation otherwise runs only in a full analysis. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent c539adc commit 53433f8

19 files changed

Lines changed: 317 additions & 4 deletions

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,43 @@ jobs:
353353
../bashunit assert contains 'Scanned files with changed symbols (1); re-analysing the files affected by them.' "$OUTPUT"
354354
../bashunit assert contains 'Result cache restored. 1 file will be reanalysed.' "$OUTPUT"
355355
../bashunit assert contains 'Instantiated class ResultCacheE2EGenerated\Foo not found.' "$OUTPUT"
356+
- script: |
357+
cd e2e/result-cache-stub-edit
358+
# A project stub file is a dependency of the files using the symbols it declares, so editing
359+
# a PHPDoc in it re-analyses just those files. The expected lines come from a cold run.
360+
OUTPUT=$(../bashunit assert exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
361+
echo "$OUTPUT"
362+
../bashunit assert contains 'UseFoo::run() should return string but returns int.' "$OUTPUT"
363+
patch -p0 < phpdoc-change.patch
364+
OUTPUT=$(../bashunit assert exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
365+
echo "$OUTPUT"
366+
../bashunit assert not_contains 'Result cache not used' "$OUTPUT"
367+
../bashunit assert contains 'UseChild::run() should return int but returns string.' "$OUTPUT"
368+
../bashunit assert not_contains 'UseFoo::run()' "$OUTPUT"
369+
# A comment outside the PHPDocs changes nothing the analysed files see.
370+
patch -p0 < comment-change.patch
371+
OUTPUT=$(../bashunit assert exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
372+
echo "$OUTPUT"
373+
../bashunit assert contains 'Result cache restored. 0 files will be reanalysed.' "$OUTPUT"
374+
# The stub files are validated again, as in a full analysis.
375+
patch -p0 < invalid-phpdoc.patch
376+
OUTPUT=$(../bashunit assert exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
377+
echo "$OUTPUT"
378+
../bashunit assert not_contains 'Result cache not used' "$OUTPUT"
379+
../bashunit assert contains 'Foo::get() has invalid return type ResultCacheE2EStubEdit\NotAClass.' "$OUTPUT"
380+
../bashunit assert contains 'UseFoo::run() should return string but returns ResultCacheE2EStubEdit\NotAClass.' "$OUTPUT"
381+
patch -p0 -R < invalid-phpdoc.patch
382+
OUTPUT=$(../bashunit assert exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
383+
echo "$OUTPUT"
384+
../bashunit assert not_contains 'has invalid return type' "$OUTPUT"
385+
../bashunit assert contains 'UseChild::run() should return int but returns string.' "$OUTPUT"
386+
# A class the stub file did not declare before: the files using it depend only on the file
387+
# declaring it, so the whole result cache is invalidated.
388+
patch -p0 < new-symbol.patch
389+
OUTPUT=$(../bashunit assert exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
390+
echo "$OUTPUT"
391+
../bashunit assert contains 'declares different symbols' "$OUTPUT"
392+
../bashunit assert contains 'UseBar::run() should return string but returns int.' "$OUTPUT"
356393
- script: |
357394
cd e2e/bug-15125
358395
composer install

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ e2e/bashunit
2222
/e2e/result-cache-moved-tmpdir/tmp-a
2323
/e2e/result-cache-moved-tmpdir/tmp-b
2424
/e2e/result-cache-stale-objects/tmp
25+
/e2e/result-cache-stub-edit/tmp
2526
/e2e/result-cache-truncated/tmp
2627
/e2e/result-cache-worker-count/tmp
2728
e2e/restart-manager/probe.log
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--- stubs/Foo.stub
2+
+++ stubs/Foo.stub
3+
@@ -2,6 +2,7 @@
4+
5+
namespace ResultCacheE2EStubEdit;
6+
7+
+// Foo is generated from a template.
8+
class Foo
9+
{
10+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--- stubs/Foo.stub
2+
+++ stubs/Foo.stub
3+
@@ -6,7 +6,7 @@
4+
class Foo
5+
{
6+
7+
- /** @return string */
8+
+ /** @return NotAClass */
9+
public function get() {}
10+
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--- stubs/Foo.stub
2+
+++ stubs/Foo.stub
3+
@@ -10,3 +10,11 @@
4+
public function get() {}
5+
6+
}
7+
+
8+
+class Bar
9+
+{
10+
+
11+
+ /** @return int */
12+
+ public function get() {}
13+
+
14+
+}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--- stubs/Foo.stub
2+
+++ stubs/Foo.stub
3+
@@ -5,7 +5,7 @@
4+
class Foo
5+
{
6+
7+
- /** @return int */
8+
+ /** @return string */
9+
public function get() {}
10+
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
parameters:
2+
level: 5
3+
paths:
4+
- src
5+
stubFiles:
6+
- stubs/Foo.stub
7+
tmpDir: tmp
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace ResultCacheE2EStubEdit;
4+
5+
class Bar
6+
{
7+
8+
/** @return mixed */
9+
public function get()
10+
{
11+
return 1;
12+
}
13+
14+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace ResultCacheE2EStubEdit;
4+
5+
class Child extends Foo
6+
{
7+
8+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace ResultCacheE2EStubEdit;
4+
5+
class Foo
6+
{
7+
8+
/** @return mixed */
9+
public function get()
10+
{
11+
return 1;
12+
}
13+
14+
}

0 commit comments

Comments
 (0)