Skip to content

Commit f11b30b

Browse files
SanderMullerclaude
andauthored
Keep an optional path as written where a plain one would be (#6452)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 677df31 commit f11b30b

5 files changed

Lines changed: 64 additions & 0 deletions

File tree

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,21 @@ jobs:
847847
OUTPUT=$(../bashunit -a exit_code "0" "../../bin/phpstan analyse -vv")
848848
echo "$OUTPUT"
849849
../bashunit -a contains 'Result cache restored. 0 files will be reanalysed.' "$OUTPUT"
850+
- script: |
851+
cd e2e/result-cache-relative-path
852+
# An optional excludePath must reach the cache the way a required one does. It used to
853+
# be absolutized whatever the loader was asked to expand, so it landed in the metadata
854+
# as an absolute path and a checkout at another path discarded the whole cache.
855+
../../bin/phpstan analyse -c phpstan-optional-path.neon
856+
if grep -q "$(cd ../.. && pwd)/" tmp-optional-path/resultCache.php; then
857+
echo 'cache still holds absolute paths under the checkout:'
858+
grep -o "$(cd ../.. && pwd)/[^'\"]*" tmp-optional-path/resultCache.php | sort -u | head -20
859+
exit 1
860+
fi
861+
OUTPUT=$(../bashunit -a exit_code "0" "../../bin/phpstan analyse -c phpstan-optional-path.neon -vv")
862+
echo "$OUTPUT"
863+
../bashunit -a contains 'Result cache restored. 0 files will be reanalysed.' "$OUTPUT"
864+
850865
- script: |
851866
cd e2e/result-cache-relative-path
852867
MAIN="$(pwd)"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/tmp
2+
/tmp-optional-path
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace ResultCacheRelativePath\OptionalSrc;
4+
5+
// Reported at level 8 unless the optional excludePath keeps this directory out of the analysis,
6+
// so the scenario fails if the entry stops excluding.
7+
class ExcludedWithError
8+
{
9+
10+
public function getName(): string
11+
{
12+
return 1;
13+
}
14+
15+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# The same sources as phpstan.neon plus optional-src/, with optional excludePaths added.
2+
# `- path (?)` used to be absolutized whatever the loader was asked to expand, so it reached the
3+
# result cache metadata as an absolute path while the required entries stayed as written.
4+
#
5+
# One entry points at a directory that exists and holds an error, so the scenario fails if the
6+
# entry stops excluding. The other points at nothing, which is what `(?)` is for.
7+
#
8+
# Its own tmpDir: two configs sharing one would write the same %tmpDir%/resultCache.php and discard
9+
# each other's cache, which is https://github.com/phpstan/phpstan/issues/15232 and not what this
10+
# scenario is about.
11+
parameters:
12+
level: 8
13+
tmpDir: tmp-optional-path
14+
paths:
15+
- src
16+
- optional-src
17+
excludePaths:
18+
analyse:
19+
- optional-src (?)
20+
- src/NotThere (?)
21+
ignoreErrors:
22+
-
23+
identifier: booleanNot.alwaysFalse
24+
path: src/TraitWithConstantCondition.php

‎src/DependencyInjection/NeonAdapter.php‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,15 @@ private function createOptionalPath(string $keyToResolve, Entity $entity, string
161161
return null;
162162
}
163163

164+
// Expanded and absolutized only where a plain path entry under the same key would be. A
165+
// loader given a narrower list - CommandHelper reads the project config for the result cache
166+
// metadata with only paths and tmpDir in it - keeps the value exactly as written, so the
167+
// optional entry and the required one beside it are stored the same way and a move of the
168+
// anchor directory leaves both alone.
169+
if (!in_array($keyToResolve, $this->expandRelativePaths, true)) {
170+
return new OptionalPath($entity->value);
171+
}
172+
164173
$path = $this->expandKnownParameters($entity->value);
165174
if ($path === null) {
166175
return null;

0 commit comments

Comments
 (0)