Skip to content

Commit 6ae7f1c

Browse files
committed
WIP: Task: cache ModuleFileLoader::resolveTypeOfImport
previously, every type lookup will result in re-parsing
1 parent 7f90fdc commit 6ae7f1c

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

src/Module/Loader/ModuleFile/ModuleFileLoader.php

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,31 +39,39 @@
3939

4040
final class ModuleFileLoader implements LoaderInterface
4141
{
42+
/** @var array<string, array<string, TypeInterface>> */
43+
private array $cache = [];
44+
4245
public function resolveTypeOfImport(ImportNode $importNode): TypeInterface
4346
{
4447
$pathToImportFrom = $importNode->source->path->resolveRelationTo(
4548
Path::fromString($importNode->path)
4649
);
47-
$source = Source::fromFile($pathToImportFrom->value);
48-
$tokenizer = Tokenizer::fromSource($source);
49-
$module = ModuleNode::fromTokens($tokenizer->getIterator());
50-
$export = $module->exports->get($importNode->name->value);
5150

52-
if ($export === null) {
53-
throw new \Exception(
54-
'@TODO: Module "' . $importNode->path . '" has no exported member "' . $importNode->name->value . '".'
55-
);
51+
if (!isset($this->cache[$pathToImportFrom->value])) {
52+
$source = Source::fromFile($pathToImportFrom->value);
53+
$tokenizer = Tokenizer::fromSource($source);
54+
$module = ModuleNode::fromTokens($tokenizer->getIterator());
55+
$moduleId = ModuleId::fromSource($source);
56+
57+
foreach ($module->exports->items as $export) {
58+
$this->cache[$pathToImportFrom->value][$importNode->name->value] = match ($export->declaration::class) {
59+
ComponentDeclarationNode::class => ComponentType::fromComponentDeclarationNode($export->declaration),
60+
EnumDeclarationNode::class => EnumStaticType::fromModuleIdAndDeclaration(
61+
$moduleId,
62+
$export->declaration,
63+
),
64+
StructDeclarationNode::class => StructType::fromStructDeclarationNode($export->declaration)
65+
};
66+
}
5667
}
5768

58-
$moduleId = ModuleId::fromSource($source);
69+
if ($type = $this->cache[$pathToImportFrom->value][$importNode->name->value] ?? null) {
70+
return $type;
71+
}
5972

60-
return match ($export->declaration::class) {
61-
ComponentDeclarationNode::class => ComponentType::fromComponentDeclarationNode($export->declaration),
62-
EnumDeclarationNode::class => EnumStaticType::fromModuleIdAndDeclaration(
63-
$moduleId,
64-
$export->declaration,
65-
),
66-
StructDeclarationNode::class => StructType::fromStructDeclarationNode($export->declaration)
67-
};
73+
throw new \Exception(
74+
'@TODO: Module "' . $importNode->path . '" has no exported member "' . $importNode->name->value . '".'
75+
);
6876
}
6977
}

src/TypeSystem/Type/EnumType/EnumStaticType.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public function is(TypeInterface $other): bool
7373
return true;
7474
}
7575
if ($other instanceof EnumStaticType) {
76+
// @TODO this check is not needed actually since `EnumStaticType::fromModuleIdAndDeclaration`
77+
// is cached inside \PackageFactory\ComponentEngine\Module\Loader\ModuleFile\ModuleFileLoader::resolveTypeOfImport
78+
// so it "should" always be the same instance ...
7679
return $this->moduleId === $other->moduleId
7780
&& $this->enumName === $other->enumName;
7881
}

test/Unit/TypeSystem/Type/EnumType/EnumStaticTypeTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ public function canBeComparedToOther(): void
152152
$enumDeclarationNode
153153
);
154154

155+
$this->assertTrue($enumStaticType->is($enumStaticType));
156+
155157
$enumStaticType2 = EnumStaticType::fromModuleIdAndDeclaration(
156158
ModuleId::fromString("module-a"),
157159
$enumDeclarationNode

0 commit comments

Comments
 (0)