From dff37cfcdf0ee1b049f533d0a306a252fb1dcc64 Mon Sep 17 00:00:00 2001 From: Sander Muller Date: Sat, 11 Jul 2026 14:05:06 +0200 Subject: [PATCH] Track define()'d constants as exported nodes Global constants declared with define() have the same result-cache staleness as `const` had: a file reading a define()'d constant records a dependency on the defining file (via the ConstFetch handling), but a define() is a function call rather than a declaration, so it produced no exported node. Changing the define()'s value therefore did not re-analyse the reading files. Export define('NAME', ) calls with a literal name, reusing ExportedConstantNode, so changing the value re-analyses the dependents. Covered by a result-cache e2e test. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/e2e-tests.yml | 7 +++++++ .../changeDefineValue.patch | 7 +++++++ e2e/result-cache-define/phpstan.neon | 5 +++++ .../src/ClassUsingDefine.php | 16 ++++++++++++++++ e2e/result-cache-define/src/define.php | 3 +++ e2e/result-cache-define/tmp/.gitignore | 2 ++ src/Dependency/ExportedNodeResolver.php | 19 +++++++++++++++++++ 7 files changed, 59 insertions(+) create mode 100644 e2e/result-cache-define/changeDefineValue.patch create mode 100644 e2e/result-cache-define/phpstan.neon create mode 100644 e2e/result-cache-define/src/ClassUsingDefine.php create mode 100644 e2e/result-cache-define/src/define.php create mode 100644 e2e/result-cache-define/tmp/.gitignore diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 06b8e514062..6a8715514db 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -372,6 +372,13 @@ jobs: OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw") echo "$OUTPUT" ../bashunit -a contains 'ClassUsingConstant.php:13:Constant SOME_MODE not found. [identifier=constant.notFound]' "$OUTPUT" + - script: | + cd e2e/result-cache-define + ../../bin/phpstan analyse + patch -b src/define.php < changeDefineValue.patch + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw") + echo "$OUTPUT" + ../bashunit -a contains 'ClassUsingDefine.php:13:Method ResultCacheE2EDefine\ClassUsingDefine::getMode() should return int<1, 3> but returns 5. [identifier=return.type]' "$OUTPUT" - script: | cd e2e/bug-12606 export CONFIGTEST=test diff --git a/e2e/result-cache-define/changeDefineValue.patch b/e2e/result-cache-define/changeDefineValue.patch new file mode 100644 index 00000000000..43836f76965 --- /dev/null +++ b/e2e/result-cache-define/changeDefineValue.patch @@ -0,0 +1,7 @@ +--- src/define.php ++++ src/define.php +@@ -1,3 +1,3 @@ + + */ + public function getMode(): int + { + return SOME_DEFINED_MODE; + } + +} diff --git a/e2e/result-cache-define/src/define.php b/e2e/result-cache-define/src/define.php new file mode 100644 index 00000000000..e5a86fdac80 --- /dev/null +++ b/e2e/result-cache-define/src/define.php @@ -0,0 +1,3 @@ +name instanceof Name + && $node->name->toLowerString() === 'define' + ) { + $args = $node->getArgs(); + if ( + isset($args[0], $args[1]) + && $args[0]->value instanceof Node\Scalar\String_ + ) { + return new ExportedConstantsNode([ + new ExportedConstantNode( + $args[0]->value->value, + $this->exprPrinter->printExpr($args[1]->value), + ), + ]); + } + } + return null; }