Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4716b6d

Browse files
committed
Fix inconsistent analysis on case-insensitive filesystems
Update e2e-tests.yml Update e2e-tests.yml Update e2e-tests.yml Update e2e-tests.yml Update e2e-tests.yml Update e2e-tests.yml Update e2e-tests.yml fix PathRoutingParser extract and re-use AnalysedFilesResolver use AnalysedFilesResolver more use AnalysedFilesResolver more simplify test also on windows added failling ubuntu test added feature detect simplify detect more assertions simplify Update AnalysedFilesResolver.php
1 parent e33a560 commit 4716b6d

File tree

18 files changed

+185
-53
lines changed

18 files changed

+185
-53
lines changed

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

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ jobs:
301301

302302
e2e-tests:
303303
name: "E2E tests"
304-
runs-on: "ubuntu-latest"
304+
runs-on: ${{ matrix.os }}
305305
timeout-minutes: 60
306306

307307
strategy:
@@ -310,84 +310,127 @@ jobs:
310310
- script: "bin/phpstan analyse -l 8 -a tests/e2e/data/timecop.php -c tests/e2e/data/empty.neon tests/e2e/data/timecop.php"
311311
tools: "pecl"
312312
extensions: "timecop-beta"
313+
os: "ubuntu-latest"
313314
- script: "bin/phpstan analyse -l 8 -a tests/e2e/data/soap.php -c tests/e2e/data/empty.neon tests/e2e/data/soap.php"
314315
extensions: "soap"
316+
os: "ubuntu-latest"
315317
- script: "bin/phpstan analyse -l 8 -a tests/e2e/data/soap.php -c tests/e2e/data/empty.neon tests/e2e/data/soap.php"
316318
extensions: ""
319+
os: "ubuntu-latest"
317320
- script: "bin/phpstan analyse -l 8 tests/e2e/anon-class/Granularity.php"
318321
extensions: ""
322+
os: "ubuntu-latest"
319323
- script: "bin/phpstan analyse -l 8 e2e/phpstan-phpunit-190/test.php -c e2e/phpstan-phpunit-190/test.neon"
320324
extensions: ""
325+
os: "ubuntu-latest"
321326
- script: "bin/phpstan analyse e2e/only-files-not-analysed-trait/src -c e2e/only-files-not-analysed-trait/ignore.neon"
322327
extensions: ""
328+
os: "ubuntu-latest"
323329
- script: "bin/phpstan analyse e2e/only-files-not-analysed-trait/src/Foo.php e2e/only-files-not-analysed-trait/src/BarTrait.php -c e2e/only-files-not-analysed-trait/no-ignore.neon"
324330
extensions: ""
331+
os: "ubuntu-latest"
325332
- script: |
326333
cd e2e/baseline-uninit-prop-trait
327334
../../bin/phpstan analyse --debug --configuration test-no-baseline.neon --generate-baseline test-baseline.neon
328335
../../bin/phpstan analyse --debug --configuration test.neon
336+
os: "ubuntu-latest"
329337
- script: |
330338
cd e2e/baseline-uninit-prop-trait
331339
../../bin/phpstan analyse --configuration test-no-baseline.neon --generate-baseline test-baseline.neon
332340
../../bin/phpstan analyse --configuration test.neon
341+
os: "ubuntu-latest"
333342
- script: |
334343
cd e2e/discussion-11362
335344
composer install
336345
../../bin/phpstan
346+
os: "ubuntu-latest"
337347
- script: |
338348
cd e2e/bug-11819
339349
../../bin/phpstan
350+
os: "ubuntu-latest"
340351
- script: |
341352
cd e2e/composer-and-phpstan-version-config
342353
composer install --ignore-platform-reqs
343354
../../bin/phpstan analyze test.php --level=0
355+
os: "ubuntu-latest"
344356
- script: |
345357
cd e2e/composer-max-version
346358
composer install
347359
../../bin/phpstan analyze test.php --level=0
360+
os: "ubuntu-latest"
348361
- script: |
349362
cd e2e/composer-min-max-version
350363
composer install
351364
../../bin/phpstan analyze test.php --level=0
365+
os: "ubuntu-latest"
352366
- script: |
353367
cd e2e/composer-min-open-end-version
354368
composer install
355369
../../bin/phpstan analyze test.php --level=0
370+
os: "ubuntu-latest"
356371
- script: |
357372
cd e2e/composer-min-version-v5
358373
composer install --ignore-platform-reqs
359374
../../bin/phpstan analyze test.php --level=0
375+
os: "ubuntu-latest"
360376
- script: |
361377
cd e2e/composer-min-version-v7
362378
composer install --ignore-platform-reqs
363379
../../bin/phpstan analyze test.php --level=0
380+
os: "ubuntu-latest"
364381
- script: |
365382
cd e2e/composer-min-version
366383
composer install
367384
../../bin/phpstan analyze test.php --level=0
385+
os: "ubuntu-latest"
368386
- script: |
369387
cd e2e/composer-no-versions
370388
composer install
371389
../../bin/phpstan analyze test.php --level=0
390+
os: "ubuntu-latest"
372391
- script: |
373392
cd e2e/composer-version-config-invalid
374393
OUTPUT=$(../bashunit -a exit_code "1" ../../bin/phpstan)
375394
echo "$OUTPUT"
376395
../bashunit -a contains 'Invalid configuration' "$OUTPUT"
377396
../bashunit -a contains 'Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.' "$OUTPUT"
397+
os: "ubuntu-latest"
378398
- script: |
379399
cd e2e/composer-version-config-patch
380400
composer install --ignore-platform-reqs
381401
../../bin/phpstan analyze test.php --level=0
402+
os: "ubuntu-latest"
382403
- script: |
383404
cd e2e/composer-version-config
384405
composer install
385406
../../bin/phpstan analyze test.php --level=0
407+
os: "ubuntu-latest"
408+
- script: |
409+
cd e2e/bug-12972
410+
OUTPUT=$(../bashunit -a exit_code "1" ../../bin/phpstan)
411+
echo "$OUTPUT"
412+
../bashunit -a contains 'Internal error: Failed opening required' "$OUTPUT"
413+
../bashunit -a contains 'e2e/bug-12972/src/OTHER/file.php' "$OUTPUT"
414+
os: "ubuntu-latest"
415+
- script: |
416+
cd e2e/bug-12972
417+
../../bin/phpstan analyze
418+
os: "macos-latest"
419+
- script: |
420+
cd e2e/bug-12972
421+
../../bin/phpstan analyze
422+
os: "windows-latest"
386423
387424
steps:
388425
- name: "Checkout"
389426
uses: actions/checkout@v4
390427

428+
- name: "Install GNU Patch on macOS" # see https://github.com/cweagans/composer-patches/issues/326
429+
if: runner.os == 'macOS'
430+
run: |
431+
brew install gpatch
432+
echo "/opt/homebrew/opt/gpatch/libexec/gnubin" >> $GITHUB_PATH
433+
391434
- name: "Install PHP"
392435
uses: "shivammathur/setup-php@v2"
393436
with:

‎e2e/bug-12972/autoloader.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
spl_autoload_register(function($class) {
4+
if ($class === \other12972\MyClass::class) {
5+
require_once __DIR__ . '/src/OTHER/file.php'; // wrong case sensitivity on purpose
6+
}
7+
});

‎e2e/bug-12972/phpstan.dist.neon‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
parameters:
2+
level: 9
3+
4+
paths:
5+
- src
6+
7+
bootstrapFiles:
8+
- autoloader.php

‎e2e/bug-12972/src/folder/file2.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Foo12972;
4+
5+
use other12972\MyClass;
6+
7+
function doBar(MyClass $myClass):void {}

‎e2e/bug-12972/src/other/file.php‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace other12972;
4+
5+
class MyClass {
6+
public function doSomething(): int
7+
{
8+
return 1;
9+
}
10+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
use PHPStan\File\FilesystemHelper;
6+
use function array_fill_keys;
7+
use function array_map;
8+
use function strtolower;
9+
10+
final class AnalysedFilesResolver
11+
{
12+
13+
/** @var bool[] filePath(string) => bool(true) */
14+
private array $analysedFiles;
15+
16+
/**
17+
* @param string[] $files
18+
*/
19+
public function __construct(array $files = [])
20+
{
21+
$this->setAnalysedFiles($files);
22+
}
23+
24+
/**
25+
* @param string[] $files
26+
*/
27+
public function setAnalysedFiles(array $files): void
28+
{
29+
if (FilesystemHelper::isCaseSensitive() === false) {
30+
$files = array_map(static fn (string $file): string => strtolower($file), $files);
31+
}
32+
$this->analysedFiles = array_fill_keys($files, true);
33+
}
34+
35+
public function isInAnalyzedFiles(string $file): bool
36+
{
37+
if (FilesystemHelper::isCaseSensitive() === false) {
38+
$file = strtolower($file);
39+
}
40+
41+
return isset($this->analysedFiles[$file]);
42+
}
43+
44+
}

‎src/Analyser/Analyser.php‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PHPStan\Collectors\Registry as CollectorRegistry;
88
use PHPStan\Rules\Registry as RuleRegistry;
99
use Throwable;
10-
use function array_fill_keys;
1110
use function array_merge;
1211
use function count;
1312
use function memory_get_peak_usage;
@@ -47,7 +46,7 @@ public function analyse(
4746
}
4847

4948
$this->nodeScopeResolver->setAnalysedFiles($allAnalysedFiles);
50-
$allAnalysedFiles = array_fill_keys($allAnalysedFiles, true);
49+
$analyzedFilesResolver = newAnalysedFilesResolver($allAnalysedFiles);
5150

5251
/** @var list<Error> $errors */
5352
$errors = [];
@@ -77,7 +76,7 @@ public function analyse(
7776
try {
7877
$fileAnalyserResult = $this->fileAnalyser->analyseFile(
7978
$file,
80-
$allAnalysedFiles,
79+
$analyzedFilesResolver,
8180
$this->ruleRegistry,
8281
$this->collectorRegistry,
8382
null,

‎src/Analyser/FileAnalyser.php‎

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,11 @@ public function __construct(
6262
}
6363

6464
/**
65-
* @param array<string, true> $analysedFiles
6665
* @param callable(Node $node, Scope $scope): void|null $outerNodeCallback
6766
*/
6867
public function analyseFile(
6968
string $file,
70-
array$analysedFiles,
69+
AnalysedFilesResolver$analysedFilesResolver,
7170
RuleRegistry $ruleRegistry,
7271
CollectorRegistry $collectorRegistry,
7372
?callable $outerNodeCallback,
@@ -86,13 +85,14 @@ public function analyseFile(
8685
$exportedNodes = [];
8786
$linesToIgnore = [];
8887
$unmatchedLineIgnores = [];
88+
8989
if (is_file($file)) {
9090
try {
91-
$this->collectErrors($analysedFiles);
91+
$this->collectErrors($analysedFilesResolver);
9292
$parserNodes = $this->parser->parseFile($file);
9393
$linesToIgnore = $unmatchedLineIgnores = [$file => $this->getLinesToIgnoreFromTokens($parserNodes)];
9494
$temporaryFileErrors = [];
95-
$nodeCallback = function (Node $node, Scope $scope) use (&$fileErrors, &$fileCollectedData, &$fileDependencies, &$exportedNodes, $file, $ruleRegistry, $collectorRegistry, $outerNodeCallback, $analysedFiles, &$linesToIgnore, &$unmatchedLineIgnores, &$temporaryFileErrors): void {
95+
$nodeCallback = function (Node $node, Scope $scope) use (&$fileErrors, &$fileCollectedData, &$fileDependencies, &$exportedNodes, $file, $ruleRegistry, $collectorRegistry, $outerNodeCallback, $analysedFilesResolver, &$linesToIgnore, &$unmatchedLineIgnores, &$temporaryFileErrors): void {
9696
if ($node instanceof Node\Stmt\Trait_) {
9797
foreach (array_keys($linesToIgnore[$file] ?? []) as $lineToIgnore) {
9898
if ($lineToIgnore < $node->getStartLine() || $lineToIgnore > $node->getEndLine()) {
@@ -203,7 +203,7 @@ public function analyseFile(
203203

204204
try {
205205
$dependencies = $this->dependencyResolver->resolveDependencies($node, $scope);
206-
foreach ($dependencies->getFileDependencies($scope->getFile(), $analysedFiles) as $dependentFile) {
206+
foreach ($dependencies->getFileDependencies($scope->getFile(), $analysedFilesResolver) as $dependentFile) {
207207
$fileDependencies[] = $dependentFile;
208208
}
209209
if ($dependencies->getExportedNode() !== null) {
@@ -318,14 +318,11 @@ private function getLinesToIgnoreFromTokens(array $nodes): array
318318
return $nodes[0]->getAttribute('linesToIgnore', []);
319319
}
320320

321-
/**
322-
* @param array<string, true> $analysedFiles
323-
*/
324-
private function collectErrors(array $analysedFiles): void
321+
private function collectErrors(AnalysedFilesResolver $analyzedFilesResolver): void
325322
{
326323
$this->filteredPhpErrors = [];
327324
$this->allPhpErrors = [];
328-
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) use ($analysedFiles): bool {
325+
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) use ($analyzedFilesResolver): bool {
329326
if ((error_reporting() & $errno) === 0) {
330327
// silence @ operator
331328
return true;
@@ -339,7 +336,7 @@ private function collectErrors(array $analysedFiles): void
339336
return true;
340337
}
341338

342-
if (!isset($analysedFiles[$errfile])) {
339+
if (!$analyzedFilesResolver->isInAnalyzedFiles($errfile)) {
343340
return true;
344341
}
345342

‎src/Analyser/Ignore/IgnoredErrorHelperResult.php‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
namespace PHPStan\Analyser\Ignore;
44

5+
use PHPStan\Analyser\AnalysedFilesResolver;
56
use PHPStan\Analyser\Error;
67
use PHPStan\File\FileHelper;
78
use PHPStan\ShouldNotHappenException;
8-
use function array_fill_keys;
9-
use function array_key_exists;
109
use function array_values;
1110
use function count;
1211
use function is_array;
@@ -43,12 +42,11 @@ public function getErrors(): array
4342

4443
/**
4544
* @param Error[] $errors
46-
* @param string[] $analysedFiles
4745
*/
4846
public function process(
4947
array $errors,
5048
bool $onlyFiles,
51-
array$analysedFiles,
49+
AnalysedFilesResolver$analysedFilesResolver,
5250
bool $hasInternalErrors,
5351
): IgnoredErrorHelperProcessedResult
5452
{
@@ -190,8 +188,6 @@ public function process(
190188
), $unmatchedIgnoredError['file'], $unmatchedIgnoredError['line'], false))->withIdentifier('ignore.count');
191189
}
192190

193-
$analysedFilesKeys = array_fill_keys($analysedFiles, true);
194-
195191
if (!$hasInternalErrors) {
196192
foreach ($unmatchedIgnoredErrors as $unmatchedIgnoredError) {
197193
$reportUnmatched = $unmatchedIgnoredError['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors;
@@ -214,7 +210,8 @@ public function process(
214210
), $unmatchedIgnoredError['file'], $unmatchedIgnoredError['line'], false))->withIdentifier('ignore.count');
215211
}
216212
} elseif (isset($unmatchedIgnoredError['realPath'])) {
217-
if (!array_key_exists($unmatchedIgnoredError['realPath'], $analysedFilesKeys)) {
213+
214+
if (!$analysedFilesResolver->isInAnalyzedFiles($unmatchedIgnoredError['realPath'])) {
218215
continue;
219216
}
220217

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /