Skip to content

Commit da8ddf2

Browse files
committed
Introduce FileGenerator for generating code of classes and interfaces - Close #15
1 parent 0bf1ce8 commit da8ddf2

File tree

4 files changed

+126
-86
lines changed

4 files changed

+126
-86
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"require": {
3535
"php": "^7.4 || ^8.0",
3636
"open-code-modeling/json-schema-to-php": "^0.2.0 || 0.3.x-dev",
37-
"open-code-modeling/php-code-ast": "^0.9.0 || 0.10.x-dev"
37+
"open-code-modeling/php-code-ast": "^0.10.0 || 0.11.x-dev"
3838
},
3939
"require-dev": {
4040
"jangregor/phpstan-prophecy": "^0.8.0",
@@ -43,7 +43,7 @@
4343
"phpspec/prophecy-phpunit": "^2.0",
4444
"phpstan/phpstan": "^0.12.33",
4545
"phpstan/phpstan-strict-rules": "^0.12.4",
46-
"phpunit/phpunit": "^9.2.6",
46+
"phpunit/phpunit": "^9.5.0",
4747
"prooph/php-cs-fixer-config": "^0.3",
4848
"roave/security-advisories": "dev-master",
4949
"squizlabs/php_codesniffer": "^3.4"

src/ClassGenerator.php

Lines changed: 21 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,18 @@
1111
namespace OpenCodeModeling\JsonSchemaToPhpAst;
1212

1313
use OpenCodeModeling\CodeAst\Builder\ClassBuilder;
14-
use OpenCodeModeling\CodeAst\Builder\ClassBuilderCollection;
1514
use OpenCodeModeling\CodeAst\Builder\ClassConstBuilder;
1615
use OpenCodeModeling\CodeAst\Builder\ClassMethodBuilder;
1716
use OpenCodeModeling\CodeAst\Builder\ClassPropertyBuilder;
17+
use OpenCodeModeling\CodeAst\Builder\FileCollection;
1818
use OpenCodeModeling\CodeAst\Code\ClassConstGenerator;
19-
use OpenCodeModeling\CodeAst\Package\ClassInfo;
2019
use OpenCodeModeling\CodeAst\Package\ClassInfoList;
2120
use OpenCodeModeling\JsonSchemaToPhp\Type\ArrayType;
2221
use OpenCodeModeling\JsonSchemaToPhp\Type\ObjectType;
2322
use OpenCodeModeling\JsonSchemaToPhp\Type\ReferenceType;
2423
use OpenCodeModeling\JsonSchemaToPhp\Type\ScalarType;
2524
use OpenCodeModeling\JsonSchemaToPhp\Type\TypeDefinition;
2625
use OpenCodeModeling\JsonSchemaToPhp\Type\TypeSet;
27-
use PhpParser\NodeTraverser;
28-
use PhpParser\Parser;
29-
use PhpParser\PrettyPrinterAbstract;
3026

3127
final class ClassGenerator
3228
{
@@ -57,15 +53,15 @@ public function __construct(
5753

5854
/**
5955
* @param ClassBuilder $classBuilder Main class
60-
* @param ClassBuilderCollection $classBuilderCollection Collection for other classes
56+
* @param FileCollection $fileCollection Collection for other classes
6157
* @param TypeSet $typeSet
6258
* @param string $srcFolder Source folder for namespace imports
6359
* @param string|null $className Class name is used from $classBuilder if not set
6460
* @return void
6561
*/
6662
public function generateClasses(
6763
ClassBuilder $classBuilder,
68-
ClassBuilderCollection $classBuilderCollection,
64+
FileCollection $fileCollection,
6965
TypeSet $typeSet,
7066
string $srcFolder,
7167
string $className = null
@@ -103,7 +99,7 @@ public function generateClasses(
10399

104100
$this->generateClasses(
105101
ClassBuilder::fromScratch($itemClassName, $classNamespace)->setFinal(true),
106-
$classBuilderCollection,
102+
$fileCollection,
107103
$itemTypeSet,
108104
$srcFolder,
109105
$itemPropertyName
@@ -113,7 +109,7 @@ public function generateClasses(
113109
case $propertyType instanceof ObjectType:
114110
$this->generateClasses(
115111
ClassBuilder::fromScratch($propertyClassName, $classNamespace)->setFinal(true),
116-
$classBuilderCollection,
112+
$fileCollection,
117113
$propertyTypeSet,
118114
$srcFolder,
119115
$propertyClassName
@@ -130,7 +126,7 @@ public function generateClasses(
130126
if ($propertyRefType = $propertyType->resolvedType()) {
131127
$this->generateClasses(
132128
ClassBuilder::fromScratch($propertyClassName, $classNamespace)->setFinal(true),
133-
$classBuilderCollection,
129+
$fileCollection,
134130
$propertyRefType,
135131
$srcFolder,
136132
$propertyType->name()
@@ -146,7 +142,7 @@ public function generateClasses(
146142
$classBuilder->addNamespaceImport($classNamespace . '\\' . $propertyClassName);
147143
break;
148144
case $propertyType instanceof ScalarType:
149-
$classBuilderCollection->add(
145+
$fileCollection->add(
150146
$this->generateValueObject($propertyClassName, $classNamespace, $propertyType)
151147
);
152148
$classBuilder->addNamespaceImport($classNamespace . '\\' . $propertyClassName);
@@ -161,17 +157,17 @@ public function generateClasses(
161157
break;
162158
}
163159
}
164-
$classBuilderCollection->add($classBuilder);
160+
$fileCollection->add($classBuilder);
165161
break;
166162
case $type instanceof ScalarType:
167-
$classBuilderCollection->add(
163+
$fileCollection->add(
168164
$this->generateValueObject(($this->classNameFilter)($className), $classNamespace, $type)
169165
);
170166
break;
171167
case $type instanceof ArrayType:
172168
$arrayClassBuilder = $this->generateValueObject(($this->classNameFilter)($className), $classNamespace, $type);
173169
$this->addNamespaceImport($arrayClassBuilder, $type);
174-
$classBuilderCollection->add($arrayClassBuilder);
170+
$fileCollection->add($arrayClassBuilder);
175171
break;
176172
default:
177173
break;
@@ -181,16 +177,19 @@ public function generateClasses(
181177
/**
182178
* Generation of getter methods for value object are skipped.
183179
*
184-
* @param ClassBuilderCollection $classBuilderCollection
180+
* @param FileCollection $classBuilderCollection
185181
* @param bool $typed
186182
* @param callable $methodNameFilter Filter the property name to your desired method name e.g. with get prefix
187183
*/
188184
public function addGetterMethods(
189-
ClassBuilderCollection $classBuilderCollection,
185+
FileCollection $classBuilderCollection,
190186
bool $typed,
191187
callable $methodNameFilter
192188
): void {
193189
foreach ($classBuilderCollection as $classBuilder) {
190+
if (! $classBuilder instanceof ClassBuilder) {
191+
continue;
192+
}
194193
foreach ($classBuilder->getProperties() as $classPropertyBuilder) {
195194
$methodName = ($methodNameFilter)($classPropertyBuilder->getName());
196195

@@ -211,18 +210,21 @@ public function addGetterMethods(
211210
/**
212211
* Generation of constants for value object are skipped.
213212
*
214-
* @param ClassBuilderCollection $classBuilderCollection
213+
* @param FileCollection $fileCollection
215214
* @param callable $constantNameFilter Converts the name to a proper class constant name
216215
* @param callable $constantValueFilter Converts the name to a proper class constant value e.g. snake_case or camelCase
217216
* @param int $visibility Visibility of the class constant
218217
*/
219218
public function addClassConstantsForProperties(
220-
ClassBuilderCollection $classBuilderCollection,
219+
FileCollection $fileCollection,
221220
callable $constantNameFilter,
222221
callable $constantValueFilter,
223222
int $visibility = ClassConstGenerator::FLAG_PUBLIC
224223
): void {
225-
foreach ($classBuilderCollection as $classBuilder) {
224+
foreach ($fileCollection as $classBuilder) {
225+
if (! $classBuilder instanceof ClassBuilder) {
226+
continue;
227+
}
226228
foreach ($classBuilder->getProperties() as $classPropertyBuilder) {
227229
$constantName = ($constantNameFilter)($classPropertyBuilder->getName());
228230

@@ -252,50 +254,6 @@ public function generateValueObject(string $className, string $classNamespace, T
252254
return $classBuilder;
253255
}
254256

255-
/**
256-
* @param ClassBuilderCollection $classBuilderCollection
257-
* @param Parser $parser
258-
* @param PrettyPrinterAbstract $printer
259-
* @param callable|null $currentFileAst Callable to return current file AST, if null, file will be overwritten
260-
* @return array<string, string> List of filename => code
261-
*/
262-
public function generateFiles(
263-
ClassBuilderCollection $classBuilderCollection,
264-
Parser $parser,
265-
PrettyPrinterAbstract $printer,
266-
callable $currentFileAst = null
267-
): array {
268-
$files = [];
269-
270-
if ($currentFileAst === null) {
271-
$currentFileAst = static function (ClassBuilder $classBuilder, ClassInfo $classInfo) {
272-
return [];
273-
};
274-
}
275-
276-
$previousNamespace = '__invalid//namespace__';
277-
278-
foreach ($classBuilderCollection as $classBuilder) {
279-
if ($previousNamespace !== $classBuilder->getNamespace()) {
280-
$previousNamespace = $classBuilder->getNamespace();
281-
$classInfo = $this->classInfoList->classInfoForNamespace($previousNamespace);
282-
$path = $classInfo->getPath($classBuilder->getNamespace() . '\\' . $classBuilder->getName());
283-
}
284-
// @phpstan-ignore-next-line
285-
$filename = $classInfo->getFilenameFromPathAndName($path, $classBuilder->getName());
286-
287-
$nodeTraverser = new NodeTraverser();
288-
$classBuilder->injectVisitors($nodeTraverser, $parser);
289-
290-
$files[$filename] = $printer->prettyPrintFile(
291-
// @phpstan-ignore-next-line
292-
$nodeTraverser->traverse($currentFileAst($classBuilder, $classInfo))
293-
);
294-
}
295-
296-
return $files;
297-
}
298-
299257
private function addNamespaceImport(ClassBuilder $classBuilder, TypeDefinition $typeDefinition): void
300258
{
301259
switch (true) {

src/FileGenerator.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/**
4+
* @see https://github.com/open-code-modeling/json-schema-to-php-ast for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/json-schema-to-php-ast/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/json-schema-to-php-ast/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModeling\JsonSchemaToPhpAst;
12+
13+
use OpenCodeModeling\CodeAst\Builder\File;
14+
use OpenCodeModeling\CodeAst\Builder\FileCollection;
15+
use OpenCodeModeling\CodeAst\Package\ClassInfo;
16+
use OpenCodeModeling\CodeAst\Package\ClassInfoList;
17+
use PhpParser\NodeTraverser;
18+
use PhpParser\Parser;
19+
use PhpParser\PrettyPrinterAbstract;
20+
21+
final class FileGenerator
22+
{
23+
private ClassInfoList $classInfoList;
24+
25+
public function __construct(ClassInfoList $classInfoList)
26+
{
27+
$this->classInfoList = $classInfoList;
28+
}
29+
30+
/**
31+
* @param FileCollection $fileCollection
32+
* @param Parser $parser
33+
* @param PrettyPrinterAbstract $printer
34+
* @param callable|null $currentFileAst Callable to return current file AST, if null, file will be overwritten
35+
* @return array<string, string> List of filename => code
36+
*/
37+
public function generateFiles(
38+
FileCollection $fileCollection,
39+
Parser $parser,
40+
PrettyPrinterAbstract $printer,
41+
callable $currentFileAst = null
42+
): array {
43+
$files = [];
44+
45+
if ($currentFileAst === null) {
46+
$currentFileAst = static function (File $file, ClassInfo $classInfo) {
47+
return [];
48+
};
49+
}
50+
51+
$previousNamespace = '__invalid//namespace__';
52+
53+
foreach ($fileCollection as $classBuilder) {
54+
if ($previousNamespace !== $classBuilder->getNamespace()) {
55+
$previousNamespace = $classBuilder->getNamespace();
56+
$classInfo = $this->classInfoList->classInfoForNamespace($previousNamespace);
57+
$path = $classInfo->getPath($classBuilder->getNamespace() . '\\' . $classBuilder->getName());
58+
}
59+
// @phpstan-ignore-next-line
60+
$filename = $classInfo->getFilenameFromPathAndName($path, $classBuilder->getName());
61+
62+
$nodeTraverser = new NodeTraverser();
63+
$classBuilder->injectVisitors($nodeTraverser, $parser);
64+
65+
$files[$filename] = $printer->prettyPrintFile(
66+
// @phpstan-ignore-next-line
67+
$nodeTraverser->traverse($currentFileAst($classBuilder, $classInfo))
68+
);
69+
}
70+
71+
return $files;
72+
}
73+
}

0 commit comments

Comments
 (0)