Skip to content

Commit 04277aa

Browse files
committed
Unify ext-* and package handling
1 parent 6cd4c6f commit 04277aa

File tree

8 files changed

+69
-136
lines changed

8 files changed

+69
-136
lines changed

bin/composer-dependency-analyser

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ try {
3838
$configuration = $initializer->initConfiguration($options, $composerJson);
3939
$classLoaders = $initializer->initComposerClassLoaders();
4040

41-
$analyser = new Analyser($stopwatch, $classLoaders, $configuration, $composerJson->dependencies, $composerJson->extensions);
41+
$analyser = new Analyser($stopwatch, $classLoaders, $configuration, $composerJson->dependencies);
4242
$result = $analyser->run();
4343

4444
$formatter = $initializer->initFormatter($options);

src/Analyser.php

Lines changed: 56 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use function array_filter;
2222
use function array_key_exists;
2323
use function array_keys;
24-
use function array_merge;
2524
use function explode;
2625
use function file_get_contents;
2726
use function get_declared_classes;
@@ -81,19 +80,12 @@ class Analyser
8180
private $classmap = [];
8281

8382
/**
84-
* package name => is dev dependency
83+
* package or ext-* => is dev dependency
8584
*
8685
* @var array<string, bool>
8786
*/
8887
private $composerJsonDependencies;
8988

90-
/**
91-
* ext-* => is dev dependency
92-
*
93-
* @var array<string, bool>
94-
*/
95-
private $composerJsonExtensions;
96-
9789
/**
9890
* symbol name => true
9991
*
@@ -117,21 +109,18 @@ class Analyser
117109

118110
/**
119111
* @param array<string, ClassLoader> $classLoaders vendorDir => ClassLoader (e.g. result of \Composer\Autoload\ClassLoader::getRegisteredLoaders())
120-
* @param array<string, bool> $composerJsonDependencies package name => is dev dependency
121-
* @param array<string, bool> $composerJsonExtensions ext-* => is dev dependency
112+
* @param array<string, bool> $composerJsonDependencies package or ext-* => is dev dependency
122113
*/
123114
public function __construct(
124115
Stopwatch $stopwatch,
125116
array $classLoaders,
126117
Configuration $config,
127-
array $composerJsonDependencies,
128-
array $composerJsonExtensions
118+
array $composerJsonDependencies
129119
)
130120
{
131121
$this->stopwatch = $stopwatch;
132122
$this->config = $config;
133123
$this->composerJsonDependencies = $composerJsonDependencies;
134-
$this->composerJsonExtensions = $composerJsonExtensions;
135124

136125
$this->initExistingSymbols();
137126

@@ -150,14 +139,12 @@ public function run(): AnalysisResult
150139
$scannedFilesCount = 0;
151140
$unknownClassErrors = [];
152141
$unknownFunctionErrors = [];
153-
$missingExtensions = [];
154142
$shadowErrors = [];
155143
$devInProdErrors = [];
156144
$prodOnlyInDevErrors = [];
157145
$unusedErrors = [];
158146

159-
$usedPackages = [];
160-
$usedExtensions = [];
147+
$usedDependencies = [];
161148
$prodPackagesUsedInProdPath = [];
162149

163150
$usages = [];
@@ -176,72 +163,64 @@ public function run(): AnalysisResult
176163
}
177164

178165
if (isset($this->extensionSymbols[$kind][$usedSymbol])) {
179-
$neededExtension = $this->extensionSymbols[$kind][$usedSymbol];
180-
$usedExtensions[$neededExtension] = true;
181-
182-
if (!isset($this->composerJsonExtensions[$neededExtension])) {
183-
foreach ($lineNumbers as $lineNumber) {
184-
$missingExtensions[$neededExtension][] = new SymbolUsage($filePath, $lineNumber, $kind);
185-
}
186-
}
187-
188-
continue;
189-
}
166+
$dependencyName = $this->extensionSymbols[$kind][$usedSymbol];
190167

191-
$symbolPath = $this->getSymbolPath($usedSymbol, $kind);
168+
} else {
169+
$symbolPath = $this->getSymbolPath($usedSymbol, $kind);
192170

193-
if ($symbolPath === null) {
194-
if ($kind === SymbolKind::CLASSLIKE && !$ignoreList->shouldIgnoreUnknownClass($usedSymbol, $filePath)) {
195-
foreach ($lineNumbers as $lineNumber) {
196-
$unknownClassErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
171+
if ($symbolPath === null) {
172+
if ($kind === SymbolKind::CLASSLIKE && !$ignoreList->shouldIgnoreUnknownClass($usedSymbol, $filePath)) {
173+
foreach ($lineNumbers as $lineNumber) {
174+
$unknownClassErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
175+
}
197176
}
198-
}
199177

200-
if ($kind === SymbolKind::FUNCTION && !$ignoreList->shouldIgnoreUnknownFunction($usedSymbol, $filePath)) {
201-
foreach ($lineNumbers as $lineNumber) {
202-
$unknownFunctionErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
178+
if ($kind === SymbolKind::FUNCTION && !$ignoreList->shouldIgnoreUnknownFunction($usedSymbol, $filePath)) {
179+
foreach ($lineNumbers as $lineNumber) {
180+
$unknownFunctionErrors[$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
181+
}
203182
}
183+
184+
continue;
204185
}
205186

206-
continue;
207-
}
187+
if (!$this->isVendorPath($symbolPath)) {
188+
continue; // local class
189+
}
208190

209-
if (!$this->isVendorPath($symbolPath)) {
210-
continue; // local class
191+
$dependencyName = $this->getPackageNameFromVendorPath($symbolPath);
211192
}
212193

213-
$packageName = $this->getPackageNameFromVendorPath($symbolPath);
214-
215194
if (
216-
$this->isShadowDependency($packageName)
217-
&& !$ignoreList->shouldIgnoreError(ErrorType::SHADOW_DEPENDENCY, $filePath, $packageName)
195+
$this->isShadowDependency($dependencyName)
196+
&& !$ignoreList->shouldIgnoreError(ErrorType::SHADOW_DEPENDENCY, $filePath, $dependencyName)
218197
) {
219198
foreach ($lineNumbers as $lineNumber) {
220-
$shadowErrors[$packageName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
199+
$shadowErrors[$dependencyName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
221200
}
222201
}
223202

224203
if (
225204
!$isDevFilePath
226-
&& $this->isDevDependency($packageName)
227-
&& !$ignoreList->shouldIgnoreError(ErrorType::DEV_DEPENDENCY_IN_PROD, $filePath, $packageName)
205+
&& $this->isDevDependency($dependencyName)
206+
&& !$ignoreList->shouldIgnoreError(ErrorType::DEV_DEPENDENCY_IN_PROD, $filePath, $dependencyName)
228207
) {
229208
foreach ($lineNumbers as $lineNumber) {
230-
$devInProdErrors[$packageName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
209+
$devInProdErrors[$dependencyName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
231210
}
232211
}
233212

234213
if (
235214
!$isDevFilePath
236-
&& !$this->isDevDependency($packageName)
215+
&& !$this->isDevDependency($dependencyName)
237216
) {
238-
$prodPackagesUsedInProdPath[$packageName] = true;
217+
$prodPackagesUsedInProdPath[$dependencyName] = true;
239218
}
240219

241-
$usedPackages[$packageName] = true;
220+
$usedDependencies[$dependencyName] = true;
242221

243222
foreach ($lineNumbers as $lineNumber) {
244-
$usages[$packageName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
223+
$usages[$dependencyName][$usedSymbol][] = new SymbolUsage($filePath, $lineNumber, $kind);
245224
}
246225
}
247226
}
@@ -254,36 +233,40 @@ public function run(): AnalysisResult
254233
continue;
255234
}
256235

257-
$symbolPath = $this->getSymbolPath($forceUsedSymbol, null);
236+
if (
237+
isset($this->extensionSymbols[SymbolKind::FUNCTION][$forceUsedSymbol])
238+
|| isset($this->extensionSymbols[SymbolKind::CONSTANT][$forceUsedSymbol])
239+
|| isset($this->extensionSymbols[SymbolKind::CLASSLIKE][$forceUsedSymbol])
240+
) {
241+
$forceUsedDependency = $this->extensionSymbols[SymbolKind::FUNCTION][$forceUsedSymbol]
242+
?? $this->extensionSymbols[SymbolKind::CONSTANT][$forceUsedSymbol]
243+
?? $this->extensionSymbols[SymbolKind::CLASSLIKE][$forceUsedSymbol];
244+
} else {
245+
$symbolPath = $this->getSymbolPath($forceUsedSymbol, null);
246+
247+
if ($symbolPath === null || !$this->isVendorPath($symbolPath)) {
248+
continue;
249+
}
258250

259-
if ($symbolPath === null || !$this->isVendorPath($symbolPath)) {
260-
continue;
251+
$forceUsedDependency = $this->getPackageNameFromVendorPath($symbolPath);
261252
}
262253

263-
$forceUsedPackage = $this->getPackageNameFromVendorPath($symbolPath);
264-
$usedPackages[$forceUsedPackage] = true;
265-
$forceUsedPackages[$forceUsedPackage] = true;
254+
$usedDependencies[$forceUsedDependency] = true;
255+
$forceUsedPackages[$forceUsedDependency] = true;
266256
}
267257

268258
if ($this->config->shouldReportUnusedDevDependencies()) {
269-
$dependenciesForUnusedAnalysis = array_merge(
270-
array_keys($this->composerJsonDependencies),
271-
array_keys($this->composerJsonExtensions)
272-
);
259+
$dependenciesForUnusedAnalysis = array_keys($this->composerJsonDependencies);
273260

274261
} else {
275-
$dependenciesForUnusedAnalysis = array_merge(
276-
array_keys(array_filter($this->composerJsonDependencies, static function (bool $devDependency) {
277-
return !$devDependency; // dev deps are typically used only in CI
278-
})),
279-
array_keys($this->composerJsonExtensions)
280-
);
262+
$dependenciesForUnusedAnalysis = array_keys(array_filter($this->composerJsonDependencies, static function (bool $devDependency) {
263+
return !$devDependency; // dev deps are typically used only in CI
264+
}));
281265
}
282266

283267
$unusedDependencies = array_diff(
284268
$dependenciesForUnusedAnalysis,
285-
array_keys($usedPackages),
286-
array_keys($usedExtensions),
269+
array_keys($usedDependencies),
287270
self::CORE_EXTENSIONS
288271
);
289272

@@ -300,7 +283,8 @@ public function run(): AnalysisResult
300283
$prodDependencies,
301284
array_keys($prodPackagesUsedInProdPath),
302285
array_keys($forceUsedPackages), // we dont know where are those used, lets not report them
303-
$unusedDependencies
286+
$unusedDependencies,
287+
self::CORE_EXTENSIONS
304288
);
305289

306290
foreach ($prodPackagesUsedOnlyInDev as $prodPackageUsedOnlyInDev) {
@@ -313,7 +297,6 @@ public function run(): AnalysisResult
313297
$scannedFilesCount,
314298
$this->stopwatch->stop(),
315299
$usages,
316-
$missingExtensions,
317300
$unknownClassErrors,
318301
$unknownFunctionErrors,
319302
$shadowErrors,

src/ComposerJson.php

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,7 @@ class ComposerJson
3131
public $composerAutoloadPath;
3232

3333
/**
34-
* ext-* => isDev
35-
*
36-
* @readonly
37-
* @var array<string, bool>
38-
*/
39-
public $extensions;
40-
41-
/**
42-
* Package => isDev
34+
* Package or ext-* => isDev
4335
*
4436
* @readonly
4537
* @var array<string, bool>
@@ -90,10 +82,8 @@ public function __construct(
9082

9183
$this->dependencies = array_merge(
9284
array_fill_keys(array_keys(array_filter($requiredPackages, $filterPackages, ARRAY_FILTER_USE_KEY)), false),
93-
array_fill_keys(array_keys(array_filter($requiredDevPackages, $filterPackages, ARRAY_FILTER_USE_KEY)), true)
94-
);
95-
$this->extensions = array_merge(
9685
array_fill_keys(array_keys(array_filter($requiredPackages, $filterExtensions, ARRAY_FILTER_USE_KEY)), false),
86+
array_fill_keys(array_keys(array_filter($requiredDevPackages, $filterPackages, ARRAY_FILTER_USE_KEY)), true),
9787
array_fill_keys(array_keys(array_filter($requiredDevPackages, $filterExtensions, ARRAY_FILTER_USE_KEY)), true)
9888
);
9989

src/Result/AnalysisResult.php

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ class AnalysisResult
2525
*/
2626
private $usages;
2727

28-
/**
29-
* @var array<string, list<SymbolUsage>>
30-
*/
31-
private $missingExtensionsErrors = [];
32-
3328
/**
3429
* @var array<string, list<SymbolUsage>>
3530
*/
@@ -67,7 +62,6 @@ class AnalysisResult
6762

6863
/**
6964
* @param array<string, array<string, list<SymbolUsage>>> $usages package => [ classname => usage[] ]
70-
* @param array<string, list<SymbolUsage>> $missingExtensionErrors extension => usages
7165
* @param array<string, list<SymbolUsage>> $unknownClassErrors package => usages
7266
* @param array<string, list<SymbolUsage>> $unknownFunctionErrors package => usages
7367
* @param array<string, array<string, list<SymbolUsage>>> $shadowDependencyErrors package => [ classname => usage[] ]
@@ -80,7 +74,6 @@ public function __construct(
8074
int $scannedFilesCount,
8175
float $elapsedTime,
8276
array $usages,
83-
array $missingExtensionErrors,
8477
array $unknownClassErrors,
8578
array $unknownFunctionErrors,
8679
array $shadowDependencyErrors,
@@ -91,7 +84,6 @@ public function __construct(
9184
)
9285
{
9386
ksort($usages);
94-
ksort($missingExtensionErrors);
9587
ksort($unknownClassErrors);
9688
ksort($unknownFunctionErrors);
9789
ksort($shadowDependencyErrors);
@@ -101,7 +93,6 @@ public function __construct(
10193

10294
$this->scannedFilesCount = $scannedFilesCount;
10395
$this->elapsedTime = $elapsedTime;
104-
$this->missingExtensionsErrors = $missingExtensionErrors;
10596
$this->unknownClassErrors = $unknownClassErrors;
10697
$this->unknownFunctionErrors = $unknownFunctionErrors;
10798

@@ -143,14 +134,6 @@ public function getUsages(): array
143134
return $this->usages;
144135
}
145136

146-
/**
147-
* @return array<string, list<SymbolUsage>>
148-
*/
149-
public function getMissingExtensionsErrors(): array
150-
{
151-
return $this->missingExtensionsErrors;
152-
}
153-
154137
/**
155138
* @return array<string, list<SymbolUsage>>
156139
*/

src/Result/ConsoleFormatter.php

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,23 +117,12 @@ private function printResultErrors(
117117
$unusedIgnores = $result->getUnusedIgnores();
118118

119119
$unknownClassErrors = $result->getUnknownClassErrors();
120-
$missingExtensionErrors = $result->getMissingExtensionsErrors();
121120
$unknownFunctionErrors = $result->getUnknownFunctionErrors();
122121
$shadowDependencyErrors = $result->getShadowDependencyErrors();
123122
$devDependencyInProductionErrors = $result->getDevDependencyInProductionErrors();
124123
$prodDependencyOnlyInDevErrors = $result->getProdDependencyOnlyInDevErrors();
125124
$unusedDependencyErrors = $result->getUnusedDependencyErrors();
126125

127-
if (count($missingExtensionErrors) > 0) {
128-
$hasError = true;
129-
$this->printSymbolBasedErrors(
130-
'Missing extensions!',
131-
'those are used, but not listed in composer.json',
132-
$missingExtensionErrors,
133-
$maxShownUsages
134-
);
135-
}
136-
137126
if (count($unknownClassErrors) > 0) {
138127
$hasError = true;
139128
$this->printSymbolBasedErrors(

0 commit comments

Comments
 (0)