| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of js_ast; |
| |
| abstract class _TypePrinterBase implements TypeRefVisitor { |
| void out(String s); |
| void visit(Node node); |
| |
| void outSeparated<T extends Node>(String separator, Iterable<T> items, |
| [action(T item)]) { |
| action ??= visit; |
| var first = true; |
| for (var item in items) { |
| if (first) { |
| first = false; |
| } else { |
| out(separator); |
| } |
| action(item); |
| } |
| } |
| |
| void outTypeArg(Iterable<TypeRef> typeArgs) { |
| if (typeArgs.isNotEmpty) { |
| // TODO(ochafik): Double-check precedence issues when we start emitting |
| // type arguments outside type literals (generic method call, etc). |
| out('<'); |
| outSeparated(", ", typeArgs); |
| out('>'); |
| } |
| } |
| |
| @override |
| visitQualifiedTypeRef(QualifiedTypeRef node) { |
| outSeparated(".", node.path); |
| } |
| } |
| |
| abstract class TypeScriptTypePrinter extends _TypePrinterBase { |
| void _outTypeAnnotation(TypeRef type) { |
| if (type is OptionalTypeRef) { |
| out("?: "); |
| visit(type.type); |
| } else { |
| out(": "); |
| visit(type); |
| } |
| } |
| |
| @override |
| visitGenericTypeRef(GenericTypeRef node) { |
| if (node.rawType is FunctionTypeRef) { |
| outTypeArg(node.typeArgs); |
| visit(node.rawType); |
| } else { |
| visit(node.rawType); |
| outTypeArg(node.typeArgs); |
| } |
| } |
| |
| @override |
| visitArrayTypeRef(ArrayTypeRef node) { |
| if (node.elementType == null) { |
| out("Array"); |
| } else { |
| visit(node.elementType); |
| out("[]"); |
| } |
| } |
| |
| @override |
| visitOptionalTypeRef(OptionalTypeRef node) { |
| visit(node.type); |
| } |
| |
| @override |
| visitRecordTypeRef(RecordTypeRef node) { |
| out('{'); |
| outSeparated(", ", node.types.keys, (Identifier name) { |
| var type = node.types[name]; |
| visit(name); |
| _outTypeAnnotation(type); |
| }); |
| out('}'); |
| } |
| |
| @override |
| visitUnionTypeRef(UnionTypeRef node) { |
| outSeparated("|", node.types.where((t) => !t.isNull)); |
| } |
| |
| @override |
| visitFunctionTypeRef(FunctionTypeRef node) { |
| if (node.returnType == null) { |
| out('Function'); |
| } else { |
| out('('); |
| if (node.paramTypes == null) { |
| out('...any'); |
| } else { |
| outSeparated(", ", node.paramTypes.keys, (Identifier name) { |
| var paramType = node.paramTypes[name]; |
| visit(name); |
| _outTypeAnnotation(paramType); |
| }); |
| } |
| out(') => '); |
| visit(node.returnType); |
| } |
| } |
| |
| @override |
| visitAnyTypeRef(AnyTypeRef node) { |
| out("any"); |
| } |
| |
| @override |
| visitUnknownTypeRef(UnknownTypeRef node) { |
| out("any"); |
| } |
| } |
| |
| class ClosureTypePrinter extends _TypePrinterBase implements NodeVisitor { |
| final _buffer = new StringBuffer(); |
| |
| @override |
| void out(String s) => _buffer.write(s); |
| |
| @override |
| void visit(Node node) => node.accept(this); |
| |
| noSuchMethod(Invocation i) => super.noSuchMethod(i); |
| |
| @override |
| visitGenericTypeRef(GenericTypeRef node) { |
| visit(node.rawType); |
| outTypeArg(node.typeArgs); |
| } |
| |
| @override |
| visitIdentifier(Identifier node) { |
| //out(localNamer.getName(node)); |
| out(node.name); |
| } |
| |
| @override |
| visitAccess(PropertyAccess node) { |
| var selector = node.selector; |
| if (selector is LiteralString) { |
| visit(node.receiver); |
| out("."); |
| out(selector.valueWithoutQuotes); |
| } else { |
| assert(false); |
| out("?"); |
| } |
| } |
| |
| @override |
| toString() => _buffer.toString(); |
| |
| @override |
| visitArrayTypeRef(ArrayTypeRef node) { |
| out("Array"); |
| if (node.elementType != null) { |
| out("<"); |
| visit(node.elementType); |
| out(">"); |
| } |
| } |
| |
| @override |
| visitOptionalTypeRef(OptionalTypeRef node) { |
| visit(node.type); |
| out("="); |
| } |
| |
| @override |
| visitRecordTypeRef(RecordTypeRef node) { |
| out('{'); |
| outSeparated(", ", node.types.keys, (Identifier name) { |
| var type = node.types[name]; |
| visit(name); |
| out(": "); |
| visit(type is OptionalTypeRef ? type.orUndefined() : type); |
| }); |
| out('}'); |
| } |
| |
| @override |
| visitAnyTypeRef(AnyTypeRef node) { |
| out("*"); |
| } |
| |
| @override |
| visitUnknownTypeRef(UnknownTypeRef node) { |
| out("?"); |
| } |
| |
| @override |
| visitUnionTypeRef(UnionTypeRef node) { |
| out("("); |
| outSeparated("|", node.types); |
| out(")"); |
| } |
| |
| @override |
| visitFunctionTypeRef(FunctionTypeRef node) { |
| if (node.returnType == null) { |
| out('Function'); |
| } else { |
| out('function('); |
| if (node.paramTypes == null) { |
| out("...*"); |
| } else { |
| outSeparated(", ", node.paramTypes.values); |
| } |
| out(')'); |
| if (node.returnType != null) { |
| out(":"); |
| visit(node.returnType); |
| } |
| } |
| } |
| } |