| import '../elements/elements.dart'; | |
| import 'visitor.dart'; | |
| class Printer extends Visitor<Classes, void> { | |
| const Printer(); | |
| @override | |
| void visit(Classes node) { | |
| for (final MapEntry(:key, :value) in node.decls.entries) { | |
| print('<$key>'); | |
| const _ClassPrinter().visit(value); | |
| print('</$key>'); | |
| } | |
| } | |
| } | |
| class _ClassPrinter extends Visitor<ClassDecl, void> { | |
| const _ClassPrinter(); | |
| @override | |
| void visit(ClassDecl node) { | |
| print(' <methods>'); | |
| for (final method in node.methods) { | |
| method.accept(const _MethodPrinter()); | |
| } | |
| print(' </methods>'); | |
| print(' <fields>'); | |
| for (final field in node.fields) { | |
| field.accept(const _FieldPrinter()); | |
| } | |
| print(' </fields>'); | |
| } | |
| } | |
| class _MethodPrinter extends Visitor<Method, void> { | |
| const _MethodPrinter(); | |
| @override | |
| void visit(Method node) { | |
| print(' <${node.finalName}>'); | |
| print(' <return>'); | |
| node.returnType.accept(_TypePrinter(8)); | |
| print(' </return>'); | |
| print(' <params>'); | |
| for (final param in node.params) { | |
| param.accept(const _ParamPrinter()); | |
| } | |
| print(' </params>'); | |
| print(' </${node.finalName}>'); | |
| } | |
| } | |
| class _FieldPrinter extends Visitor<Field, void> { | |
| const _FieldPrinter(); | |
| @override | |
| void visit(Field node) { | |
| print(' <${node.finalName}>'); | |
| node.type.accept(_TypePrinter(6)); | |
| print(' </${node.finalName}>'); | |
| } | |
| } | |
| class _ParamPrinter extends Visitor<Param, void> { | |
| const _ParamPrinter(); | |
| @override | |
| void visit(Param node) { | |
| print(' <${node.finalName}>'); | |
| node.type.accept(_TypePrinter(10)); | |
| print(' </${node.finalName}>'); | |
| } | |
| } | |
| class _TypePrinter extends TypeVisitor<void> { | |
| int depth; | |
| _TypePrinter(this.depth); | |
| void printAnnotation(ReferredType node) { | |
| if (node.annotations != null) { | |
| print('${' ' * depth}<annotations>'); | |
| depth += 2; | |
| for (final annotation in node.annotations!) { | |
| annotation.accept(_AnnotationPrinter(depth)); | |
| } | |
| depth -= 2; | |
| print('${' ' * depth}</annotations>'); | |
| } | |
| } | |
| @override | |
| void visitArrayType(ArrayType node) { | |
| print('${' ' * depth}<array>'); | |
| depth += 2; | |
| node.elementType.accept(this); | |
| printAnnotation(node); | |
| depth -= 2; | |
| print('${' ' * depth}</array>'); | |
| } | |
| @override | |
| void visitDeclaredType(DeclaredType node) { | |
| print('${' ' * depth}<${node.classDecl.binaryName}>'); | |
| depth += 2; | |
| printAnnotation(node); | |
| for (final param in node.params) { | |
| param.accept(this); | |
| } | |
| depth -= 2; | |
| print('${' ' * depth}</${node.classDecl.binaryName}>'); | |
| } | |
| @override | |
| void visitTypeVar(TypeVar node) { | |
| print('${' ' * depth}<${node.name}>'); | |
| print('${' ' * (depth + 1)}<origin>'); | |
| print('${' ' * (depth + 1)}${node.origin.name}'); | |
| print('${' ' * (depth + 1)}</origin>'); | |
| printAnnotation(node); | |
| print('${' ' * depth}</${node.name}>'); | |
| } | |
| @override | |
| void visitPrimitiveType(PrimitiveType node) { | |
| print('${' ' * depth}<${node.name}>'); | |
| printAnnotation(node); | |
| print('${' ' * depth}</${node.name}>'); | |
| } | |
| @override | |
| void visitWildcard(Wildcard node) { | |
| print('${' ' * depth}<*>'); | |
| printAnnotation(node); | |
| print('${' ' * depth}</*>'); | |
| } | |
| @override | |
| void visitNonPrimitiveType(ReferredType node) {} | |
| } | |
| class _AnnotationPrinter extends Visitor<Annotation, void> { | |
| int depth; | |
| _AnnotationPrinter(this.depth); | |
| @override | |
| void visit(Annotation node) { | |
| print('${' ' * depth}</${node.binaryName}>'); | |
| } | |
| } |