6
6
use PHPStan \Analyser \Error ;
7
7
use PHPStan \Rules \Rule ;
8
8
use PHPStan \Testing \RuleTestCase as OriginalRuleTestCase ;
9
+ use function array_diff ;
9
10
use function array_values ;
10
11
use function explode ;
11
12
use function file_get_contents ;
15
16
use function preg_match ;
16
17
use function preg_match_all ;
17
18
use function preg_replace ;
19
+ use function sort ;
18
20
use function sprintf ;
19
21
use function trim ;
20
22
use function uniqid ;
26
28
abstract class RuleTestCase extends OriginalRuleTestCase
27
29
{
28
30
29
- protected function analyseFile (string $ file , bool $ autofix = false ): void
31
+ /**
32
+ * @param list<string> $files
33
+ */
34
+ protected function analyseFiles (array $ files , bool $ autofix = false ): void
30
35
{
31
- $ analyserErrors = $ this ->gatherAnalyserErrors ([$ file ]);
36
+ sort ($ files );
37
+
38
+ $ analyserErrors = $ this ->gatherAnalyserErrors ($ files );
32
39
33
40
if ($ autofix === true ) {
34
- $ this ->autofix ($ file , $ analyserErrors );
35
- self ::fail ("File $ file was autofixed. This setup should never remain in the codebase. " );
41
+ foreach ($ files as $ file ) {
42
+ $ this ->autofix ($ file , $ analyserErrors );
43
+ }
44
+
45
+ self ::fail ('Autofixed. This setup should never remain in the codebase. ' );
36
46
}
37
47
38
- $ actualErrors = $ this ->processActualErrors ($ analyserErrors );
39
- $ expectedErrors = $ this ->parseExpectedErrors ($ file );
48
+ if ($ analyserErrors === []) {
49
+ $ this ->expectNotToPerformAssertions ();
50
+ }
51
+
52
+ $ actualErrorsByFile = $ this ->processActualErrors ($ analyserErrors );
53
+
54
+ foreach ($ actualErrorsByFile as $ file => $ actualErrors ) {
55
+ $ expectedErrors = $ this ->parseExpectedErrors ($ file );
56
+
57
+ $ extraErrors = array_diff ($ expectedErrors , $ actualErrors );
58
+ $ missingErrors = array_diff ($ actualErrors , $ expectedErrors );
40
59
41
- self ::assertSame (
42
- implode ("\n" , $ expectedErrors ) . "\n" ,
43
- implode ("\n" , $ actualErrors ) . "\n" ,
44
- );
60
+ $ extraErrorsString = $ extraErrors === [] ? '' : "\n - Extra errors: " . implode ("\n" , $ extraErrors );
61
+ $ missingErrorsString = $ missingErrors === [] ? '' : "\n - Missing errors: " . implode ("\n" , $ missingErrors );
62
+
63
+ self ::assertSame (
64
+ implode ("\n" , $ expectedErrors ) . "\n" ,
65
+ implode ("\n" , $ actualErrors ) . "\n" ,
66
+ sprintf (
67
+ "Errors in file $ file do not match. %s \n" ,
68
+ $ extraErrorsString . $ missingErrorsString ,
69
+ ),
70
+ );
71
+ }
45
72
}
46
73
47
74
/**
48
75
* @param list<Error> $actualErrors
49
- * @return list<string>
76
+ * @return array<string, list<string> >
50
77
*/
51
78
protected function processActualErrors (array $ actualErrors ): array
52
79
{
@@ -55,15 +82,22 @@ protected function processActualErrors(array $actualErrors): array
55
82
foreach ($ actualErrors as $ error ) {
56
83
$ usedLine = $ error ->getLine () ?? -1 ;
57
84
$ key = sprintf ('%04d ' , $ usedLine ) . '- ' . uniqid ();
58
- $ resultToAssert [$ key ] = $ this ->formatErrorForAssert ($ error ->getMessage (), $ usedLine );
85
+ $ resultToAssert [$ error -> getFile ()][ $ key ] = $ this ->formatErrorForAssert ($ error ->getMessage (), $ usedLine );
59
86
60
87
self ::assertNotNull ($ error ->getIdentifier (), "Missing error identifier for error: {$ error ->getMessage ()}" );
61
88
self ::assertStringStartsWith ('shipmonk. ' , $ error ->getIdentifier (), "Unexpected error identifier for: {$ error ->getMessage ()}" );
62
89
}
63
90
64
- ksort ($ resultToAssert );
91
+ $ finalResult = [];
92
+
93
+ foreach ($ resultToAssert as $ file => $ fileErrors ) {
94
+ ksort ($ fileErrors );
95
+ $ finalResult [$ file ] = array_values ($ fileErrors );
96
+ }
65
97
66
- return array_values ($ resultToAssert );
98
+ ksort ($ finalResult );
99
+
100
+ return $ finalResult ;
67
101
}
68
102
69
103
/**
@@ -117,6 +151,10 @@ private function autofix(string $file, array $analyserErrors): void
117
151
throw new LogicException ('Error without line number: ' . $ analyserError ->getMessage ());
118
152
}
119
153
154
+ if ($ analyserError ->getFile () !== $ file ) {
155
+ continue ;
156
+ }
157
+
120
158
$ errorsByLines [$ line ] = $ analyserError ;
121
159
}
122
160
0 commit comments