Skip to content

Commit

Permalink
store resolutions differently
Browse files Browse the repository at this point in the history
  • Loading branch information
klees committed Nov 29, 2023
1 parent 0cd1111 commit cf76f09
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 49 deletions.
24 changes: 1 addition & 23 deletions components/ILIAS/Component/src/Dependencies/In.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ class In implements Dependency

public function __construct(
protected InType $type,
string $name,
protected array $resolved_by = []
string $name
) {
if ($type !== InType::INTERNAL) {
$name = new Name($name);
Expand Down Expand Up @@ -59,25 +58,4 @@ public function addDependant(Out $out): void
$this->dependant[(string) $out] = $out;
$out->addDependency($this);
}

public function addResolution(Out $other): void
{
if ($this->type !== InType::SEEK && count($this->resolved_by) > 0) {
throw new LogicException(
"Dependency of type {$this->type} can only be resolved once."
);
}
$this->resolved_by[] = $other;
$other->addResolves($this);
}

public function getResolvedBy(): array
{
return $this->resolved_by;
}

public function isResolved(): bool
{
return count($this->resolved_by) > 0;
}
}
46 changes: 46 additions & 0 deletions components/ILIAS/Component/src/Dependencies/OfComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class OfComponent implements \ArrayAccess
{
protected Component $component;
protected array $dependencies = [];
protected array $resolutions = [];

public function __construct(Component $component, Dependency ...$ds)
{
Expand Down Expand Up @@ -85,6 +86,51 @@ public function getOutDependenciesOf(OutType $type): \Iterator
}
}

public function addResolution(In $in, array|Out $other)
{
if (!isset($this[(string) $in])) {
throw new \LogicException("Can't add resolution for unknown dependency.");
}
if ($in->getType() !== InType::SEEK) {
if (isset($this->resolution)) {
throw new \LogicException(
"Dependency of type {$in->getType()->value} can only be resolved once."
);
}
if (!($other instanceof Out)) {
throw new \LogicException(
"Dependency of type {$in->getType()->value} can only be resolved by plain Out."
);
}
$this->resolutions[(string) $in] = $other;
} else {
if (!isset($this->resolution)) {
$this->resolutions[(string) $in] = [];
}
if (!is_array($other)) {
throw new \LogicException(
"Dependency of type {$in->getType()->value} can only be resolved by array of Outs."
);
}
$this->resolutions[(string) $in] = $other;
}
}

public function getResolution(In $in): array|Out
{
if (!isset($this->resolutions[(string) $in])) {
throw new \LogicException(
"No resolution for {$in}..."
);
}
return $this->resolutions[(string) $in];
}

public function isResolved(In $in): bool
{
return isset($this->resolutions[(string) $in]);
}

// ArrayAccess

public function offsetExists($dependency_description): bool
Expand Down
6 changes: 0 additions & 6 deletions components/ILIAS/Component/src/Dependencies/Out.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ class Out implements Dependency
protected Name|string $name;
protected array $dependencies = [];
protected ?OfComponent $component = null;
protected array $resolves = [];

public function __construct(
protected OutType $type,
Expand Down Expand Up @@ -91,9 +90,4 @@ public function getDependencies(): array
{
return $this->dependencies;
}

public function addResolves(In $in): void
{
$this->resolves[] = $in;
}
}
6 changes: 3 additions & 3 deletions components/ILIAS/Component/src/Dependencies/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ protected function renderUse(array $component_lookup, OfComponent $component): s
{
$use = "";
foreach ($component->getInDependenciesOf(InType::USE) as $in) {
$r = $in->getResolvedBy()[0];
$r = $component->getResolution($in);
$p = $r->aux["position"];
$o = $component_lookup[$r->getComponent()->getComponentName()];
$use .= "\n" . <<<PHP
Expand All @@ -116,7 +116,7 @@ protected function renderSeek(array $component_lookup, OfComponent $component):
{
$seek = "";
foreach ($component->getInDependenciesOf(InType::SEEK) as $in) {
$rs = $in->getResolvedBy();
$rs = $component->getResolution($in);
$u = [];
$a = "";
foreach ($rs as $r) {
Expand All @@ -142,7 +142,7 @@ protected function renderPull(array $component_lookup, OfComponent $component):
{
$pull = "";
foreach ($component->getInDependenciesOf(InType::PULL) as $in) {
$r = $in->getResolvedBy()[0];
$r = $component->getResolution($in);
$o = $component_lookup[$r->getComponent()->getComponentName()];
$pull .= "\n" . <<<PHP
\$pull[{$in->getName()}::class] = fn() => \$provide_{$o}[{$r->getName()}::class];
Expand Down
16 changes: 7 additions & 9 deletions components/ILIAS/Component/src/Dependencies/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,7 @@ protected function resolveDependenciesSeed(): \Generator
*/
protected function resolveDependency(array $visited, OfComponent $component, In $in): \Generator
{
// Since SEEK-dependencies might in fact have no resolution and this
// is also fine, this would lead to these dependencies be checked
// again, even if that is not necessary. We take this potential
// trade off for some simplicity.
if ($in->isResolved()) {
if ($component->isResolved($in)) {
return;
}

Expand Down Expand Up @@ -134,20 +130,22 @@ protected function resolvePull(array $visited, OfComponent $component, In $in):
}

yield from $this->resolveTransitiveDependencies($visited, $candidate);
$in->addResolution($candidate);
$component->addResolution($in, $candidate);
}

protected function resolveSeek(array $visited, OfComponent $component, In $in): \Generator
{
$resolutions = [];
foreach ($this->components as $other) {
if ($other->offsetExists("CONTRIBUTE: " . $in->getName())) {
// For CONTRIBUTEd, we just use all contributions.
foreach ($other["CONTRIBUTE: " . $in->getName()] as $o) {
yield from $this->resolveTransitiveDependencies($visited, $o);
$in->addResolution($o);
$resolutions[] = $o;
}
}
}
$component->addResolution($in, $resolutions);
}

protected function resolveUse(array $visited, OfComponent $component, In $in): \Generator
Expand All @@ -169,7 +167,7 @@ protected function resolveUse(array $visited, OfComponent $component, In $in): \

if (count($candidates) === 1) {
yield from $this->resolveTransitiveDependencies($visited, $candidates[0]);
$in->addResolution($candidates[0]);
$component->addResolution($in, $candidates[0]);
return;
}

Expand All @@ -183,7 +181,7 @@ protected function resolveUse(array $visited, OfComponent $component, In $in): \
foreach ($candidates as $candidate) {
if ($candidate->aux["class"] === $preferred_class) {
yield from $this->resolveTransitiveDependencies($visited, $candidates[0]);
$in->addResolution($candidate);
$component->addResolution($in, $candidate);
return;
}
}
Expand Down
13 changes: 5 additions & 8 deletions components/ILIAS/Component/tests/Dependencies/ResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ public function testResolvePull(): void

$pull = new D\In(D\InType::PULL, $name);
$provide = new D\Out(D\OutType::PROVIDE, $name, null, []);
$pull->addResolution($provide);

$c1 = new D\OfComponent($component, $pull);
$c1->addResolution($pull, $provide);
$c2 = new D\OfComponent($component, $provide);

$this->assertEquals([$c1, $c2], $result);
Expand Down Expand Up @@ -147,14 +147,12 @@ public function testResolveSeek(): void

$result = $this->resolver->resolveDependencies([], $c1, $c2, $c3);


$seek = new D\In(D\InType::SEEK, $name);
$contribute1 = new D\Out(D\OutType::CONTRIBUTE, $name, null, []);
$contribute2 = new D\Out(D\OutType::CONTRIBUTE, $name, null, []);
$seek->addResolution($contribute1);
$seek->addResolution($contribute2);

$c1 = new D\OfComponent($component, $seek);
$c1->addResolution($seek, [$contribute1, $contribute2]);
$c2 = new D\OfComponent($component, $contribute1);
$c3 = new D\OfComponent($component, $contribute2);

Expand All @@ -177,9 +175,9 @@ public function testResolveUseOneOption(): void

$use = new D\In(D\InType::USE, $name);
$implement = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => "Some\\Class"], []);
$use->addResolution($implement);

$c1 = new D\OfComponent($component, $use);
$c1->addResolution($use, $implement);
$c2 = new D\OfComponent($component, $implement);

$this->assertEquals([$c1, $c2], $result);
Expand Down Expand Up @@ -245,9 +243,9 @@ public function testUseDisambiguateDuplicateSpecific(): void
$use = new D\In(D\InType::USE, $name);
$implement1 = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => "Some\\Class"], []);
$implement2 = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => "Some\\OtherClass"], []);
$use->addResolution($implement2);

$c1 = new D\OfComponent($component, $use);
$c1->addResolution($use, $implement2);
$c2 = new D\OfComponent($component, $implement1);
$c3 = new D\OfComponent($component, $implement2);

Expand Down Expand Up @@ -277,10 +275,9 @@ public function testUseDisambiguateDuplicateGeneric(): void
$use = new D\In(D\InType::USE, $name);
$implement1 = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => "Some\\Class"], []);
$implement2 = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => "Some\\OtherClass"], []);
$use->addResolution($implement2);


$c1 = new D\OfComponent($component, $use);
$c1->addResolution($use, $implement2);
$c2 = new D\OfComponent($component, $implement1);
$c3 = new D\OfComponent($component, $implement2);

Expand Down

0 comments on commit cf76f09

Please sign in to comment.