Skip to content

Commit 050971c

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 184d34e commit 050971c

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
@@ -317,6 +317,43 @@ jobs:
317317
../bashunit -a contains 'Scanned files with changed symbols (1); re-analysing the files affected by them.' "$OUTPUT"
318318
../bashunit -a contains 'Result cache restored. 1 file will be reanalysed.' "$OUTPUT"
319319
../bashunit -a contains 'Instantiated class ResultCacheE2EGenerated\Foo not found.' "$OUTPUT"
320+
- script: |
321+
cd e2e/result-cache-stub-edit
322+
# A project stub file is a dependency of the files using the symbols it declares, so editing
323+
# a PHPDoc in it re-analyses just those files. The expected lines come from a cold run.
324+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
325+
echo "$OUTPUT"
326+
../bashunit -a contains 'UseFoo::run() should return string but returns int.' "$OUTPUT"
327+
patch -p0 < phpdoc-change.patch
328+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
329+
echo "$OUTPUT"
330+
../bashunit -a not_contains 'Result cache not used' "$OUTPUT"
331+
../bashunit -a contains 'UseChild::run() should return int but returns string.' "$OUTPUT"
332+
../bashunit -a not_contains 'UseFoo::run()' "$OUTPUT"
333+
# A comment outside the PHPDocs changes nothing the analysed files see.
334+
patch -p0 < comment-change.patch
335+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
336+
echo "$OUTPUT"
337+
../bashunit -a contains 'Result cache restored. 0 files will be reanalysed.' "$OUTPUT"
338+
# The stub files are validated again, as in a full analysis.
339+
patch -p0 < invalid-phpdoc.patch
340+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
341+
echo "$OUTPUT"
342+
../bashunit -a not_contains 'Result cache not used' "$OUTPUT"
343+
../bashunit -a contains 'Foo::get() has invalid return type ResultCacheE2EStubEdit\NotAClass.' "$OUTPUT"
344+
../bashunit -a contains 'UseFoo::run() should return string but returns ResultCacheE2EStubEdit\NotAClass.' "$OUTPUT"
345+
patch -p0 -R < invalid-phpdoc.patch
346+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
347+
echo "$OUTPUT"
348+
../bashunit -a not_contains 'has invalid return type' "$OUTPUT"
349+
../bashunit -a contains 'UseChild::run() should return int but returns string.' "$OUTPUT"
350+
# A class the stub file did not declare before: the files using it depend only on the file
351+
# declaring it, so the whole result cache is invalidated.
352+
patch -p0 < new-symbol.patch
353+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
354+
echo "$OUTPUT"
355+
../bashunit -a contains 'declares different symbols' "$OUTPUT"
356+
../bashunit -a contains 'UseBar::run() should return string but returns int.' "$OUTPUT"
320357
- script: |
321358
cd e2e/bug-15125
322359
composer install

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ e2e/bashunit
2121
/e2e/result-cache-moved-tmpdir/tmp-a
2222
/e2e/result-cache-moved-tmpdir/tmp-b
2323
/e2e/result-cache-stale-objects/tmp
24+
/e2e/result-cache-stub-edit/tmp
2425
/e2e/result-cache-truncated/tmp
2526
/e2e/result-cache-worker-count/tmp
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)