Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f753099

Browse files
Generate code from file collection with current file AST support - Close #66
1 parent 0152269 commit f753099

File tree

2 files changed

+486
-0
lines changed

2 files changed

+486
-0
lines changed

‎src/FileCodeGenerator.php

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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;
12+
13+
use OpenCodeModeling\CodeAst\Builder\ClassBuilder;
14+
use OpenCodeModeling\CodeAst\Builder\ClassConstBuilder;
15+
use OpenCodeModeling\CodeAst\Builder\ClassMethodBuilder;
16+
use OpenCodeModeling\CodeAst\Builder\File;
17+
use OpenCodeModeling\CodeAst\Builder\FileCollection;
18+
use OpenCodeModeling\CodeAst\Code\ClassConstGenerator;
19+
use OpenCodeModeling\CodeAst\Package\ClassInfo;
20+
use OpenCodeModeling\CodeAst\Package\ClassInfoList;
21+
use PhpParser\NodeTraverser;
22+
use PhpParser\Parser;
23+
use PhpParser\PrettyPrinterAbstract;
24+
25+
final class FileCodeGenerator
26+
{
27+
private ClassInfoList $classInfoList;
28+
private Parser $parser;
29+
private PrettyPrinterAbstract $printer;
30+
31+
public function __construct(
32+
Parser $parser,
33+
PrettyPrinterAbstract $printer,
34+
ClassInfoList $classInfoList
35+
) {
36+
$this->parser = $parser;
37+
$this->printer = $printer;
38+
$this->classInfoList = $classInfoList;
39+
}
40+
41+
/**
42+
* Returns the generated code of provided file collection
43+
*
44+
* @param FileCollection $fileCollection
45+
* @param callable|null $currentFileAst Callable to return current file AST, if null, file will be overwritten
46+
* @return array<string, string> List of filename => code
47+
*/
48+
public function generateFiles(
49+
FileCollection $fileCollection,
50+
callable $currentFileAst = null
51+
): array {
52+
$files = [];
53+
54+
if ($currentFileAst === null) {
55+
$currentFileAst = static function (File $file, ClassInfo $classInfo) {
56+
return [];
57+
};
58+
}
59+
60+
$previousNamespace = '__invalid//namespace__';
61+
62+
foreach ($fileCollection as $classBuilder) {
63+
if ($previousNamespace !== $classBuilder->getNamespace()) {
64+
$previousNamespace = $classBuilder->getNamespace();
65+
$classInfo = $this->classInfoList->classInfoForNamespace($previousNamespace);
66+
$path = $classInfo->getPath($classBuilder->getNamespace() . '\\' . $classBuilder->getName());
67+
}
68+
$filename = $classInfo->getFilenameFromPathAndName($path, $classBuilder->getName());
69+
70+
$nodeTraverser = new NodeTraverser();
71+
$classBuilder->injectVisitors($nodeTraverser, $this->parser);
72+
73+
$files[$filename] = $this->printer->prettyPrintFile(
74+
$nodeTraverser->traverse($currentFileAst($classBuilder, $classInfo))
75+
);
76+
}
77+
78+
return $files;
79+
}
80+
81+
/**
82+
* Generation of getter methods. Use $skip callable to skip generation e. g. for value objects
83+
*
84+
* @param FileCollection $classBuilderCollection Only ClassBuilder objects are considered
85+
* @param bool $typed Should the generated code be typed
86+
* @param callable $methodNameFilter Filter the property name to your desired method name e.g. with "get" prefix
87+
* @param callable|null $skip Check method to skip getter methods e.g. for value objects
88+
*/
89+
public function addGetterMethodsForProperties(
90+
FileCollection $classBuilderCollection,
91+
bool $typed,
92+
callable $methodNameFilter,
93+
callable $skip = null
94+
): void {
95+
if ($skip === null) {
96+
$skip = static function (ClassBuilder $classBuilder) {
97+
return false;
98+
};
99+
}
100+
101+
foreach ($classBuilderCollection as $classBuilder) {
102+
if (! $classBuilder instanceof ClassBuilder) {
103+
continue;
104+
}
105+
foreach ($classBuilder->getProperties() as $classPropertyBuilder) {
106+
$methodName = ($methodNameFilter)($classPropertyBuilder->getName());
107+
108+
if (true === ($skip)($classBuilder)
109+
|| $classBuilder->hasMethod($methodName)) {
110+
continue 2;
111+
}
112+
$classBuilder->addMethod(
113+
ClassMethodBuilder::fromScratch($methodName, $typed)
114+
->setReturnType($classPropertyBuilder->getType())
115+
->setReturnTypeDocBlockHint($classPropertyBuilder->getTypeDocBlockHint())
116+
->setBody('return $this->' . $classPropertyBuilder->getName() . ';')
117+
);
118+
}
119+
}
120+
}
121+
122+
/**
123+
* Generation of constants for each property. Use $skip callable to skip generation e. g. for value objects
124+
*
125+
* @param FileCollection $fileCollection Only ClassBuilder objects are considered
126+
* @param callable $constantNameFilter Converts the name to a proper class constant name
127+
* @param callable $constantValueFilter Converts the name to a proper class constant value e.g. snake_case or camelCase
128+
* @param callable|null $skip Check method to skip getter methods e.g. for value objects
129+
* @param int $visibility Visibility of the class constant
130+
*/
131+
public function addClassConstantsForProperties(
132+
FileCollection $fileCollection,
133+
callable $constantNameFilter,
134+
callable $constantValueFilter,
135+
callable $skip = null,
136+
int $visibility = ClassConstGenerator::FLAG_PUBLIC
137+
): void {
138+
if ($skip === null) {
139+
$skip = static function (ClassBuilder $classBuilder) {
140+
return false;
141+
};
142+
}
143+
144+
foreach ($fileCollection as $classBuilder) {
145+
if (! $classBuilder instanceof ClassBuilder) {
146+
continue;
147+
}
148+
foreach ($classBuilder->getProperties() as $classPropertyBuilder) {
149+
$constantName = ($constantNameFilter)($classPropertyBuilder->getName());
150+
151+
if (true === ($skip)($classBuilder)
152+
|| $classBuilder->hasConstant($constantName)) {
153+
continue 2;
154+
}
155+
$classBuilder->addConstant(
156+
ClassConstBuilder::fromScratch(
157+
$constantName,
158+
($constantValueFilter)($classPropertyBuilder->getName()),
159+
$visibility
160+
)
161+
);
162+
}
163+
}
164+
}
165+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /