88
99declare (strict_types=1 );
1010
11- namespace Respect \Dev \CodeGen ;
11+ namespace Respect \Dev \CodeGen \ FluentBuilder ;
1212
13- use DirectoryIterator ;
1413use Nette \PhpGenerator \PhpNamespace ;
1514use Nette \PhpGenerator \Printer ;
1615use ReflectionClass ;
1716use ReflectionParameter ;
18- use Respect \Dev \CodeGen \Attributes \Mixin ;
17+ use Respect \Dev \CodeGen \CodeGenerator ;
18+ use Respect \Dev \CodeGen \Config ;
19+ use Respect \Dev \CodeGen \InterfaceConfig ;
20+ use Respect \Dev \CodeGen \NamespaceScanner ;
1921
2022use function file_get_contents ;
2123use function in_array ;
2224use function is_file ;
2325use function is_readable ;
2426use function ksort ;
25- use function sprintf ;
2627
27- final class MixinGenerator
28+ final class MixinGenerator implements CodeGenerator
2829{
2930 /** @param array<InterfaceConfig> $interfaces */
3031 public function __construct (
31- private readonly string $ sourceDir ,
32- private readonly string $ sourceNamespace ,
33- private readonly string $ outputDir ,
34- private readonly string $ outputNamespace ,
35- private readonly array $ interfaces ,
32+ private readonly Config $ config ,
3633 private readonly MethodBuilder $ methodBuilder = new MethodBuilder (),
37- private readonly OutputFormatter $ outputFormatter = new OutputFormatter () ,
34+ private readonly array $ interfaces = [] ,
3835 ) {
3936 }
4037
4138 /** @return array<string, string> filename => content */
4239 public function generate (): array
4340 {
44- $ validators = $ this ->scanValidators ( );
45- $ prefixes = $ this ->discoverPrefixes ($ validators );
46- $ filters = $ this ->discoverFilters ($ validators );
41+ $ nodes = NamespaceScanner:: scan ( $ this ->config -> sourceDir , $ this -> config -> sourceNamespace );
42+ $ prefixes = $ this ->discoverPrefixes ($ nodes );
43+ $ filters = $ this ->discoverFilters ($ nodes );
4744
4845 $ files = [];
4946
@@ -52,12 +49,12 @@ public function generate(): array
5249
5350 foreach ($ prefixes as $ prefix ) {
5451 $ interfaceName = $ prefix ['name ' ] . $ interfaceConfig ->suffix ;
55- $ prefixInterfaceNames [] = $ this ->outputNamespace . '\\' . $ interfaceName ;
52+ $ prefixInterfaceNames [] = $ this ->config -> outputNamespace . '\\' . $ interfaceName ;
5653
5754 $ this ->generateInterface (
5855 $ interfaceName ,
5956 $ interfaceConfig ,
60- $ validators ,
57+ $ nodes ,
6158 $ filters ,
6259 $ prefix ,
6360 $ files ,
@@ -67,7 +64,7 @@ public function generate(): array
6764 $ this ->generateRootInterface (
6865 $ interfaceConfig ,
6966 $ prefixInterfaceNames ,
70- $ validators ,
67+ $ nodes ,
7168 $ filters ,
7269 $ files ,
7370 );
@@ -76,41 +73,16 @@ public function generate(): array
7673 return $ files ;
7774 }
7875
79- /** @return array<string, ReflectionClass> */
80- private function scanValidators (): array
81- {
82- $ validators = [];
83-
84- foreach (new DirectoryIterator ($ this ->sourceDir ) as $ file ) {
85- if (!$ file ->isFile ()) {
86- continue ;
87- }
88-
89- $ className = $ this ->sourceNamespace . '\\' . $ file ->getBasename ('.php ' );
90- $ reflection = new ReflectionClass ($ className );
91-
92- if ($ reflection ->isAbstract ()) {
93- continue ;
94- }
95-
96- $ validators [$ reflection ->getShortName ()] = $ reflection ;
97- }
98-
99- ksort ($ validators );
100-
101- return $ validators ;
102- }
103-
10476 /**
105- * @param array<string, ReflectionClass> $validators
77+ * @param array<string, ReflectionClass> $nodes
10678 *
10779 * @return array<array{name: string, prefix: string, requireInclusion: bool, prefixParameter: ?ReflectionParameter}>
10880 */
109- private function discoverPrefixes (array $ validators ): array
81+ private function discoverPrefixes (array $ nodes ): array
11082 {
11183 $ prefixes = [];
11284
113- foreach ($ validators as $ reflection ) {
85+ foreach ($ nodes as $ reflection ) {
11486 $ attributes = $ reflection ->getAttributes (Mixin::class);
11587 if ($ attributes === []) {
11688 continue ;
@@ -121,14 +93,13 @@ private function discoverPrefixes(array $validators): array
12193 continue ;
12294 }
12395
96+ $ constructor = $ reflection ->getConstructor ();
12497 $ prefixParameter = null ;
125- if ($ mixin ->prefixParameter ) {
126- $ constructor = $ reflection ->getConstructor ();
127- if ($ constructor !== null ) {
128- $ params = $ constructor ->getParameters ();
129- if ($ params !== []) {
130- $ prefixParameter = $ params [0 ];
131- }
98+
99+ if ($ mixin ->prefixParameter && $ constructor !== null ) {
100+ $ parameters = $ constructor ->getParameters ();
101+ if ($ parameters !== []) {
102+ $ prefixParameter = $ parameters [0 ];
132103 }
133104 }
134105
@@ -146,15 +117,15 @@ private function discoverPrefixes(array $validators): array
146117 }
147118
148119 /**
149- * @param array<string, ReflectionClass> $validators
120+ * @param array<string, ReflectionClass> $nodes
150121 *
151122 * @return array<string, Mixin>
152123 */
153- private function discoverFilters (array $ validators ): array
124+ private function discoverFilters (array $ nodes ): array
154125 {
155126 $ filters = [];
156127
157- foreach ($ validators as $ name => $ reflection ) {
128+ foreach ($ nodes as $ name => $ reflection ) {
158129 $ attributes = $ reflection ->getAttributes (Mixin::class);
159130 if ($ attributes === []) {
160131 continue ;
@@ -167,23 +138,23 @@ private function discoverFilters(array $validators): array
167138 }
168139
169140 /**
170- * @param array<string, ReflectionClass> $validators
141+ * @param array<string, ReflectionClass> $nodes
171142 * @param array<string, Mixin> $filters
172143 * @param array{name: string, prefix: string, requireInclusion: bool, prefixParameter: ?ReflectionParameter} $prefix
173144 * @param array<string, string> $files
174145 */
175146 private function generateInterface (
176147 string $ interfaceName ,
177148 InterfaceConfig $ config ,
178- array $ validators ,
149+ array $ nodes ,
179150 array $ filters ,
180151 array $ prefix ,
181152 array &$ files ,
182153 ): void {
183- $ namespace = new PhpNamespace ($ this ->outputNamespace );
154+ $ namespace = new PhpNamespace ($ this ->config -> outputNamespace );
184155 $ interface = $ namespace ->addInterface ($ interfaceName );
185156
186- foreach ($ validators as $ name => $ reflection ) {
157+ foreach ($ nodes as $ name => $ reflection ) {
187158 $ mixin = $ filters [$ name ] ?? null ;
188159
189160 if ($ prefix ['requireInclusion ' ]) {
@@ -211,27 +182,29 @@ private function generateInterface(
211182
212183 /**
213184 * @param array<string> $prefixInterfaceNames
214- * @param array<string, ReflectionClass> $validators
185+ * @param array<string, ReflectionClass> $nodes
215186 * @param array<string, Mixin> $filters
216187 * @param array<string, string> $files
217188 */
218189 private function generateRootInterface (
219190 InterfaceConfig $ config ,
220191 array $ prefixInterfaceNames ,
221- array $ validators ,
192+ array $ nodes ,
222193 array $ filters ,
223194 array &$ files ,
224195 ): void {
225196 $ interfaceName = $ config ->suffix ;
226- $ namespace = new PhpNamespace ($ this ->outputNamespace );
197+ $ namespace = new PhpNamespace ($ this ->config -> outputNamespace );
227198 $ interface = $ namespace ->addInterface ($ interfaceName );
228199
229200 foreach ($ config ->rootExtends as $ extend ) {
201+ $ namespace ->addUse ($ extend );
230202 $ interface ->addExtend ($ extend );
231203 }
232204
233- foreach ($ prefixInterfaceNames as $ prefixInterface ) {
234- $ interface ->addExtend ($ prefixInterface );
205+ foreach ($ prefixInterfaceNames as $ prefixInterfaceName ) {
206+ $ namespace ->addUse ($ prefixInterfaceName );
207+ $ interface ->addExtend ($ prefixInterfaceName );
235208 }
236209
237210 if ($ config ->rootComment !== null ) {
@@ -242,7 +215,7 @@ private function generateRootInterface(
242215 $ namespace ->addUse ($ use );
243216 }
244217
245- foreach ($ validators as $ reflection ) {
218+ foreach ($ nodes as $ reflection ) {
246219 $ method = $ this ->methodBuilder ->build (
247220 $ namespace ,
248221 $ reflection ,
@@ -260,16 +233,17 @@ private function generateRootInterface(
260233 /** @param array<string, string> $files */
261234 private function addFile (string $ interfaceName , PhpNamespace $ namespace , array &$ files ): void
262235 {
236+ $ filename = $ this ->config ->outputDir . '/ ' . $ interfaceName . '.php ' ;
237+
263238 $ printer = new Printer ();
264239 $ printer ->wrapLength = 300 ;
265240
266- $ filename = sprintf ('%s/%s.php ' , $ this ->outputDir , $ interfaceName );
267241 $ existingContent = '' ;
268242 if (is_file ($ filename ) && is_readable ($ filename )) {
269243 $ existingContent = file_get_contents ($ filename ) ?: '' ;
270244 }
271245
272- $ formattedContent = $ this ->outputFormatter ->format (
246+ $ formattedContent = $ this ->config -> outputFormatter ->format (
273247 $ printer ->printNamespace ($ namespace ),
274248 $ existingContent ,
275249 );
0 commit comments