Skip to content

Commit e187945

Browse files
SanderMullerclaude
authored andcommitted
Do not export what is declared inside a function or method body
A define() or a class declared inside a function or method body is not found from other files, and ExportedNodeVisitor does not look inside function bodies. Exporting it during the analysis made every edit of its file look like a symbol disappeared, so all files with errors were re-analysed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent e840006 commit e187945

7 files changed

Lines changed: 69 additions & 4 deletions

File tree

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,19 @@ jobs:
442442
echo "$INFO"
443443
../bashunit -a equals 'true' "$(echo "$INFO" | jq --raw-output '.resultCacheUsed')"
444444
../bashunit -a equals '1' "$(echo "$INFO" | jq --raw-output '.filesToAnalyseCount')"
445+
- script: |
446+
cd e2e/result-cache-define-in-function
447+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
448+
echo "$OUTPUT"
449+
../bashunit -a contains 'Other.php:10:Method ResultCacheE2EDefineInFunction\Other::doOther() should return int but returns string.' "$OUTPUT"
450+
# A define() inside a function or method body is not an exported node, so an edit of the
451+
# file calling it looks like no symbol appeared or disappeared: only the file itself is
452+
# re-analysed, not every file with errors.
453+
patch -b src/functions.php < body.patch
454+
INFO=$(../../bin/phpstan result-cache-info --json)
455+
echo "$INFO"
456+
../bashunit -a equals 'true' "$(echo "$INFO" | jq --raw-output '.resultCacheUsed')"
457+
../bashunit -a equals '1' "$(echo "$INFO" | jq --raw-output '.filesToAnalyseCount')"
445458
- script: |
446459
cd e2e/result-cache-function-shares-method-name
447460
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw")
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--- src/functions.php
2+
+++ src/functions.php
3+
@@ -6,7 +6,7 @@
4+
{
5+
define('RESULT_CACHE_E2E_IN_FUNCTION', 1);
6+
7+
- return 1;
8+
+ return 2;
9+
}
10+
11+
class Bootstrap
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
level: 8
3+
tmpDir: tmp
4+
paths:
5+
- src
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace ResultCacheE2EDefineInFunction;
4+
5+
class Other
6+
{
7+
8+
public function doOther(): int
9+
{
10+
return 'foo';
11+
}
12+
13+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace ResultCacheE2EDefineInFunction;
4+
5+
function setUp(): int
6+
{
7+
define('RESULT_CACHE_E2E_IN_FUNCTION', 1);
8+
9+
return 1;
10+
}
11+
12+
class Bootstrap
13+
{
14+
15+
public function boot(): void
16+
{
17+
define('RESULT_CACHE_E2E_IN_METHOD', 1);
18+
}
19+
20+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.*

‎src/Dependency/DependencyResolver.php‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,11 @@ public function resolveExportedNode(Node $node, Scope $scope): ?RootExportedNode
9696
$this->nameScopeTracker->enterNode($node);
9797
}
9898

99-
// A function declared inside another function is not supported (function.inner), and the
100-
// restore does not look inside function bodies for exported nodes (ExportedNodeVisitor):
101-
// exporting it here would make every edit of its file look like a symbol disappeared.
102-
if (($nodeProfile & self::PROFILE_EXPORT) === 0 || ($node instanceof Node\Stmt\Function_ && $scope->getFunction() !== null)) {
99+
// Nothing declared inside a function or method body is a symbol other files can use: a function
100+
// declared there is not supported (function.inner), and a class or a define() there is not found.
101+
// The restore does not look inside function bodies for exported nodes (ExportedNodeVisitor), so
102+
// exporting one here would make every edit of its file look like a symbol disappeared.
103+
if (($nodeProfile & self::PROFILE_EXPORT) === 0 || $scope->getFunction() !== null) {
103104
return null;
104105
}
105106

0 commit comments

Comments
 (0)