55use Override ;
66use PHPStan \Analyser \Error ;
77use PHPStan \Command \AnalysisResult ;
8+ use PHPStan \Command \CommandHelper ;
89use PHPStan \File \FuzzyRelativePathHelper ;
910use PHPStan \File \NullRelativePathHelper ;
1011use PHPStan \File \SimpleRelativePathHelper ;
@@ -34,6 +35,7 @@ protected function tearDown(): void
3435 putenv ('COLUMNS ' );
3536 putenv ('TERM_PROGRAM ' );
3637 putenv ('TERMINAL_EMULATOR ' . ($ this ->terminalEmulator !== false ? '= ' . $ this ->terminalEmulator : '' ));
38+ putenv ('PHPSTAN_TABLE_ERROR_FORMATTER_FORCE_SHOW_ALL_ERRORS ' );
3739 }
3840
3941 public static function dataFormatterOutputProvider (): iterable
@@ -293,6 +295,198 @@ public function testFormatErrors(
293295 $ this ->assertSame ($ expected , $ this ->getOutputContent (false , $ verbose ), sprintf ('%s: output do not match ' , $ message ));
294296 }
295297
298+ public static function dataErrorLimit (): iterable
299+ {
300+ yield [
301+ 'errorsBudget ' => null ,
302+ 'usedLevel ' => CommandHelper::DEFAULT_LEVEL ,
303+ 'showAllErrors ' => false ,
304+ 'expected ' => ' ------ -------------------------------
305+ Line Foo.php (in context of trait)
306+ ------ -------------------------------
307+ 12 Test
308+ 13 Test
309+ 14 Test
310+ 15 Test
311+ ------ -------------------------------
312+
313+
314+ [ERROR] Found 4 errors
315+
316+ ' ,
317+ ];
318+ yield [
319+ 'errorsBudget ' => 1 ,
320+ 'usedLevel ' => CommandHelper::DEFAULT_LEVEL ,
321+ 'showAllErrors ' => false ,
322+ 'expected ' => ' ------ -------------------------------
323+ Line Foo.php (in context of trait)
324+ ------ -------------------------------
325+ 12 Test
326+ ------ -------------------------------
327+
328+
329+ [ERROR] Found 1+ errors
330+
331+ ! [NOTE] Result is limited to the first 1 errors
332+ ! - Pass PHPSTAN_TABLE_ERROR_FORMATTER_FORCE_SHOW_ALL_ERRORS=1
333+ ! environment variable to show all errors
334+ ! - Consider using PHPStan Pro for more comfortable error browsing
335+ ! Learn more: https://phpstan.com
336+
337+ ' ,
338+ ];
339+
340+ yield [
341+ 'errorsBudget ' => 3 ,
342+ 'usedLevel ' => '8 ' ,
343+ 'showAllErrors ' => false ,
344+ 'expected ' => ' ------ -------------------------------
345+ Line Foo.php (in context of trait)
346+ ------ -------------------------------
347+ 12 Test
348+ 13 Test
349+ 14 Test
350+ ------ -------------------------------
351+
352+
353+ [ERROR] Found 3+ errors
354+
355+ ! [NOTE] Result is limited to the first 3 errors
356+ ! - Consider lowering the PHPStan level
357+ ! - Pass PHPSTAN_TABLE_ERROR_FORMATTER_FORCE_SHOW_ALL_ERRORS=1
358+ ! environment variable to show all errors
359+ ! - Consider using PHPStan Pro for more comfortable error browsing
360+ ! Learn more: https://phpstan.com
361+
362+ ' ,
363+ ];
364+
365+ yield [
366+ 'errorsBudget ' => 3 ,
367+ 'usedLevel ' => CommandHelper::DEFAULT_LEVEL ,
368+ 'showAllErrors ' => false ,
369+ 'expected ' => ' ------ -------------------------------
370+ Line Foo.php (in context of trait)
371+ ------ -------------------------------
372+ 12 Test
373+ 13 Test
374+ 14 Test
375+ ------ -------------------------------
376+
377+
378+ [ERROR] Found 3+ errors
379+
380+ ! [NOTE] Result is limited to the first 3 errors
381+ ! - Pass PHPSTAN_TABLE_ERROR_FORMATTER_FORCE_SHOW_ALL_ERRORS=1
382+ ! environment variable to show all errors
383+ ! - Consider using PHPStan Pro for more comfortable error browsing
384+ ! Learn more: https://phpstan.com
385+ ' ,
386+ ];
387+
388+ yield [
389+ 'errorsBudget ' => 4 ,
390+ 'usedLevel ' => CommandHelper::DEFAULT_LEVEL ,
391+ 'showAllErrors ' => false ,
392+ 'expected ' => ' ------ -------------------------------
393+ Line Foo.php (in context of trait)
394+ ------ -------------------------------
395+ 12 Test
396+ 13 Test
397+ 14 Test
398+ 15 Test
399+ ------ -------------------------------
400+
401+
402+ [ERROR] Found 4 errors
403+
404+ ' ,
405+ ];
406+ yield [
407+ 'errorsBudget ' => 5 ,
408+ 'usedLevel ' => CommandHelper::DEFAULT_LEVEL ,
409+ 'showAllErrors ' => false ,
410+ 'expected ' => ' ------ -------------------------------
411+ Line Foo.php (in context of trait)
412+ ------ -------------------------------
413+ 12 Test
414+ 13 Test
415+ 14 Test
416+ 15 Test
417+ ------ -------------------------------
418+
419+
420+ [ERROR] Found 4 errors
421+
422+ ' ,
423+ ];
424+
425+ yield [
426+ 'errorsBudget ' => null ,
427+ 'usedLevel ' => '8 ' ,
428+ 'showAllErrors ' => false ,
429+ 'expected ' => '
430+
431+ [ERROR] Found 1000+ errors
432+
433+ ' ,
434+ 'generateErrorsCount ' => TableErrorFormatter::ERRORS_LIMIT + 5 ,
435+ ];
436+
437+ yield [
438+ 'errorsBudget ' => null ,
439+ 'usedLevel ' => '8 ' ,
440+ 'showAllErrors ' => true ,
441+ 'expected ' => '
442+
443+ [ERROR] Found 1005 errors
444+
445+ ' ,
446+ 'generateErrorsCount ' => TableErrorFormatter::ERRORS_LIMIT + 5 ,
447+ ];
448+ }
449+
450+ #[DataProvider('dataErrorLimit ' )]
451+ public function testErrorLimit (
452+ ?int $ errorsBudget ,
453+ string $ usedLevel ,
454+ bool $ showAllErrors ,
455+ string $ expected ,
456+ int $ generateErrorsCount = 4 ,
457+ ): void
458+ {
459+ // windows has minor formatting differences (line breaks)
460+ $ this ->skipIfNotOnUnix ();
461+
462+ putenv ('COLUMNS=80 ' );
463+ if ($ showAllErrors ) {
464+ if ($ errorsBudget !== null ) {
465+ $ this ->fail ('showAllErrors cannot be true when errorsBudget is set ' );
466+ }
467+ putenv ('PHPSTAN_TABLE_ERROR_FORMATTER_FORCE_SHOW_ALL_ERRORS=1 ' );
468+ $ errorsBudget = null ;
469+ } else {
470+ putenv ('PHPSTAN_TABLE_ERROR_FORMATTER_FORCE_SHOW_ALL_ERRORS ' );
471+ }
472+
473+ $ formatter = $ this ->createErrorFormatter (
474+ null ,
475+ null ,
476+ $ usedLevel ,
477+ $ errorsBudget ,
478+ );
479+ $ errors = [];
480+ $ line = 12 ;
481+ for ($ i = 0 ; $ i < $ generateErrorsCount ; $ i ++) {
482+ $ errors [] = new Error ('Test ' , 'Foo.php (in context of trait) ' , $ line , filePath: 'Foo.php ' , traitFilePath: 'Bar.php ' );
483+ $ line ++;
484+ }
485+ $ formatter ->formatErrors (new AnalysisResult ($ errors , [], [], [], [], false , null , true , 0 , false , []), $ this ->getOutput ());
486+
487+ $ this ->assertStringContainsString ($ expected , $ this ->getOutputContent ());
488+ }
489+
296490 public function testEditorUrlWithTrait (): void
297491 {
298492 $ formatter = $ this ->createErrorFormatter ('editor://%file%/%line% ' );
@@ -441,14 +635,20 @@ public function testJetBrainsTerminalRelativePath(): void
441635 false ,
442636 null ,
443637 null ,
638+ CommandHelper::DEFAULT_LEVEL ,
444639 );
445640 $ error = new Error ('Test ' , 'Foo.php ' , 12 , filePath: self ::DIRECTORY_PATH . '/rel/Foo.php ' );
446641 $ formatter ->formatErrors (new AnalysisResult ([$ error ], [], [], [], [], false , null , true , 0 , false , []), $ this ->getOutput (true ));
447642
448643 $ this ->assertStringContainsString ('at rel/Foo.php:12 ' , $ this ->getOutputContent (true ));
449644 }
450645
451- private function createErrorFormatter (?string $ editorUrl , ?string $ editorUrlTitle = null ): TableErrorFormatter
646+ private function createErrorFormatter (
647+ ?string $ editorUrl ,
648+ ?string $ editorUrlTitle = null ,
649+ string $ usedLevel = CommandHelper::DEFAULT_LEVEL ,
650+ ?int $ errorsBudget = null ,
651+ ): TableErrorFormatter
452652 {
453653 $ relativePathHelper = new FuzzyRelativePathHelper (new NullRelativePathHelper (), self ::DIRECTORY_PATH , [], '/ ' );
454654
@@ -462,6 +662,8 @@ private function createErrorFormatter(?string $editorUrl, ?string $editorUrlTitl
462662 false ,
463663 $ editorUrl ,
464664 $ editorUrlTitle ,
665+ $ usedLevel ,
666+ $ errorsBudget ,
465667 );
466668 }
467669
0 commit comments