Skip to content

Commit b972c9f

Browse files
Fix test failures by making RestrictImplicitDependencyUsage module-aware
Co-authored-by: robertvansteen <14931924+robertvansteen@users.noreply.github.com>
1 parent d8734ca commit b972c9f

1 file changed

Lines changed: 56 additions & 15 deletions

File tree

‎src/Rules/RestrictImplicitDependencyUsage.php‎

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,26 @@ final class RestrictImplicitDependencyUsage implements RestrictedClassNameUsageE
7070
];
7171

7272
/**
73-
* @var ComposerJson
73+
* @var array<string, ComposerJson>
7474
*/
75-
private array $composerJson;
75+
private array $composerJsonCache = [];
7676

7777
/**
78-
* @var InstalledJson
78+
* @var array<string, InstalledJson>
7979
*/
80-
private array $installedJson;
80+
private array $installedJsonCache = [];
8181

8282
/**
83-
* @var array<string, list<string>>
83+
* @var array<string, array<string, list<string>>>
8484
*/
85-
private array $installedPackages;
85+
private array $installedPackagesCache = [];
8686

8787
/**
88-
* @var list<string>
88+
* @var array<string, list<string>>
8989
*/
90-
private array $allowedNamespaces;
90+
private array $allowedNamespacesCache = [];
91+
92+
private ?string $currentModuleRoot = null;
9193

9294
public function isRestrictedClassNameUsage(ClassReflection $classReflection, Scope $scope, ClassNameUsageLocation $location): ?RestrictedUsage
9395
{
@@ -99,6 +101,9 @@ public function isRestrictedClassNameUsage(ClassReflection $classReflection, Sco
99101
return null;
100102
}
101103

104+
// Set the module root based on the file being analyzed
105+
$this->currentModuleRoot = $this->findModuleRoot($scope->getFile());
106+
102107
if ($this->isInAllowedNamespace($classReflection->getName())) {
103108
return null;
104109
}
@@ -115,14 +120,46 @@ public function isRestrictedClassNameUsage(ClassReflection $classReflection, Sco
115120
);
116121
}
117122

123+
private function findModuleRoot(string $file): string
124+
{
125+
$dir = dirname($file);
126+
while ($dir !== '/') {
127+
if (file_exists($dir . '/composer.json')) {
128+
return $dir;
129+
}
130+
$parent = dirname($dir);
131+
if ($parent === $dir) {
132+
break;
133+
}
134+
$dir = $parent;
135+
}
136+
137+
// Fallback to basepath if no composer.json found
138+
return basepath() ?? getcwd();
139+
}
140+
118141
public function getKey(): string
119142
{
120143
return 'restrict-implicit-dependency-usage';
121144
}
122145

123146
public function getHash(): string
124147
{
125-
return hash(serialize($this->getComposerJson()) . serialize($this->getInstalledJson()), Algorithm::Sha256);
148+
// Hash all cached modules
149+
$hashes = [];
150+
foreach ($this->composerJsonCache as $moduleRoot => $composerJson) {
151+
$installedJson = $this->installedJsonCache[$moduleRoot] ?? [];
152+
$hashes[] = hash(serialize($composerJson) . serialize($installedJson) . $moduleRoot, Algorithm::Sha256);
153+
}
154+
155+
// If no modules cached yet, return a default hash
156+
if (empty($hashes)) {
157+
$moduleRoot = basepath() ?? getcwd();
158+
$this->currentModuleRoot = $moduleRoot;
159+
return hash(serialize($this->getComposerJson()) . serialize($this->getInstalledJson()) . $moduleRoot, Algorithm::Sha256);
160+
}
161+
162+
return hash(implode('', $hashes), Algorithm::Sha256);
126163
}
127164

128165
public function isInGlobalNamespace(string $class): bool
@@ -153,7 +190,8 @@ public function getPackageNameForClass(string $class): ?string
153190
*/
154191
private function getAllowedNamespaces(): array
155192
{
156-
return $this->allowedNamespaces ??= [
193+
$moduleRoot = $this->currentModuleRoot ?? basepath() ?? getcwd();
194+
return $this->allowedNamespacesCache[$moduleRoot] ??= [
157195
...$this->getOwnedNamespaces(),
158196
...$this->getRequiredNamespaces(),
159197
];
@@ -201,7 +239,8 @@ private function getRequiredPackages(): array
201239
*/
202240
private function getInstalledPackagesWithNamespaces(): array
203241
{
204-
return $this->installedPackages ??= [
242+
$moduleRoot = $this->currentModuleRoot ?? basepath() ?? getcwd();
243+
return $this->installedPackagesCache[$moduleRoot] ??= [
205244
...from_entries(array_map(fn(array $package) => [$package['name'], keys($package['autoload']['psr-4'] ?? [])], $this->getInstalledJson()['packages'])),
206245
...$this->getReplacedPackagesWithNamespaces(),
207246
];
@@ -228,28 +267,30 @@ private function getReplacedPackages(): array
228267
*/
229268
private function getInstalledJson(): array
230269
{
231-
return $this->installedJson ??= Type\shape([
270+
$moduleRoot = $this->currentModuleRoot ?? basepath() ?? getcwd();
271+
return $this->installedJsonCache[$moduleRoot] ??= Type\shape([
232272
'packages' => Type\vec(Type\shape([
233273
'name' => Type\string(),
234274
'autoload' => Type\optional(Type\shape([
235275
'psr-4' => Type\optional(Type\dict(Type\string(), Type\union(Type\string(), Type\vec(Type\string())))),
236276
], allow_unknown_fields: true)),
237277
'replace' => Type\optional(Type\dict(Type\string(), Type\string())),
238278
], allow_unknown_fields: true)),
239-
], allow_unknown_fields: true)->assert(decode(read(basepath() . '/vendor/composer/installed.json')));
279+
], allow_unknown_fields: true)->assert(decode(read($moduleRoot . '/vendor/composer/installed.json')));
240280
}
241281

242282
/**
243283
* @return ComposerJson
244284
*/
245285
private function getComposerJson(): array
246286
{
247-
return $this->composerJson ??= Type\shape([
287+
$moduleRoot = $this->currentModuleRoot ?? basepath() ?? getcwd();
288+
return $this->composerJsonCache[$moduleRoot] ??= Type\shape([
248289
'require' => Type\optional(Type\dict(Type\string(), Type\string())),
249290
'require-dev' => Type\optional(Type\dict(Type\string(), Type\string())),
250291
'autoload' => Type\optional(Type\shape([
251292
'psr-4' => Type\optional(Type\dict(Type\string(), Type\union(Type\string(), Type\vec(Type\string())))),
252293
], allow_unknown_fields: true)),
253-
], allow_unknown_fields: true)->assert(decode(read('composer.json')));
294+
], allow_unknown_fields: true)->assert(decode(read($moduleRoot . '/composer.json')));
254295
}
255296
}

0 commit comments

Comments
 (0)