| Index: lib/src/js/type_printer.dart
|
| diff --git a/lib/src/js/type_printer.dart b/lib/src/js/type_printer.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5f47711e294adab525c5cd6d5abc9f6d252bf135
|
| --- /dev/null
|
| +++ b/lib/src/js/type_printer.dart
|
| @@ -0,0 +1,226 @@
|
| +// 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(String separator, Iterable items, [action(dynamic 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, (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;
|
| + assert(selector is LiteralString);
|
| + if (selector is! LiteralString) {
|
| + out("?");
|
| + return;
|
| + }
|
| + visit(node.receiver);
|
| + out(".");
|
| + out(selector.valueWithoutQuotes);
|
| + }
|
| +
|
| + @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);
|
| + }
|
| + }
|
| + }
|
| +}
|
|
|