Skip to content

Commit ecbe189

Browse files
committed
Add ClassBuilder collection - Close #45
1 parent af4396b commit ecbe189

File tree

2 files changed

+210
-0
lines changed

2 files changed

+210
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
3+
/**
4+
* @see https://github.com/open-code-modeling/php-code-ast for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/php-code-ast/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/php-code-ast/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModeling\CodeAst\Builder;
12+
13+
use Countable;
14+
use Iterator;
15+
16+
final class ClassBuilderCollection implements Iterator, Countable
17+
{
18+
/**
19+
* @var array<string, ClassBuilder>
20+
*/
21+
private $items;
22+
23+
public static function fromItems(ClassBuilder ...$classBuilders): self
24+
{
25+
return new self(...$classBuilders);
26+
}
27+
28+
public static function emptyList(): self
29+
{
30+
return new self();
31+
}
32+
33+
private function __construct(ClassBuilder ...$classBuilders)
34+
{
35+
foreach ($classBuilders as $classBuilder) {
36+
$this->items[$this->identifier($classBuilder)] = $classBuilder;
37+
}
38+
}
39+
40+
public function add(ClassBuilder $classBuilder): self
41+
{
42+
$this->items[$this->identifier($classBuilder)] = $classBuilder;
43+
44+
return $this;
45+
}
46+
47+
public function remove(ClassBuilder $classBuilder): self
48+
{
49+
unset($this->items[$this->identifier($classBuilder)]);
50+
51+
return $this;
52+
}
53+
54+
public function contains(ClassBuilder $classBuilder): bool
55+
{
56+
return isset($this->items[$this->identifier($classBuilder)]);
57+
}
58+
59+
public function filter(callable $filter): self
60+
{
61+
return new self(...\array_values(
62+
\array_filter(
63+
$this->items,
64+
static function (ClassBuilder $classBuilder) use ($filter) {
65+
return $filter($classBuilder);
66+
}
67+
)
68+
)
69+
);
70+
}
71+
72+
/**
73+
* @return array<string, ClassBuilder>
74+
*/
75+
public function items(): array
76+
{
77+
return $this->items;
78+
}
79+
80+
public function rewind(): void
81+
{
82+
\reset($this->items);
83+
}
84+
85+
public function current(): ClassBuilder
86+
{
87+
return \current($this->items);
88+
}
89+
90+
public function key(): string
91+
{
92+
return \key($this->items);
93+
}
94+
95+
public function next(): void
96+
{
97+
\next($this->items);
98+
}
99+
100+
public function valid(): bool
101+
{
102+
return \key($this->items) !== null;
103+
}
104+
105+
public function count(): int
106+
{
107+
return \count($this->items);
108+
}
109+
110+
private function identifier(ClassBuilder $classBuilder): string
111+
{
112+
$namespace = $classBuilder->getNamespace() !== null ? ('\\' . $classBuilder->getNamespace()) : '';
113+
$name = $classBuilder->getName() !== null ? ('\\' . $classBuilder->getName()) : '';
114+
115+
$identifier = $namespace . $name;
116+
117+
if ($identifier === '') {
118+
return \spl_object_hash($classBuilder);
119+
}
120+
121+
return $identifier;
122+
}
123+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
/**
4+
* @see https://github.com/open-code-modeling/php-code-ast for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/php-code-ast/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/php-code-ast/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModelingTest\CodeAst\Builder;
12+
13+
use OpenCodeModeling\CodeAst\Builder\ClassBuilder;
14+
use OpenCodeModeling\CodeAst\Builder\ClassBuilderCollection;
15+
use PHPUnit\Framework\TestCase;
16+
17+
final class ClassBuilderCollectionTest extends TestCase
18+
{
19+
/**
20+
* @test
21+
*/
22+
public function it_adds_same_class_builder_not_twice(): void
23+
{
24+
$classBuilder = ClassBuilder::fromScratch('MyClass');
25+
$cut = ClassBuilderCollection::fromItems($classBuilder);
26+
$this->assertCount(1, $cut);
27+
28+
$cut->add($classBuilder);
29+
$this->assertCount(1, $cut);
30+
31+
$items = $cut->items();
32+
$this->assertArrayHasKey('\\MyClass', $items);
33+
}
34+
35+
/**
36+
* @test
37+
*/
38+
public function it_adds_and_removes_class_builder(): void
39+
{
40+
$classBuilderWithoutNamespace = ClassBuilder::fromScratch('MyClass');
41+
$classBuilderNamespace = ClassBuilder::fromScratch('MyClass', 'MyNamespace');
42+
43+
$cut = ClassBuilderCollection::fromItems($classBuilderWithoutNamespace);
44+
$this->assertCount(1, $cut);
45+
46+
$cut->add($classBuilderNamespace);
47+
$this->assertCount(2, $cut);
48+
49+
$items = $cut->items();
50+
$this->assertArrayHasKey('\\MyClass', $items);
51+
$this->assertArrayHasKey('\\MyNamespace\\MyClass', $items);
52+
53+
$i = 0;
54+
55+
foreach ($cut as $item) {
56+
$this->assertInstanceOf(ClassBuilder::class, $item);
57+
if ($i === 0) {
58+
$this->assertSame('MyClass', $item->getName());
59+
$this->assertNull($item->getNamespace());
60+
} else {
61+
$this->assertSame('MyClass', $item->getName());
62+
$this->assertSame('MyNamespace', $item->getNamespace());
63+
}
64+
$i++;
65+
}
66+
67+
$cut->remove($classBuilderNamespace);
68+
$this->assertCount(1, $cut);
69+
70+
$items = $cut->items();
71+
$this->assertArrayHasKey('\\MyClass', $items);
72+
}
73+
74+
/**
75+
* @test
76+
*/
77+
public function it_adds_anonymous_class_builder(): void
78+
{
79+
$classBuilder = ClassBuilder::fromScratch(null);
80+
81+
$cut = ClassBuilderCollection::fromItems($classBuilder);
82+
$this->assertCount(1, $cut);
83+
84+
$items = $cut->items();
85+
$this->assertArrayHasKey(\spl_object_hash($classBuilder), $items);
86+
}
87+
}

0 commit comments

Comments
 (0)