Skip to content

Commit 022da8b

Browse files
committed
Generate transpiled class names dynamically
1 parent 269a02b commit 022da8b

19 files changed

Lines changed: 521 additions & 24 deletions
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2022 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Target\Php\TargetSpecific;
24+
25+
final class ClassName
26+
{
27+
/**
28+
* @var array<string,ClassName>
29+
*/
30+
private static array $instances;
31+
32+
/**
33+
* @var string[]
34+
*/
35+
private array $segments;
36+
37+
private function __construct(private readonly string $fullyQualifiedClassName)
38+
{
39+
$this->segments = explode('\\', $this->fullyQualifiedClassName);
40+
}
41+
42+
public static function fromString(string $string): self
43+
{
44+
return self::$instances[$string] ??= new self($string);
45+
}
46+
47+
public function getFullyQualifiedClassName(): string
48+
{
49+
return $this->fullyQualifiedClassName;
50+
}
51+
52+
public function getNamespace(): string
53+
{
54+
return join('\\', array_slice($this->segments, 0, -1));
55+
}
56+
57+
public function getShortClassName(): string
58+
{
59+
return $this->segments[count($this->segments) - 1];
60+
}
61+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2022 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\ComponentDeclaration;
24+
25+
use PackageFactory\ComponentEngine\Parser\Ast\ComponentDeclarationNode;
26+
use PackageFactory\ComponentEngine\Target\Php\TargetSpecific\ClassName;
27+
28+
interface ComponentDeclarationStrategyInterface
29+
{
30+
public function getClassNameFor(ComponentDeclarationNode $componentDeclarationNode): ClassName;
31+
public function getBaseClassNameFor(ComponentDeclarationNode $componentDeclarationNode): ?ClassName;
32+
}

src/Target/Php/Transpiler/ComponentDeclaration/ComponentDeclarationTranspiler.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,29 +36,38 @@ final class ComponentDeclarationTranspiler
3636
{
3737
public function __construct(
3838
private readonly ScopeInterface $scope,
39-
private readonly ModuleNode $module
39+
private readonly ModuleNode $module,
40+
private readonly ComponentDeclarationStrategyInterface $strategy
4041
) {
4142
}
4243

4344
public function transpile(ComponentDeclarationNode $componentDeclarationNode): string
4445
{
46+
$className = $this->strategy->getClassNameFor($componentDeclarationNode);
47+
$baseClassName = $this->strategy->getBaseClassNameFor($componentDeclarationNode);
48+
4549
$lines = [];
4650

47-
// @TODO: Generate Namespaces Dynamically
4851
$lines[] = '<?php';
4952
$lines[] = '';
5053
$lines[] = 'declare(strict_types=1);';
5154
$lines[] = '';
52-
$lines[] = 'namespace Vendor\\Project\\Component;';
55+
$lines[] = 'namespace ' . $className->getNamespace() . ';';
5356
$lines[] = '';
54-
$lines[] = 'use Vendor\\Project\\BaseClass;';
57+
58+
if ($baseClassName) {
59+
$lines[] = 'use ' . $baseClassName->getFullyQualifiedClassName() . ';';
60+
}
5561

5662
foreach ($this->module->imports->items as $importNode) {
63+
// @TODO: Generate Namespaces Dynamically
5764
$lines[] = 'use Vendor\\Project\\Component\\' . $importNode->name->value . ';';
5865
}
5966

6067
$lines[] = '';
61-
$lines[] = 'final class ' . $componentDeclarationNode->componentName . ' extends BaseClass';
68+
$lines[] = $baseClassName
69+
? 'final class ' . $className->getShortClassName() . ' extends ' . $baseClassName->getShortClassName()
70+
: 'final class ' . $className->getShortClassName();
6271
$lines[] = '{';
6372

6473
if (!$componentDeclarationNode->propertyDeclarations->isEmpty()) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2022 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\EnumDeclaration;
24+
25+
use PackageFactory\ComponentEngine\Parser\Ast\EnumDeclarationNode;
26+
use PackageFactory\ComponentEngine\Target\Php\TargetSpecific\ClassName;
27+
28+
interface EnumDeclarationStrategyInterface
29+
{
30+
public function getClassNameFor(EnumDeclarationNode $enumDeclarationNode): ClassName;
31+
}

src/Target/Php/Transpiler/EnumDeclaration/EnumDeclarationTranspiler.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,24 @@
2626

2727
final class EnumDeclarationTranspiler
2828
{
29+
public function __construct(
30+
private readonly EnumDeclarationStrategyInterface $strategy
31+
) {
32+
}
33+
2934
public function transpile(EnumDeclarationNode $enumDeclarationNode): string
3035
{
36+
$className = $this->strategy->getClassNameFor($enumDeclarationNode);
37+
3138
$lines = [];
3239

33-
// @TODO: Generate Namespaces Dynamically
3440
$lines[] = '<?php';
3541
$lines[] = '';
3642
$lines[] = 'declare(strict_types=1);';
3743
$lines[] = '';
38-
$lines[] = 'namespace Vendor\\Project\\Component;';
44+
$lines[] = 'namespace ' . $className->getNamespace() . ';';
3945
$lines[] = '';
40-
$lines[] = 'enum ' . $enumDeclarationNode->enumName . ' : string';
46+
$lines[] = 'enum ' . $className->getShortClassName() . ' : string';
4147
$lines[] = '{';
4248

4349
foreach ($enumDeclarationNode->memberDeclarations->items as $memberDeclarationNode) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2022 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\Module;
24+
25+
use PackageFactory\ComponentEngine\Parser\Ast\ModuleNode;
26+
use PackageFactory\ComponentEngine\Target\Php\Transpiler\ComponentDeclaration\ComponentDeclarationStrategyInterface;
27+
use PackageFactory\ComponentEngine\Target\Php\Transpiler\EnumDeclaration\EnumDeclarationStrategyInterface;
28+
use PackageFactory\ComponentEngine\Target\Php\Transpiler\StructDeclaration\StructDeclarationStrategyInterface;
29+
30+
interface ModuleStrategyInterface
31+
{
32+
public function getComponentDeclarationStrategyFor(ModuleNode $moduleNode): ComponentDeclarationStrategyInterface;
33+
public function getEnumDeclarationStrategyFor(ModuleNode $moduleNode): EnumDeclarationStrategyInterface;
34+
public function getStructDeclarationStrategyFor(ModuleNode $moduleNode): StructDeclarationStrategyInterface;
35+
}

src/Target/Php/Transpiler/Module/ModuleTranspiler.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ final class ModuleTranspiler
3737
{
3838
public function __construct(
3939
private readonly LoaderInterface $loader,
40-
private readonly ScopeInterface $globalScope
40+
private readonly ScopeInterface $globalScope,
41+
private readonly ModuleStrategyInterface $strategy
4142
) {
4243
}
4344

@@ -51,10 +52,15 @@ public function transpile(ModuleNode $moduleNode): string
5152
moduleNode: $moduleNode,
5253
parentScope: $this->globalScope
5354
),
54-
module: $moduleNode
55+
module: $moduleNode,
56+
strategy: $this->strategy->getComponentDeclarationStrategyFor($moduleNode)
5557
))->transpile($exportNode->declaration),
56-
EnumDeclarationNode::class => (new EnumDeclarationTranspiler())->transpile($exportNode->declaration),
57-
StructDeclarationNode::class => (new StructDeclarationTranspiler())->transpile($exportNode->declaration)
58+
EnumDeclarationNode::class => (new EnumDeclarationTranspiler(
59+
strategy: $this->strategy->getEnumDeclarationStrategyFor($moduleNode)
60+
))->transpile($exportNode->declaration),
61+
StructDeclarationNode::class => (new StructDeclarationTranspiler(
62+
strategy: $this->strategy->getStructDeclarationStrategyFor($moduleNode)
63+
))->transpile($exportNode->declaration)
5864
};
5965
}
6066

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2022 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\StructDeclaration;
24+
25+
use PackageFactory\ComponentEngine\Parser\Ast\StructDeclarationNode;
26+
use PackageFactory\ComponentEngine\Target\Php\TargetSpecific\ClassName;
27+
28+
interface StructDeclarationStrategyInterface
29+
{
30+
public function getClassNameFor(StructDeclarationNode $structDeclarationNode): ClassName;
31+
public function getBaseClassNameFor(StructDeclarationNode $structDeclarationNode): ?ClassName;
32+
}

src/Target/Php/Transpiler/StructDeclaration/StructDeclarationTranspiler.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,33 @@
2828

2929
final class StructDeclarationTranspiler
3030
{
31+
public function __construct(
32+
private readonly StructDeclarationStrategyInterface $strategy
33+
) {
34+
}
35+
3136
public function transpile(StructDeclarationNode $structDeclarationNode): string
3237
{
38+
$className = $this->strategy->getClassNameFor($structDeclarationNode);
39+
$baseClassName = $this->strategy->getBaseClassNameFor($structDeclarationNode);
40+
3341
$lines = [];
3442

35-
// @TODO: Generate Namespaces Dynamically
3643
$lines[] = '<?php';
3744
$lines[] = '';
3845
$lines[] = 'declare(strict_types=1);';
3946
$lines[] = '';
40-
$lines[] = 'namespace Vendor\\Project\\Component;';
47+
$lines[] = 'namespace ' . $className->getNamespace() . ';';
4148
$lines[] = '';
42-
$lines[] = 'use Vendor\\Project\\BaseClass;';
49+
50+
if ($baseClassName) {
51+
$lines[] = 'use ' . $baseClassName->getFullyQualifiedClassName() . ';';
52+
}
53+
4354
$lines[] = '';
44-
$lines[] = 'final class ' . $structDeclarationNode->structName . ' extends BaseClass';
55+
$lines[] = $baseClassName
56+
? 'final class ' . $className->getShortClassName() . ' extends ' . $baseClassName->getShortClassName()
57+
: 'final class ' . $className->getShortClassName();
4558
$lines[] = '{';
4659

4760
if (!$structDeclarationNode->propertyDeclarations->isEmpty()) {

test/Integration/PhpTranspilerIntegrationTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use PackageFactory\ComponentEngine\Parser\Source\Source;
3030
use PackageFactory\ComponentEngine\Test\Unit\TypeSystem\Scope\Fixtures\DummyScope;
3131
use PackageFactory\ComponentEngine\Target\Php\Transpiler\Module\ModuleTranspiler;
32+
use PackageFactory\ComponentEngine\Test\Unit\Target\Php\Transpiler\Module\ModuleTestStrategy;
3233
use PackageFactory\ComponentEngine\TypeSystem\Type\BooleanType\BooleanType;
3334
use PackageFactory\ComponentEngine\TypeSystem\Type\EnumType\EnumStaticType;
3435
use PackageFactory\ComponentEngine\TypeSystem\Type\EnumType\EnumType;
@@ -91,7 +92,8 @@ public function testTranspiler(string $example): void
9192
'enum ButtonType { LINK BUTTON SUBMIT NONE }'
9293
)
9394
)
94-
])
95+
]),
96+
strategy: new ModuleTestStrategy()
9597
);
9698

9799
$this->assertEquals($expected, $transpiler->transpile($module));

0 commit comments

Comments
 (0)