Skip to content

Commit ac6dae9

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.1.x
2 parents ea816fc + bc6352b commit ac6dae9

File tree

3 files changed

+148
-2
lines changed

3 files changed

+148
-2
lines changed

.github/workflows/e2e-tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ jobs:
177177
178178
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -vv --error-format raw --tmp-file differentFoo.php --instead-of src/Foo.php")
179179
echo "$OUTPUT"
180-
../bashunit -a contains 'differentFoo.php:10:Method EditorModeE2E\Foo::doFoo() should return float but returns string. [identifier=return.type]' "$OUTPUT"
180+
../bashunit -a contains 'Foo.php:10:Method EditorModeE2E\Foo::doFoo() should return float but returns string. [identifier=return.type]' "$OUTPUT"
181181
../bashunit -a not_contains 'Foo.php:10:Method EditorModeE2E\Foo::doFoo() should return int but returns string. [identifier=return.type]' "$OUTPUT"
182+
../bashunit -a not_contains 'differentFoo.php' "$OUTPUT"
182183
../bashunit -a contains 'Bar.php:10:Parameter #1 $s of method EditorModeE2E\Bar::requireString() expects string, float given. [identifier=argument.type]' "$OUTPUT"
183184
../bashunit -a contains 'Result cache restored. 2 files will be reanalysed.' "$OUTPUT"
184185
../bashunit -a contains 'Result cache was not saved because of --tmp-file and --instead-of CLI options passed (editor mode).' "$OUTPUT"

src/Command/AnalyseApplication.php

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use PHPStan\Analyser\AnalyserResult;
66
use PHPStan\Analyser\AnalyserResultFinalizer;
7+
use PHPStan\Analyser\Error;
8+
use PHPStan\Analyser\FileAnalyserResult;
79
use PHPStan\Analyser\Ignore\IgnoredErrorHelper;
810
use PHPStan\Analyser\ResultCache\ResultCacheManagerFactory;
911
use PHPStan\Collectors\CollectedData;
@@ -22,6 +24,7 @@
2224

2325
/**
2426
* @phpstan-import-type CollectorData from CollectedData
27+
* @phpstan-import-type LinesToIgnore from FileAnalyserResult
2528
*/
2629
final class AnalyseApplication
2730
{
@@ -115,7 +118,11 @@ public function analyse(
115118
}
116119

117120
$resultCacheResult = $resultCacheManager->process($intermediateAnalyserResult, $resultCache, $errorOutput, $onlyFiles, true);
118-
$analyserResult = $this->analyserResultFinalizer->finalize($resultCacheResult->getAnalyserResult(), $onlyFiles, $debug)->getAnalyserResult();
121+
$analyserResult = $this->analyserResultFinalizer->finalize(
122+
$this->switchTmpFileInAnalyserResult($resultCacheResult->getAnalyserResult(), $insteadOfFile, $tmpFile),
123+
$onlyFiles,
124+
$debug,
125+
)->getAnalyserResult();
119126
$internalErrors = $analyserResult->getInternalErrors();
120127
$errors = array_merge(
121128
$analyserResult->getErrors(),
@@ -252,4 +259,135 @@ private function runAnalyser(
252259
return $analyserResult;
253260
}
254261

262+
private function switchTmpFileInAnalyserResult(
263+
AnalyserResult $analyserResult,
264+
?string $insteadOfFile,
265+
?string $tmpFile,
266+
): AnalyserResult
267+
{
268+
if ($insteadOfFile === null || $tmpFile === null) {
269+
return $analyserResult;
270+
}
271+
272+
$newCollectedData = [];
273+
foreach ($analyserResult->getCollectedData() as $file => $data) {
274+
if ($file === $tmpFile) {
275+
$file = $insteadOfFile;
276+
}
277+
278+
$newCollectedData[$file] = $data;
279+
}
280+
281+
$dependencies = null;
282+
if ($analyserResult->getDependencies() !== null) {
283+
$dependencies = $this->switchTmpFileInDependencies($analyserResult->getDependencies(), $insteadOfFile, $tmpFile);
284+
}
285+
$usedTraitDependencies = null;
286+
if ($analyserResult->getUsedTraitDependencies() !== null) {
287+
$usedTraitDependencies = $this->switchTmpFileInDependencies($analyserResult->getUsedTraitDependencies(), $insteadOfFile, $tmpFile);
288+
}
289+
290+
$exportedNodes = [];
291+
foreach ($analyserResult->getExportedNodes() as $file => $fileExportedNodes) {
292+
if ($file === $tmpFile) {
293+
$file = $insteadOfFile;
294+
}
295+
296+
$exportedNodes[$file] = $fileExportedNodes;
297+
}
298+
299+
return new AnalyserResult(
300+
$this->switchTmpFileInErrors($analyserResult->getUnorderedErrors(), $insteadOfFile, $tmpFile),
301+
$this->switchTmpFileInErrors($analyserResult->getFilteredPhpErrors(), $insteadOfFile, $tmpFile),
302+
$this->switchTmpFileInErrors($analyserResult->getAllPhpErrors(), $insteadOfFile, $tmpFile),
303+
$this->switchTmpFileInErrors($analyserResult->getLocallyIgnoredErrors(), $insteadOfFile, $tmpFile),
304+
$this->swittchTmpFileInLinesToIgnore($analyserResult->getLinesToIgnore(), $insteadOfFile, $tmpFile),
305+
$this->swittchTmpFileInLinesToIgnore($analyserResult->getUnmatchedLineIgnores(), $insteadOfFile, $tmpFile),
306+
$analyserResult->getInternalErrors(),
307+
$newCollectedData,
308+
$dependencies,
309+
$usedTraitDependencies,
310+
$exportedNodes,
311+
$analyserResult->hasReachedInternalErrorsCountLimit(),
312+
$analyserResult->getPeakMemoryUsageBytes(),
313+
);
314+
}
315+
316+
/**
317+
* @param array<string, array<string>> $dependencies
318+
* @return array<string, array<string>>
319+
*/
320+
private function switchTmpFileInDependencies(array $dependencies, string $insteadOfFile, string $tmpFile): array
321+
{
322+
$newDependencies = [];
323+
foreach ($dependencies as $dependencyFile => $dependentFiles) {
324+
$new = [];
325+
foreach ($dependentFiles as $file) {
326+
if ($file === $tmpFile) {
327+
$new[] = $insteadOfFile;
328+
continue;
329+
}
330+
331+
$new[] = $file;
332+
}
333+
334+
$key = $dependencyFile;
335+
if ($key === $tmpFile) {
336+
$key = $insteadOfFile;
337+
}
338+
339+
$newDependencies[$key] = $new;
340+
}
341+
342+
return $newDependencies;
343+
}
344+
345+
/**
346+
* @param list<Error> $errors
347+
* @return list<Error>
348+
*/
349+
private function switchTmpFileInErrors(array $errors, string $insteadOfFile, string $tmpFile): array
350+
{
351+
$newErrors = [];
352+
foreach ($errors as $error) {
353+
if ($error->getFilePath() === $tmpFile) {
354+
$error = $error->changeFilePath($insteadOfFile);
355+
}
356+
if ($error->getTraitFilePath() === $tmpFile) {
357+
$error = $error->changeTraitFilePath($insteadOfFile);
358+
}
359+
360+
$newErrors[] = $error;
361+
}
362+
363+
return $newErrors;
364+
}
365+
366+
/**
367+
* @param array<string, LinesToIgnore> $linesToIgnore
368+
* @return array<string, LinesToIgnore>
369+
*/
370+
private function swittchTmpFileInLinesToIgnore(array $linesToIgnore, string $insteadOfFile, string $tmpFile): array
371+
{
372+
$newLinesToIgnore = [];
373+
foreach ($linesToIgnore as $file => $lines) {
374+
if ($file === $tmpFile) {
375+
$file = $insteadOfFile;
376+
}
377+
378+
$newLines = [];
379+
foreach ($lines as $f => $line) {
380+
if ($f === $tmpFile) {
381+
$f = $insteadOfFile;
382+
}
383+
384+
$newLines[$f] = $line;
385+
}
386+
387+
$newLinesToIgnore[$file] = $newLines;
388+
}
389+
390+
return $newLinesToIgnore;
391+
}
392+
255393
}

src/Command/AnalyseCommand.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
269269
}
270270
}
271271

272+
if ($inceptionResult->getEditorModeTmpFile() !== null) {
273+
if (in_array($inceptionResult->getEditorModeTmpFile(), $files, true)) {
274+
$inceptionResult->getStdOutput()->getStyle()->error(sprintf('File %s passed to --tmp-file is already in analysed project files.', $inceptionResult->getEditorModeInsteadOfFile()));
275+
return $inceptionResult->handleReturn(1, null, $this->analysisStartTime);
276+
}
277+
}
278+
272279
$analysedConfigFiles = array_intersect($files, $container->getParameter('allConfigFiles'));
273280
/** @var RelativePathHelper $relativePathHelper */
274281
$relativePathHelper = $container->getService('relativePathHelper');

0 commit comments

Comments
 (0)