3030
3131abstract class Printer
3232{
33- private SplObjectStorage $ varIds ;
33+ const MODE_DEFAULT = 0b00000 ;
34+ const MODE_RENDER_ATTRIBUTES = 0b00001 ;
3435
3536 private SplQueue $ blockQueue ;
3637
3738 private SplObjectStorage $ blocks ;
3839
39- private bool $ renderAttributes ;
40+ public bool $ renderAttributes = false ;
4041
4142 protected array $ renderers = [];
4243
43- public function __construct (bool $ renderAttributes = false )
44+ public function __construct (int $ mode = self :: MODE_DEFAULT )
4445 {
45- $ this ->renderAttributes = $ renderAttributes ;
46+ if ($ mode & self ::MODE_RENDER_ATTRIBUTES ) {
47+ $ this ->renderAttributes = true ;
48+ }
4649 $ this ->loadRenderers ();
4750 $ this ->reset ();
4851
@@ -115,141 +118,28 @@ public function renderOperand(Operand $var): string
115118 return 'UNKNOWN ' ;
116119 }
117120
118- protected function renderOp (Op $ op ): array
121+ public function renderOp (Op $ op ): array
119122 {
120- $ result = $ op ->getType ();
121-
122- if ($ op instanceof Op \CallableOp) {
123- $ func = $ op ->getFunc ();
124- $ result .= "<' " . $ func ->name . "'> " ;
125- }
126-
127- if ($ op instanceof Op \Expr \Assertion) {
128- $ result .= '< ' . $ this ->renderAssertion ($ op ->assertion ) . '> ' ;
129- }
130-
131- $ result .= $ this ->renderAttributes ($ op ->getAttributes ());
132-
133- if ($ op instanceof Op \AttributableOp) {
134- $ result .= $ this ->renderAttrGroups ($ op );
135- }
136-
137- if ($ op instanceof Op \Stmt \Property || $ op instanceof Op \Stmt \ClassMethod) {
138- $ result .= "\n flags: " . $ this ->indent ($ this ->renderFlags ($ op ));
139- }
140-
141- if ($ op instanceof Op \Stmt \TraitUse) {
142- foreach ($ op ->traits as $ index => $ trait_ ) {
143- $ result .= "\n use[ $ index]: " . $ this ->indent ($ this ->renderOperand ($ trait_ ));
144- }
145- foreach ($ op ->adaptations as $ index => $ adaptation ) {
146- if ($ adaptation instanceof Op \TraitUseAdaptation \Alias) {
147- $ result .= "\n adaptation[ $ index]: Alias " ;
148- if ($ adaptation ->trait != null ) {
149- $ result .= "\n trait: " . $ this ->indent ($ this ->renderOperand ($ adaptation ->trait ));
150- }
151- $ result .= "\n method: " . $ this ->indent ($ this ->renderOperand ($ adaptation ->method ));
152- if ($ adaptation ->newName != null ) {
153- $ result .= "\n newName: " . $ this ->indent ($ this ->renderOperand ($ adaptation ->newName ));
154- }
155- if ($ adaptation ->newModifier != null ) {
156- $ result .= "\n newModifier: " ;
157- if ($ adaptation ->isPublic ()) {
158- $ result .= "public " ;
159- }
160- if ($ adaptation ->isPrivate ()) {
161- $ result .= "private " ;
162- }
163- if ($ adaptation ->isProtected ()) {
164- $ result .= "protected " ;
165- }
166- }
167- } elseif ($ adaptation instanceof Op \TraitUseAdaptation \Precedence) {
168- $ result .= "\n adaptation[ $ index]: Insteadof " ;
169- if ($ adaptation ->trait != null ) {
170- $ result .= "\n trait: " . $ this ->indent ($ this ->renderOperand ($ adaptation ->trait ));
171- }
172- $ result .= "\n method: " . $ this ->indent ($ this ->renderOperand ($ adaptation ->method ));
173- foreach ($ adaptation ->insteadof as $ index2 => $ insteadof ) {
174- $ result .= "\n insteadof[ $ index2]: " . $ this ->indent ($ this ->renderOperand ($ insteadof ));
175- }
176- }
177- }
178- } elseif ($ op instanceof Op \Expr \Include_) {
179- $ result .= "\n type: " . $ this ->indent ($ this ->renderIncludeType ($ op ->type ));
180- }
181-
182- foreach ($ op ->getTypeNames () as $ typeName => $ type ) {
183- if (is_array ($ type )) {
184- foreach ($ type as $ key => $ subType ) {
185- if (! $ subType ) {
186- continue ;
187- }
188- $ result .= "\n {$ typeName }[ {$ key }]: " ;
189- $ result .= $ this ->indent ($ this ->renderType ($ subType ));
190- }
191- } elseif ($ type ) {
192- $ result .= "\n {$ typeName }: " ;
193- $ result .= $ this ->indent ($ this ->renderType ($ type ));
194- }
195- }
196-
197- foreach ($ op ->getVariableNames () as $ varName => $ vars ) {
198- if (is_array ($ vars )) {
199- foreach ($ vars as $ key => $ var ) {
200- if (! $ var ) {
201- continue ;
202- }
203- $ result .= "\n {$ varName }[ {$ key }]: " ;
204- $ result .= $ this ->indent ($ this ->renderOperand ($ var ));
205- }
206- } elseif ($ vars ) {
207- $ result .= "\n {$ varName }: " ;
208- $ result .= $ this ->indent ($ this ->renderOperand ($ vars ));
209- }
210- }
211-
212- $ childBlocks = [];
213- foreach ($ op ->getSubBlocks () as $ blockName => $ sub ) {
214- if (is_array ($ sub )) {
215- foreach ($ sub as $ key => $ subBlock ) {
216- if (! $ subBlock ) {
217- continue ;
218- }
219- $ this ->enqueueBlock ($ subBlock );
220- $ childBlocks [] = [
221- 'block ' => $ subBlock ,
222- 'name ' => $ blockName . '[ ' . $ key . '] ' ,
223- ];
224- }
225- } elseif ($ sub ) {
226- $ this ->enqueueBlock ($ sub );
227- $ childBlocks [] = ['block ' => $ sub , 'name ' => $ blockName ];
123+ foreach ($ this ->renderers as $ renderer ) {
124+ $ result = $ renderer ->renderOp ($ op );
125+ if ($ result !== null ) {
126+ $ kind = $ result ['kind ' ];
127+ $ childblocks = $ result ['childblocks ' ];
128+ return [
129+ 'op ' => $ op ,
130+ 'label ' => $ this ->renderOpLabel ($ result ),
131+ 'childBlocks ' => $ childblocks ,
132+ ];
228133 }
229134 }
230135
231136 return [
232137 'op ' => $ op ,
233- 'label ' => $ result ,
138+ 'label ' => ' UNKNOWN ' ,
234139 'childBlocks ' => $ childBlocks ,
235140 ];
236141 }
237142
238- protected function renderAssertion (Assertion $ assert ): string
239- {
240- $ kind = $ assert ->getKind ();
241- if ($ assert ->value instanceof Operand) {
242- return $ kind . '( ' . $ this ->renderOperand ($ assert ->value ) . ') ' ;
243- }
244- $ combinator = $ assert ->mode === Assertion::MODE_UNION ? '| ' : '& ' ;
245- $ results = [];
246- foreach ($ assert ->value as $ child ) {
247- $ results [] = $ this ->renderAssertion ($ child );
248- }
249-
250- return $ kind . '( ' . implode ($ combinator , $ results ) . ') ' ;
251- }
252-
253143 protected function indent ($ str , $ levels = 1 ): string
254144 {
255145 if ($ levels > 1 ) {
@@ -259,16 +149,14 @@ protected function indent($str, $levels = 1): string
259149 return str_replace ("\n" , "\n " , $ str );
260150 }
261151
262- protected function enqueueBlock (Block $ block ): void
152+ public function enqueueBlock (Block $ block ): void
263153 {
264154 if (! $ this ->blocks ->contains ($ block )) {
265155 $ this ->blocks [$ block ] = count ($ this ->blocks ) + 1 ;
266156 $ this ->blockQueue ->enqueue ($ block );
267157 }
268158 }
269159
270-
271-
272160 protected function render (Func $ func )
273161 {
274162 if (null !== $ func ->cfg ) {
@@ -308,7 +196,7 @@ protected function render(Func $func)
308196 ];
309197 }
310198
311- protected function renderType (?Op \Type $ type ): string
199+ public function renderType (?Op \Type $ type ): string
312200 {
313201 if ($ type instanceof Op \Type \Mixed_) {
314202 return 'mixed ' ;
@@ -341,85 +229,23 @@ protected function renderType(?Op\Type $type): string
341229 throw new LogicException ("Unknown type rendering: " . get_class ($ type ));
342230 }
343231
344- protected function renderIncludeType ( int $ type ): string
232+ public function renderOpLabel ( array $ desc ): string
345233 {
346- switch ($ type ) {
347- case 1 :
348- return "include " ;
349- case 2 :
350- return "include_once " ;
351- case 3 :
352- return "require " ;
353- case 4 :
354- return "require_once " ;
355- default :
356- throw new LogicException ("Unknown include type rendering: " . $ type );
357- }
358- }
359-
360- protected function renderFlags (Op \Stmt $ stmt ): string
361- {
362- $ result = '' ;
363-
364- if ($ stmt instanceof Op \Stmt \Property) {
365- if ($ stmt ->isReadOnly ()) {
366- $ result .= "readonly| " ;
367- }
368- } elseif ($ stmt instanceof Op \Stmt \ClassMethod) {
369- if ($ stmt ->isFinal ()) {
370- $ result .= "final| " ;
371- }
372- if ($ stmt ->isAbstract ()) {
373- $ result .= "abstract| " ;
374- }
375- }
376-
377- if ($ stmt ->isStatic ()) {
378- $ result .= "static| " ;
379- }
380-
381- if ($ stmt ->isProtected ()) {
382- $ result .= "protected " ;
383- } elseif ($ stmt ->isPrivate ()) {
384- $ result .= "private " ;
385- } else {
386- $ result .= "public " ;
387- }
388-
389- return $ result ;
390- }
391-
392- public function renderAttributes (array $ attributes ): string
393- {
394- $ result = '' ;
395- if ($ this ->renderAttributes ) {
396- foreach ($ attributes as $ key => $ value ) {
397- if (is_string ($ value ) || is_numeric ($ value )) {
398- $ result .= "\n attribute[' " . $ key . "']: " . $ value ;
399- }
400- }
401- }
402-
403- return $ result ;
404- }
405-
406- public function renderAttrGroups (Op \AttributableOp $ op ): string
407- {
408- $ result = '' ;
409-
410- foreach ($ op ->getAttributeGroups () as $ indexGroup => $ attrGroup ) {
411- $ result .= "\n attrGroup[ $ indexGroup]: " ;
412- $ result .= $ this ->indent ($ this ->renderAttributes ($ attrGroup ->getAttributes ()));
413- foreach ($ attrGroup ->attrs as $ indexAttr => $ attr ) {
414- $ result .= "\n attr[ $ indexAttr]: " ;
415- $ result .= $ this ->indent ($ this ->renderAttributes ($ attr ->getAttributes ()), 2 );
416- $ result .= "\n name: " . $ this ->renderOperand ($ attr ->name );
417- foreach ($ attr ->args as $ indexArg => $ arg ) {
418- $ result .= "\n args[ $ indexArg]: " . $ this ->renderOperand ($ arg );
234+ $ result = "{$ desc ['kind ' ]}" ;
235+ unset($ desc ['kind ' ], $ desc ['childblocks ' ]);
236+ foreach ($ desc as $ name => $ val ) {
237+ if (is_array ($ val )) {
238+ foreach ($ val as $ v ) {
239+ if (is_array ($ v )) {
240+ $ result .= $ this ->indent ("\n" . implode ("\n" , $ v ));
241+ } else {
242+ $ result .= $ this ->indent ("\n{$ v }" );
243+ }
419244 }
245+ } else {
246+ $ result .= $ this ->indent ("\n{$ val }" );
420247 }
421248 }
422-
423249 return $ result ;
424250 }
425251}
0 commit comments