🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Store PhpStorm stub paths in the reflection cache relative to the stubs root - #6179

Merged
ondrejmirtes merged 2 commits into
2.2.xfrom
e2e-moved-phpstan-installation
Aug 4, 2026
Merged

Store PhpStorm stub paths in the reflection cache relative to the stubs root#6179
ondrejmirtes merged 2 commits into
2.2.xfrom
e2e-moved-phpstan-installation

Conversation

@ondrejmirtes

@ondrejmirtes ondrejmirtes commented Aug 4, 2026

Copy link
Copy Markdown
Member

Fixes the regression introduced in ae5fd31 (Cache reflections built from the PhpStorm stubs).

The mechanism:

  • CachedPhpInternalSourceLocator keys the cache only by package versions (better-reflection, phpstorm-stubs, target PHP version) — no paths — so the entries are shared by every installation with the same versions, and survive the installation being moved.
  • The cached exportToCache() blob however stored the absolute path of the stub file inside the installation that filled the cache (.../vendor/jetbrains/phpstorm-stubs/...; in the phar case the path embeds the phar's absolute location).
  • InternalLocatedSource::importFromCache() eagerly runs FileChecker::assertReadableFile() + file_get_contents() on that path, so a warm run from a moved installation — or a different installation sharing sys_get_temp_dir() . '/phpstan', like rotating Jenkins workspaces — crashed with Internal error: "..." is not a file. The entries also survive clear-result-cache, so there was no way to recover.

The first commit adds an e2e test: copy the checkout to /tmp/phpstan-install-1, analyse a small file using built-in symbols (fills the cache), move the installation to /tmp/phpstan-install-2, run the same analysis again. It failed with the internal error above before the fix.

The second commit fixes it: the stub path is stored relative to the phpstorm-stubs package root (phpstorm-stubs:date/date_c.php) and resolved against the current installation on import, so the entries stay shared across installations and moves. An is_file() guard turns any unresolvable path into a plain cache miss, making this class of crash impossible by construction. The variable-key version bump (v1v2) invalidates existing poisoned entries with absolute paths, rescuing already-affected caches.

Verified locally besides the e2e: a warm in-place run rewrites 0 cache files (the relative entries really are imported), and a second installation at a different path shares the same warm entries. Keeping the cache (rather than reverting it) is backed by benchmarks: it saves ~1.5–3% CPU on runs with a cold result cache (ABBA pairs, paired t-test).

Closes phpstan/phpstan#15023

🤖 Generated with Claude Code

@ondrejmirtes ondrejmirtes changed the title Add e2e test moving the PHPStan installation between runs Store PhpStorm stub paths in the reflection cache relative to the stubs root Aug 4, 2026
ondrejmirtes and others added 2 commits August 4, 2026 23:16
The first run fills the reflection cache for PHP built-in symbols in
sys_get_temp_dir(); the installation is then moved and PHPStan runs
again with the same cache. The cached blobs store absolute paths to the
PhpStorm stub files while the cache key contains only package versions,
so the second run currently crashes with:

    Internal error: ".../phpstorm-stubs/date/date_c.php" is not a file

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bs root

The cache key for PHP built-in reflections deliberately contains no
paths, so the entries are shared by every PHPStan installation with the
same package versions - but the exported blob recorded the absolute
stub file path of the installation that filled the cache. Importing it
after that installation was moved or deleted crashed with "... is not a
file", and the entries survive clear-result-cache, so there was no way
to recover.

The stub path is now stored relative to the phpstorm-stubs package root
and resolved against the current installation on import, with an
is_file() guard that turns any unresolvable path into a plain cache
miss. The variable key version bump invalidates existing entries with
absolute paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ondrejmirtes
ondrejmirtes force-pushed the e2e-moved-phpstan-installation branch from d03d7a9 to b334e5d Compare August 4, 2026 21:17
@ondrejmirtes
ondrejmirtes merged commit b7a9288 into 2.2.x Aug 4, 2026
416 checks passed
@ondrejmirtes
ondrejmirtes deleted the e2e-moved-phpstan-installation branch August 4, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Internal error: Incorrect path for vendor files inside phpstan.phar

1 participant