From 255691850a054a52f0a2c20e6ab4c0bc5e59dfdb Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Tue, 3 Jan 2023 14:23:36 +0100 Subject: [PATCH] Show combined memory usage in parallel mode --- src/Analyser/Analyser.php | 2 ++ src/Analyser/AnalyserResult.php | 6 ++++ .../ResultCache/ResultCacheManager.php | 1 + src/Command/AnalyseApplication.php | 7 ++++- src/Command/AnalyseCommand.php | 30 ++++++++++--------- src/Command/AnalyserRunner.php | 3 +- src/Command/AnalysisResult.php | 6 ++++ .../ErrorFormatter/TableErrorFormatter.php | 1 + src/Command/ErrorsConsoleStyle.php | 30 +++++++++++++++++++ src/Command/FixerApplication.php | 3 +- src/Command/FixerWorkerCommand.php | 1 + src/Command/InceptionResult.php | 7 ++--- src/Command/WorkerCommand.php | 2 ++ src/Parallel/ParallelAnalyser.php | 18 +++++++++-- src/Testing/ErrorFormatterTestCase.php | 1 + tests/PHPStan/Command/AnalysisResultTest.php | 1 + .../BaselineNeonErrorFormatterTest.php | 4 +++ .../CheckstyleErrorFormatterTest.php | 1 + .../TableErrorFormatterTest.php | 7 +++-- 19 files changed, 105 insertions(+), 26 deletions(-) diff --git a/src/Analyser/Analyser.php b/src/Analyser/Analyser.php index 8858407c2d..8aaa6aa588 100644 --- a/src/Analyser/Analyser.php +++ b/src/Analyser/Analyser.php @@ -10,6 +10,7 @@ use function array_fill_keys; use function array_merge; use function count; +use function memory_get_peak_usage; use function sprintf; class Analyser @@ -110,6 +111,7 @@ public function analyse( $internalErrorsCount === 0 ? $dependencies : null, $exportedNodes, $reachedInternalErrorsCountLimit, + memory_get_peak_usage(true), ); } diff --git a/src/Analyser/AnalyserResult.php b/src/Analyser/AnalyserResult.php index 41c0e574fc..692fcdf4ce 100644 --- a/src/Analyser/AnalyserResult.php +++ b/src/Analyser/AnalyserResult.php @@ -26,6 +26,7 @@ public function __construct( private ?array $dependencies, private array $exportedNodes, private bool $reachedInternalErrorsCountLimit, + private int $peakMemoryUsageBytes, ) { $this->unorderedErrors = $errors; @@ -97,4 +98,9 @@ public function hasReachedInternalErrorsCountLimit(): bool return $this->reachedInternalErrorsCountLimit; } + public function getPeakMemoryUsageBytes(): int + { + return $this->peakMemoryUsageBytes; + } + } diff --git a/src/Analyser/ResultCache/ResultCacheManager.php b/src/Analyser/ResultCache/ResultCacheManager.php index c3220c7449..15e8484c09 100644 --- a/src/Analyser/ResultCache/ResultCacheManager.php +++ b/src/Analyser/ResultCache/ResultCacheManager.php @@ -424,6 +424,7 @@ public function process(AnalyserResult $analyserResult, ResultCache $resultCache $dependencies, $exportedNodes, $analyserResult->hasReachedInternalErrorsCountLimit(), + $analyserResult->getPeakMemoryUsageBytes(), ), $saved); } diff --git a/src/Command/AnalyseApplication.php b/src/Command/AnalyseApplication.php index 01a7ca4793..f2d81ac6c3 100644 --- a/src/Command/AnalyseApplication.php +++ b/src/Command/AnalyseApplication.php @@ -71,6 +71,7 @@ public function analyse( $internalErrors = []; $collectedData = []; $savedResultCache = false; + $memoryUsageBytes = memory_get_peak_usage(true); if ($errorOutput->isDebug()) { $errorOutput->writeLineFormatted('Result cache was not saved because of ignoredErrorHelperResult errors.'); } @@ -97,6 +98,7 @@ public function analyse( $intermediateAnalyserResult->getDependencies(), $intermediateAnalyserResult->getExportedNodes(), $intermediateAnalyserResult->hasReachedInternalErrorsCountLimit(), + $intermediateAnalyserResult->getPeakMemoryUsageBytes(), ); } @@ -105,6 +107,8 @@ public function analyse( $internalErrors = $analyserResult->getInternalErrors(); $errors = $analyserResult->getErrors(); $hasInternalErrors = count($internalErrors) > 0 || $analyserResult->hasReachedInternalErrorsCountLimit(); + $memoryUsageBytes = $analyserResult->getPeakMemoryUsageBytes(); + if (!$hasInternalErrors) { foreach ($this->getCollectedDataErrors($analyserResult->getCollectedData()) as $error) { $errors[] = $error; @@ -139,6 +143,7 @@ public function analyse( $defaultLevelUsed, $projectConfigFile, $savedResultCache, + $memoryUsageBytes, ); } @@ -195,7 +200,7 @@ private function runAnalyser( $errorOutput->getStyle()->progressStart($allAnalysedFilesCount); $errorOutput->getStyle()->progressAdvance($allAnalysedFilesCount); $errorOutput->getStyle()->progressFinish(); - return new AnalyserResult([], [], [], [], [], false); + return new AnalyserResult([], [], [], [], [], false, memory_get_peak_usage(true)); } if (!$debug) { diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index ce142af9e0..e3c3fabb7d 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -157,7 +157,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($generateBaselineFile === null && $allowEmptyBaseline) { $inceptionResult->getStdOutput()->getStyle()->error('You must pass the --generate-baseline option alongside --allow-empty-baseline.'); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, null); } $errorOutput = $inceptionResult->getErrorOutput(); @@ -200,13 +200,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int $baselineExtension = pathinfo($generateBaselineFile, PATHINFO_EXTENSION); if ($baselineExtension === '') { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename must have an extension, %s provided instead.', pathinfo($generateBaselineFile, PATHINFO_BASENAME))); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, null); } if ($baselineExtension !== 'neon') { $inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename extension must be .neon, .%s was used instead.', $baselineExtension)); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, null); } } @@ -267,7 +267,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $previous = $previous->getPrevious(); } - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, null); } throw $t; @@ -278,12 +278,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int $inceptionResult->getStdOutput()->getStyle()->error('No errors were found during the analysis. Baseline could not be generated.'); $inceptionResult->getStdOutput()->writeLineFormatted('To allow generating empty baselines, pass --allow-empty-baseline option.'); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } if ($analysisResult->hasInternalErrors()) { $inceptionResult->getStdOutput()->getStyle()->error('An internal error occurred. Baseline could not be generated. Re-run PHPStan without --generate-baseline to see what\'s going on.'); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } $baselineFileDirectory = dirname($generateBaselineFile); @@ -308,7 +308,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($mkdirResult === false) { $inceptionResult->getStdOutput()->writeLineFormatted(sprintf('Failed to create directory "%s".', $baselineFileDirectory)); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } } @@ -317,7 +317,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } catch (CouldNotWriteFileException $e) { $inceptionResult->getStdOutput()->writeLineFormatted($e->getMessage()); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } $errorsCount = 0; @@ -348,7 +348,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $inceptionResult->getStdOutput()->getStyle()->warning($message . "\nSome errors could not be put into baseline. Re-run PHPStan and fix them."); } - return $inceptionResult->handleReturn(0); + return $inceptionResult->handleReturn(0, $analysisResult->getPeakMemoryUsageBytes()); } if ($fix) { @@ -356,7 +356,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($ciDetector->isCiDetected()) { $inceptionResult->getStdOutput()->writeLineFormatted('PHPStan Pro can\'t run in CI environment yet. Stay tuned!'); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } $container->getByType(ResultCacheClearer::class)->clearTemporaryCaches(); $hasInternalErrors = $analysisResult->hasInternalErrors(); @@ -379,6 +379,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $analysisResult->isDefaultLevelUsed(), $analysisResult->getProjectConfigFile(), $analysisResult->isResultCacheSaved(), + $analysisResult->getPeakMemoryUsageBytes(), ); $stdOutput = $inceptionResult->getStdOutput(); @@ -395,7 +396,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $stdOutput->writeLineFormatted(sprintf('nonIgnorableErrorsByExceptionCount: %d', count($nonIgnorableErrorsByException))); } - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } if (!$analysisResult->isResultCacheSaved() && !$onlyFiles) { @@ -403,7 +404,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $stdOutput = $inceptionResult->getStdOutput(); if (count($analysisResult->getFileSpecificErrors()) > 0) { $stdOutput->getStyle()->error('Unknown error. Please report this as a bug.'); - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } $stdOutput->getStyle()->error('PHPStan Pro can\'t be launched because of these errors:'); @@ -418,10 +419,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $stdOutput->writeLineFormatted('Result cache was not saved.'); } - return $inceptionResult->handleReturn(1); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes()); } - $inceptionResult->handleReturn(0); + $inceptionResult->handleReturn(0, $analysisResult->getPeakMemoryUsageBytes()); /** @var FixerApplication $fixerApplication */ $fixerApplication = $container->getByType(FixerApplication::class); @@ -443,6 +444,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return $inceptionResult->handleReturn( $errorFormatter->formatErrors($analysisResult, $inceptionResult->getStdOutput()), + $analysisResult->getPeakMemoryUsageBytes(), ); } diff --git a/src/Command/AnalyserRunner.php b/src/Command/AnalyserRunner.php index 627c4f4ac5..5275c679aa 100644 --- a/src/Command/AnalyserRunner.php +++ b/src/Command/AnalyserRunner.php @@ -14,6 +14,7 @@ use function count; use function function_exists; use function is_file; +use function memory_get_peak_usage; class AnalyserRunner { @@ -48,7 +49,7 @@ public function runAnalyser( { $filesCount = count($files); if ($filesCount === 0) { - return new AnalyserResult([], [], [], [], [], false); + return new AnalyserResult([], [], [], [], [], false, memory_get_peak_usage(true)); } $schedule = $this->scheduler->scheduleWork($this->cpuCoreCounter->getNumberOfCpuCores(), $files); diff --git a/src/Command/AnalysisResult.php b/src/Command/AnalysisResult.php index 45fee4f841..9a8dae37bb 100644 --- a/src/Command/AnalysisResult.php +++ b/src/Command/AnalysisResult.php @@ -30,6 +30,7 @@ public function __construct( private bool $defaultLevelUsed, private ?string $projectConfigFile, private bool $savedResultCache, + private int $peakMemoryUsageBytes, ) { usort( @@ -123,4 +124,9 @@ public function isResultCacheSaved(): bool return $this->savedResultCache; } + public function getPeakMemoryUsageBytes(): int + { + return $this->peakMemoryUsageBytes; + } + } diff --git a/src/Command/ErrorFormatter/TableErrorFormatter.php b/src/Command/ErrorFormatter/TableErrorFormatter.php index 9512f81da3..039dfe7cca 100644 --- a/src/Command/ErrorFormatter/TableErrorFormatter.php +++ b/src/Command/ErrorFormatter/TableErrorFormatter.php @@ -46,6 +46,7 @@ public function formatErrors( if (!$analysisResult->hasErrors() && !$analysisResult->hasWarnings()) { $style->success('No errors'); + if ($this->showTipsOfTheDay) { if ($analysisResult->isDefaultLevelUsed()) { $output->writeLineFormatted('💡 Tip of the Day:'); diff --git a/src/Command/ErrorsConsoleStyle.php b/src/Command/ErrorsConsoleStyle.php index 76954e735f..98dd14cc67 100644 --- a/src/Command/ErrorsConsoleStyle.php +++ b/src/Command/ErrorsConsoleStyle.php @@ -119,6 +119,11 @@ public function createProgressBar(int $max = 0): ProgressBar { $this->progressBar = parent::createProgressBar($max); + $format = $this->getProgressBarFormat(); + if ($format !== null) { + $this->progressBar->setFormat($format); + } + $ci = $this->isCiDetected(); $this->progressBar->setOverwrite(!$ci); @@ -136,6 +141,31 @@ public function createProgressBar(int $max = 0): ProgressBar return $this->progressBar; } + private function getProgressBarFormat(): ?string + { + switch ($this->getVerbosity()) { + case OutputInterface::VERBOSITY_NORMAL: + $formatName = ProgressBar::FORMAT_NORMAL; + break; + case OutputInterface::VERBOSITY_VERBOSE: + $formatName = ProgressBar::FORMAT_VERBOSE; + break; + case OutputInterface::VERBOSITY_VERY_VERBOSE: + case OutputInterface::VERBOSITY_DEBUG: + $formatName = ProgressBar::FORMAT_VERY_VERBOSE; + break; + default: + $formatName = null; + break; + } + + if ($formatName === null) { + return null; + } + + return ProgressBar::getFormatDefinition($formatName); + } + public function progressStart(int $max = 0): void { if (!$this->showProgress) { diff --git a/src/Command/FixerApplication.php b/src/Command/FixerApplication.php index bd9d5e3b6a..d96f93d4bb 100644 --- a/src/Command/FixerApplication.php +++ b/src/Command/FixerApplication.php @@ -60,6 +60,7 @@ use function is_dir; use function is_file; use function is_string; +use function memory_get_peak_usage; use function min; use function mkdir; use function parse_url; @@ -507,7 +508,7 @@ private function reanalyseAfterFileChanges( $resultCache = $resultCacheManager->restore($inceptionFiles, false, false, $projectConfigArray, $inceptionResult->getErrorOutput(), $fixerSuggestionId); if (count($resultCache->getFilesToAnalyse()) === 0) { $result = $resultCacheManager->process( - new AnalyserResult([], [], [], [], [], false), + new AnalyserResult([], [], [], [], [], false, memory_get_peak_usage(true)), $resultCache, $inceptionResult->getErrorOutput(), false, diff --git a/src/Command/FixerWorkerCommand.php b/src/Command/FixerWorkerCommand.php index 5d6e583924..fa14b145e3 100644 --- a/src/Command/FixerWorkerCommand.php +++ b/src/Command/FixerWorkerCommand.php @@ -268,6 +268,7 @@ private function switchTmpFileInAnalyserResult( $dependencies, $exportedNodes, $analyserResult->hasReachedInternalErrorsCountLimit(), + $analyserResult->getPeakMemoryUsageBytes(), ); } diff --git a/src/Command/InceptionResult.php b/src/Command/InceptionResult.php index 8a0010c8c2..5e27b036aa 100644 --- a/src/Command/InceptionResult.php +++ b/src/Command/InceptionResult.php @@ -4,7 +4,6 @@ use PHPStan\DependencyInjection\Container; use PHPStan\Internal\BytesHelper; -use function memory_get_peak_usage; use function sprintf; class InceptionResult @@ -79,10 +78,10 @@ public function getGenerateBaselineFile(): ?string return $this->generateBaselineFile; } - public function handleReturn(int $exitCode): int + public function handleReturn(int $exitCode, ?int $peakMemoryUsageBytes): int { - if ($this->getErrorOutput()->isVerbose()) { - $this->getErrorOutput()->writeLineFormatted(sprintf('Used memory: %s', BytesHelper::bytes(memory_get_peak_usage(true)))); + if ($peakMemoryUsageBytes !== null && $this->getErrorOutput()->isVerbose()) { + $this->getErrorOutput()->writeLineFormatted(sprintf('Used memory: %s', BytesHelper::bytes($peakMemoryUsageBytes))); } return $exitCode; diff --git a/src/Command/WorkerCommand.php b/src/Command/WorkerCommand.php index 232d299fad..0a98d508af 100644 --- a/src/Command/WorkerCommand.php +++ b/src/Command/WorkerCommand.php @@ -30,6 +30,7 @@ use function is_array; use function is_bool; use function is_string; +use function memory_get_peak_usage; use function sprintf; class WorkerCommand extends Command @@ -242,6 +243,7 @@ private function runWorker( 'result' => [ 'errors' => $errors, 'collectedData' => $collectedData, + 'memoryUsage' => memory_get_peak_usage(true), 'dependencies' => $dependencies, 'exportedNodes' => $exportedNodes, 'filesCount' => count($files), diff --git a/src/Parallel/ParallelAnalyser.php b/src/Parallel/ParallelAnalyser.php index 80cbd7a255..872e22d5b5 100644 --- a/src/Parallel/ParallelAnalyser.php +++ b/src/Parallel/ParallelAnalyser.php @@ -19,11 +19,13 @@ use function array_map; use function array_pop; use function array_reverse; +use function array_sum; use function count; use function defined; use function escapeshellarg; use function is_string; use function max; +use function memory_get_usage; use function parse_url; use function sprintf; use const PHP_URL_PORT; @@ -63,7 +65,9 @@ public function analyse( $loop = new StreamSelectLoop(); $numberOfProcesses = $schedule->getNumberOfProcesses(); + $someChildEnded = false; $errors = []; + $peakMemoryUsages = []; $internalErrors = []; $collectedData = []; @@ -138,7 +142,7 @@ public function analyse( $commandOptions, $input, ), $loop, $this->processTimeout); - $process->start(function (array $json) use ($process, &$internalErrors, &$errors, &$collectedData, &$dependencies, &$exportedNodes, &$jobs, $postFileCallback, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, $processIdentifier): void { + $process->start(function (array $json) use ($process, &$internalErrors, &$errors, &$collectedData, &$dependencies, &$exportedNodes, &$peakMemoryUsages, &$jobs, $postFileCallback, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, $processIdentifier): void { foreach ($json['errors'] as $jsonError) { if (is_string($jsonError)) { $internalErrors[] = sprintf('Internal error: %s', $jsonError); @@ -179,6 +183,10 @@ public function analyse( $postFileCallback($json['filesCount']); } + if (!isset($peakMemoryUsages[$processIdentifier]) || $peakMemoryUsages[$processIdentifier] < $json['memoryUsage']) { + $peakMemoryUsages[$processIdentifier] = $json['memoryUsage']; + } + $internalErrorsCount += $json['internalErrorsCount']; if ($internalErrorsCount >= $this->internalErrorsCountLimit) { $reachedInternalErrorsCountLimit = true; @@ -192,7 +200,12 @@ public function analyse( $job = array_pop($jobs); $process->request(['action' => 'analyse', 'files' => $job]); - }, $handleError, function ($exitCode, string $output) use (&$internalErrors, &$internalErrorsCount, $processIdentifier): void { + }, $handleError, function ($exitCode, string $output) use (&$someChildEnded, &$peakMemoryUsages, &$internalErrors, &$internalErrorsCount, $processIdentifier): void { + if ($someChildEnded === false) { + $peakMemoryUsages['main'] = memory_get_usage(true); + } + $someChildEnded = true; + $this->processPool->tryQuitProcess($processIdentifier); if ($exitCode === 0) { return; @@ -221,6 +234,7 @@ public function analyse( $internalErrorsCount === 0 ? $dependencies : null, $exportedNodes, $reachedInternalErrorsCountLimit, + (int) array_sum($peakMemoryUsages), // not 100% correct as the peak usages of workers might not have met ); } diff --git a/src/Testing/ErrorFormatterTestCase.php b/src/Testing/ErrorFormatterTestCase.php index 4813452b71..924765b90b 100644 --- a/src/Testing/ErrorFormatterTestCase.php +++ b/src/Testing/ErrorFormatterTestCase.php @@ -100,6 +100,7 @@ protected function getAnalysisResult(int $numFileErrors, int $numGenericErrors): false, null, true, + 0, ); } diff --git a/tests/PHPStan/Command/AnalysisResultTest.php b/tests/PHPStan/Command/AnalysisResultTest.php index 8ec17f2a8e..cb34089ee3 100644 --- a/tests/PHPStan/Command/AnalysisResultTest.php +++ b/tests/PHPStan/Command/AnalysisResultTest.php @@ -43,6 +43,7 @@ public function testErrorsAreSortedByFileNameAndLine(): void false, null, true, + 0, ))->getFileSpecificErrors(), ); } diff --git a/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php index ea66e724ba..f07c88f9de 100644 --- a/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php @@ -148,6 +148,7 @@ public function testFormatErrorMessagesRegexEscape(): void false, null, true, + 0, ); $formatter->formatErrors( $result, @@ -185,6 +186,7 @@ public function testEscapeDiNeon(): void false, null, true, + 0, ); $formatter->formatErrors( @@ -249,6 +251,7 @@ public function testOutputOrdering(array $errors): void false, null, true, + 0, ); $formatter->formatErrors( @@ -406,6 +409,7 @@ public function testEndOfFileNewlines( false, null, true, + 0, ); $resource = fopen('php://memory', 'w', false); diff --git a/tests/PHPStan/Command/ErrorFormatter/CheckstyleErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/CheckstyleErrorFormatterTest.php index 04d4996963..2a16f5d420 100644 --- a/tests/PHPStan/Command/ErrorFormatter/CheckstyleErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/CheckstyleErrorFormatterTest.php @@ -154,6 +154,7 @@ public function testTraitPath(): void false, null, true, + 0, ), $this->getOutput()); $this->assertXmlStringEqualsXmlString(' diff --git a/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php index 8998cb0935..fd7ce19b75 100644 --- a/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php @@ -210,7 +210,7 @@ public function testEditorUrlWithTrait(): void { $formatter = $this->createErrorFormatter('editor://%file%/%line%'); $error = new Error('Test', 'Foo.php (in context of trait)', 12, true, 'Foo.php', 'Bar.php'); - $formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true), $this->getOutput()); + $formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true, 0), $this->getOutput()); $this->assertStringContainsString('Bar.php', $this->getOutputContent()); } @@ -219,7 +219,7 @@ public function testEditorUrlWithRelativePath(): void { $formatter = $this->createErrorFormatter('editor://custom/path/%relFile%/%line%'); $error = new Error('Test', 'Foo.php', 12, true, self::DIRECTORY_PATH . '/rel/Foo.php'); - $formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true), $this->getOutput(true)); + $formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true, 0), $this->getOutput(true)); $this->assertStringContainsString('editor://custom/path/rel/Foo.php', $this->getOutputContent(true)); } @@ -228,7 +228,7 @@ public function testEditorUrlWithCustomTitle(): void { $formatter = $this->createErrorFormatter('editor://any', '%relFile%:%line%'); $error = new Error('Test', 'Foo.php', 12, true, self::DIRECTORY_PATH . '/rel/Foo.php'); - $formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true), $this->getOutput(true)); + $formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true, 0), $this->getOutput(true)); $this->assertStringContainsString('rel/Foo.php:12', $this->getOutputContent(true)); } @@ -253,6 +253,7 @@ public function testBug6727(): void false, null, true, + 0, ), $this->getOutput(), );