10
10
use ReflectionClass ;
11
11
use ShipMonk \Composer \Config \Configuration ;
12
12
use ShipMonk \Composer \Config \ErrorType ;
13
- use ShipMonk \Composer \Crate \ClassUsage ;
14
- use ShipMonk \Composer \Error \ClassmapEntryMissingError ;
15
- use ShipMonk \Composer \Error \DevDependencyInProductionCodeError ;
16
- use ShipMonk \Composer \Error \ShadowDependencyError ;
17
- use ShipMonk \Composer \Error \SymbolError ;
18
- use ShipMonk \Composer \Error \UnusedDependencyError ;
13
+ use ShipMonk \Composer \Result \AnalysisResult ;
14
+ use ShipMonk \Composer \Result \SymbolUsage ;
19
15
use UnexpectedValueException ;
20
16
use function array_diff ;
21
17
use function array_filter ;
22
18
use function array_keys ;
23
- use function array_values ;
24
19
use function class_exists ;
25
20
use function defined ;
26
21
use function explode ;
27
22
use function file_get_contents ;
28
23
use function function_exists ;
29
- use function get_class ;
30
24
use function interface_exists ;
31
25
use function is_file ;
26
+ use function ksort ;
32
27
use function realpath ;
28
+ use function sort ;
33
29
use function str_replace ;
34
30
use function strlen ;
35
31
use function substr ;
36
32
use function trim ;
37
- use function usort ;
38
33
use const DIRECTORY_SEPARATOR ;
39
34
40
35
class ComposerDependencyAnalyser
@@ -86,12 +81,12 @@ public function __construct(
86
81
$ this ->composerJsonDependencies = $ composerJsonDependencies ;
87
82
}
88
83
89
- /**
90
- * @return list<SymbolError>
91
- */
92
- public function run (): array
84
+ public function run (): AnalysisResult
93
85
{
94
- $ errors = [];
86
+ $ classmapErrors = [];
87
+ $ shadowErrors = [];
88
+ $ devInProdErrors = [];
89
+ $ unusedErrors = [];
95
90
$ usedPackages = [];
96
91
97
92
foreach ($ this ->config ->getPathsToScan () as $ scanPath ) {
@@ -100,7 +95,7 @@ public function run(): array
100
95
continue ;
101
96
}
102
97
103
- foreach ($ this ->getUsedSymbolsInFile ($ filePath ) as $ usedSymbol => $ lineNumber ) {
98
+ foreach ($ this ->getUsedSymbolsInFile ($ filePath ) as $ usedSymbol => $ lineNumbers ) {
104
99
if ($ this ->isInternalClass ($ usedSymbol )) {
105
100
continue ;
106
101
}
@@ -115,7 +110,9 @@ public function run(): array
115
110
&& !$ this ->config ->shouldIgnoreUnknownClass ($ usedSymbol )
116
111
&& !$ this ->config ->shouldIgnoreError (ErrorType::UNKNOWN_CLASS , $ filePath , null )
117
112
) {
118
- $ errors [$ usedSymbol ] = new ClassmapEntryMissingError (new ClassUsage ($ usedSymbol , $ filePath , $ lineNumber ));
113
+ foreach ($ lineNumbers as $ lineNumber ) {
114
+ $ classmapErrors [$ usedSymbol ][] = new SymbolUsage ($ filePath , $ lineNumber );
115
+ }
119
116
}
120
117
121
118
continue ;
@@ -133,15 +130,19 @@ public function run(): array
133
130
$ this ->isShadowDependency ($ packageName )
134
131
&& !$ this ->config ->shouldIgnoreError (ErrorType::SHADOW_DEPENDENCY , $ filePath , $ packageName )
135
132
) {
136
- $ errors [$ packageName ] = new ShadowDependencyError ($ packageName , new ClassUsage ($ usedSymbol , $ filePath , $ lineNumber ));
133
+ foreach ($ lineNumbers as $ lineNumber ) {
134
+ $ shadowErrors [$ packageName ][$ usedSymbol ][] = new SymbolUsage ($ filePath , $ lineNumber );
135
+ }
137
136
}
138
137
139
138
if (
140
139
!$ scanPath ->isDev ()
141
140
&& $ this ->isDevDependency ($ packageName )
142
141
&& !$ this ->config ->shouldIgnoreError (ErrorType::DEV_DEPENDENCY_IN_PROD , $ filePath , $ packageName )
143
142
) {
144
- $ errors [$ packageName ] = new DevDependencyInProductionCodeError ($ packageName , new ClassUsage ($ usedSymbol , $ filePath , $ lineNumber ));
143
+ foreach ($ lineNumbers as $ lineNumber ) {
144
+ $ devInProdErrors [$ packageName ][$ usedSymbol ][] = new SymbolUsage ($ filePath , $ lineNumber );
145
+ }
145
146
}
146
147
147
148
$ usedPackages [$ packageName ] = true ;
@@ -158,20 +159,21 @@ public function run(): array
158
159
159
160
foreach ($ unusedDependencies as $ unusedDependency ) {
160
161
if (!$ this ->config ->shouldIgnoreError (ErrorType::UNUSED_DEPENDENCY , null , $ unusedDependency )) {
161
- $ errors [] = new UnusedDependencyError ( $ unusedDependency) ;
162
+ $ unusedErrors [] = $ unusedDependency ;
162
163
}
163
164
}
164
165
165
- usort ($ errors , static function (SymbolError $ a , SymbolError $ b ): int {
166
- $ aPackageName = $ a ->getPackageName () ?? '' ;
167
- $ bPackageName = $ b ->getPackageName () ?? '' ;
168
- $ aClassName = $ a ->getExampleUsage () !== null ? $ a ->getExampleUsage ()->getClassname () : '' ;
169
- $ bClassName = $ b ->getExampleUsage () !== null ? $ b ->getExampleUsage ()->getClassname () : '' ;
170
-
171
- return [get_class ($ a ), $ aPackageName , $ aClassName ] <=> [get_class ($ b ), $ bPackageName , $ bClassName ];
172
- });
166
+ ksort ($ classmapErrors );
167
+ ksort ($ shadowErrors );
168
+ ksort ($ devInProdErrors );
169
+ sort ($ unusedErrors );
173
170
174
- return array_values ($ errors );
171
+ return new AnalysisResult (
172
+ $ classmapErrors ,
173
+ $ shadowErrors ,
174
+ $ devInProdErrors ,
175
+ $ unusedErrors
176
+ );
175
177
}
176
178
177
179
private function isShadowDependency (string $ packageName ): bool
@@ -193,7 +195,7 @@ private function getPackageNameFromVendorPath(string $realPath): string
193
195
}
194
196
195
197
/**
196
- * @return array<string, int>
198
+ * @return array<string, list< int> >
197
199
*/
198
200
private function getUsedSymbolsInFile (string $ filePath ): array
199
201
{
0 commit comments