mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:31:20 +00:00
Remove experimental closure support from dartdevc
Change-Id: Id171cbfd220c4b504f13183ffdcad581c44fb41a Reviewed-on: https://dart-review.googlesource.com/64826 Commit-Queue: Jenny Messerly <jmesserly@google.com> Reviewed-by: Bob Nystrom <rnystrom@google.com>
This commit is contained in:
parent
2420134b23
commit
875abcea39
|
@ -35,7 +35,6 @@ import 'package:analyzer/src/task/strong/ast_properties.dart';
|
|||
import 'package:path/path.dart' as path;
|
||||
import 'package:source_span/source_span.dart' show SourceLocation;
|
||||
|
||||
import '../closure/closure_annotator.dart' show ClosureAnnotator;
|
||||
import '../compiler/js_metalet.dart' as JS;
|
||||
import '../compiler/js_names.dart' as JS;
|
||||
import '../compiler/js_utils.dart' as JS;
|
||||
|
@ -49,7 +48,6 @@ import 'element_helpers.dart';
|
|||
import 'error_helpers.dart';
|
||||
import 'extension_types.dart' show ExtensionTypeSet;
|
||||
import 'js_interop.dart';
|
||||
import 'js_typeref_codegen.dart' show JSTypeRefCodegen;
|
||||
import 'js_typerep.dart';
|
||||
import 'module_compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile;
|
||||
import 'nullable_type_inference.dart' show NullableTypeInference;
|
||||
|
@ -74,11 +72,7 @@ import 'type_utilities.dart';
|
|||
// expressions (which result in JS.Expression) and statements
|
||||
// (which result in (JS.Statement).
|
||||
class CodeGenerator extends Object
|
||||
with
|
||||
ClosureAnnotator,
|
||||
JSTypeRefCodegen,
|
||||
NullableTypeInference,
|
||||
SharedCompiler<LibraryElement>
|
||||
with NullableTypeInference, SharedCompiler<LibraryElement>
|
||||
implements AstVisitor<JS.Node> {
|
||||
final AnalysisContext context;
|
||||
final SummaryDataStore summaryData;
|
||||
|
@ -871,13 +865,10 @@ class CodeGenerator extends Object
|
|||
}
|
||||
}
|
||||
|
||||
JS.Expression body = closureAnnotate(
|
||||
runtimeCall('typedef(#, () => #)', [
|
||||
js.string(element.name, "'"),
|
||||
_emitFunctionType(type, nameType: false)
|
||||
]),
|
||||
element,
|
||||
node);
|
||||
JS.Expression body = runtimeCall('typedef(#, () => #)', [
|
||||
js.string(element.name, "'"),
|
||||
_emitFunctionType(type, nameType: false)
|
||||
]);
|
||||
|
||||
if (typeFormals.isNotEmpty) {
|
||||
return _defineClassTypeArguments(element, typeFormals,
|
||||
|
@ -1231,19 +1222,6 @@ class CodeGenerator extends Object
|
|||
.toList(growable: false);
|
||||
}
|
||||
|
||||
/// Emits a field declaration for TypeScript & Closure's ES6_TYPED
|
||||
/// (e.g. `class Foo { i: string; }`)
|
||||
JS.VariableDeclarationList _emitTypeScriptField(FieldElement field) {
|
||||
return JS.VariableDeclarationList(field.isStatic ? 'static' : null, [
|
||||
JS.VariableInitialization(
|
||||
JS.Identifier(
|
||||
// TODO(ochafik): use a refactored _emitMemberName instead.
|
||||
field.name,
|
||||
type: emitTypeRef(field.type)),
|
||||
null)
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
JS.Statement visitEnumDeclaration(EnumDeclaration node) {
|
||||
return _emitClassDeclaration(node, node.element, []);
|
||||
|
@ -1279,19 +1257,12 @@ class CodeGenerator extends Object
|
|||
JS.Expression className,
|
||||
JS.Expression heritage,
|
||||
List<JS.Method> methods) {
|
||||
var typeParams = _emitTypeFormals(classElem.typeParameters);
|
||||
|
||||
var jsFields = options.closure
|
||||
? classElem.fields.map(_emitTypeScriptField).toList()
|
||||
: null;
|
||||
if (classElem.typeParameters.isNotEmpty) {
|
||||
return JS.ClassExpression(className as JS.Identifier, heritage, methods,
|
||||
typeParams: typeParams, fields: jsFields)
|
||||
return JS.ClassExpression(className as JS.Identifier, heritage, methods)
|
||||
.toStatement();
|
||||
}
|
||||
var classExpr = JS.ClassExpression(
|
||||
JS.TemporaryId(classElem.name), heritage, methods,
|
||||
typeParams: typeParams, fields: jsFields);
|
||||
var classExpr =
|
||||
JS.ClassExpression(JS.TemporaryId(classElem.name), heritage, methods);
|
||||
return js.statement('# = #;', [className, classExpr]);
|
||||
}
|
||||
|
||||
|
@ -1648,8 +1619,7 @@ class CodeGenerator extends Object
|
|||
body.add(js.statement(
|
||||
'return super.#(#)(#);', [name, typeFormals, jsParams]));
|
||||
}
|
||||
var fn = JS.Fun(jsParams, JS.Block(body),
|
||||
typeParams: typeFormals, returnType: emitTypeRef(type.returnType));
|
||||
var fn = JS.Fun(jsParams, JS.Block(body));
|
||||
methods.add(JS.Method(name, fn));
|
||||
} else {
|
||||
throw StateError(
|
||||
|
@ -1664,7 +1634,6 @@ class CodeGenerator extends Object
|
|||
if (isUnsupportedFactoryConstructor(node)) return null;
|
||||
|
||||
var element = node.element;
|
||||
var returnType = emitTypeRef(element.returnType);
|
||||
var name = _constructorName(element.name);
|
||||
JS.Fun fun;
|
||||
|
||||
|
@ -1687,8 +1656,7 @@ class CodeGenerator extends Object
|
|||
js.statement('return $newKeyword #(#)',
|
||||
[visitConstructorName(redirect), params])
|
||||
..sourceInformation = _nodeStart(redirect)
|
||||
]),
|
||||
returnType: returnType);
|
||||
]));
|
||||
} else {
|
||||
// Normal factory constructor
|
||||
var body = <JS.Statement>[];
|
||||
|
@ -1697,16 +1665,13 @@ class CodeGenerator extends Object
|
|||
body.add(_visitStatement(node.body));
|
||||
|
||||
var params = _emitParameters(node.parameters?.parameters);
|
||||
fun = JS.Fun(params, JS.Block(body), returnType: returnType);
|
||||
fun = JS.Fun(params, JS.Block(body));
|
||||
}
|
||||
|
||||
_currentFunction = savedFunction;
|
||||
|
||||
return closureAnnotate(
|
||||
JS.Method(name, fun, isStatic: true)
|
||||
..sourceInformation = _functionEnd(node),
|
||||
element,
|
||||
node);
|
||||
return JS.Method(name, fun, isStatic: true)
|
||||
..sourceInformation = _functionEnd(node);
|
||||
}
|
||||
|
||||
/// Given a class C that implements method M from interface I, but does not
|
||||
|
@ -1784,7 +1749,7 @@ class CodeGenerator extends Object
|
|||
return JS.Method(
|
||||
_declareMemberName(method,
|
||||
useExtension: _extensionTypes.isNativeClass(type.element)),
|
||||
JS.Fun(fnArgs, fnBlock, typeParams: typeParams),
|
||||
JS.Fun(fnArgs, fnBlock),
|
||||
isGetter: method is PropertyAccessorElement && method.isGetter,
|
||||
isSetter: method is PropertyAccessorElement && method.isSetter,
|
||||
isStatic: false);
|
||||
|
@ -2630,14 +2595,11 @@ class CodeGenerator extends Object
|
|||
fn = _emitFunction(node.element, node.parameters, node.body);
|
||||
}
|
||||
|
||||
return closureAnnotate(
|
||||
JS.Method(_declareMemberName(node.element), fn,
|
||||
isGetter: node.isGetter,
|
||||
isSetter: node.isSetter,
|
||||
isStatic: node.isStatic)
|
||||
..sourceInformation = _functionEnd(node),
|
||||
node.element,
|
||||
node);
|
||||
return JS.Method(_declareMemberName(node.element), fn,
|
||||
isGetter: node.isGetter,
|
||||
isSetter: node.isSetter,
|
||||
isStatic: node.isStatic)
|
||||
..sourceInformation = _functionEnd(node);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -2683,8 +2645,7 @@ class CodeGenerator extends Object
|
|||
|
||||
var element = resolutionMap.elementDeclaredByFunctionDeclaration(node);
|
||||
var nameExpr = _emitTopLevelName(element);
|
||||
body.add(
|
||||
closureAnnotate(js.statement('# = #', [nameExpr, fn]), element, node));
|
||||
body.add(js.statement('# = #', [nameExpr, fn]));
|
||||
// Function types of top-level/static functions are only needed when
|
||||
// dart:mirrors is enabled.
|
||||
// TODO(jmesserly): do we even need this for mirrors, since statics are not
|
||||
|
@ -2718,13 +2679,10 @@ class CodeGenerator extends Object
|
|||
|
||||
JS.Method _emitTopLevelProperty(FunctionDeclaration node) {
|
||||
var name = node.name.name;
|
||||
return closureAnnotate(
|
||||
JS.Method(_propertyName(name),
|
||||
_emitFunctionExpression(node.functionExpression),
|
||||
isGetter: node.isGetter, isSetter: node.isSetter)
|
||||
..sourceInformation = _functionEnd(node),
|
||||
node.element,
|
||||
node);
|
||||
return JS.Method(
|
||||
_propertyName(name), _emitFunctionExpression(node.functionExpression),
|
||||
isGetter: node.isGetter, isSetter: node.isSetter)
|
||||
..sourceInformation = _functionEnd(node);
|
||||
}
|
||||
|
||||
bool _executesAtTopLevel(AstNode node) {
|
||||
|
@ -2788,8 +2746,7 @@ class CodeGenerator extends Object
|
|||
|
||||
// Convert `function(...) { ... }` to `(...) => ...`
|
||||
// This is for readability, but it also ensures correct `this` binding.
|
||||
return JS.ArrowFun(f.params, body,
|
||||
typeParams: f.typeParams, returnType: f.returnType);
|
||||
return JS.ArrowFun(f.params, body);
|
||||
}
|
||||
|
||||
/// Emits a non-arrow FunctionExpression node.
|
||||
|
@ -2824,8 +2781,7 @@ class CodeGenerator extends Object
|
|||
]);
|
||||
|
||||
code = super.exitFunction(element.name, formals, code);
|
||||
return JS.Fun(formals, code,
|
||||
typeParams: typeFormals, returnType: emitTypeRef(type.returnType));
|
||||
return JS.Fun(formals, code);
|
||||
}
|
||||
|
||||
JS.Block _emitFunctionBody(ExecutableElement element,
|
||||
|
@ -2897,8 +2853,7 @@ class CodeGenerator extends Object
|
|||
// TODO(jmesserly): this will emit argument initializers (for default
|
||||
// values) inside the generator function body. Is that the best place?
|
||||
var jsBody = _emitFunctionBody(element, parameters, body);
|
||||
var genFn = JS.Fun(jsParams, jsBody,
|
||||
isGenerator: true, returnType: emitTypeRef(returnType));
|
||||
var genFn = JS.Fun(jsParams, jsBody, isGenerator: true);
|
||||
|
||||
// Name the function if possible, to get better stack traces.
|
||||
var name = element.name;
|
||||
|
@ -3132,9 +3087,8 @@ class CodeGenerator extends Object
|
|||
return JS.PropertyAccess(target, member);
|
||||
}
|
||||
|
||||
JS.Identifier _emitVariableDef(SimpleIdentifier id, {JS.TypeRef type}) {
|
||||
return JS.Identifier(id.name, type: type)
|
||||
..sourceInformation = _nodeStart(id);
|
||||
JS.Identifier _emitVariableDef(SimpleIdentifier id) {
|
||||
return JS.Identifier(id.name)..sourceInformation = _nodeStart(id);
|
||||
}
|
||||
|
||||
/// Returns `true` if the type name referred to by [node] is used in a
|
||||
|
@ -3175,8 +3129,7 @@ class CodeGenerator extends Object
|
|||
element, () => JS.TemporaryId(element.name.substring(1)));
|
||||
}
|
||||
|
||||
var type = declaration ? emitTypeRef(element.type) : null;
|
||||
return JS.Identifier(element.name, type: type);
|
||||
return JS.Identifier(element.name);
|
||||
}
|
||||
|
||||
List<Annotation> _parameterMetadata(FormalParameter p) =>
|
||||
|
@ -4272,8 +4225,7 @@ class CodeGenerator extends Object
|
|||
return null;
|
||||
}
|
||||
|
||||
var name =
|
||||
_emitVariableDef(node.name, type: emitTypeRef(node.element.type));
|
||||
var name = _emitVariableDef(node.name);
|
||||
return JS.VariableInitialization(
|
||||
name, _visitInitializer(node.initializer, node.element));
|
||||
}
|
||||
|
@ -4300,13 +4252,10 @@ class CodeGenerator extends Object
|
|||
_isJSInvocation(init) ||
|
||||
init is InstanceCreationExpression &&
|
||||
isSdkInternalRuntime(init.staticElement.library)) {
|
||||
moduleItems.add(closureAnnotate(
|
||||
js.statement('# = #;', [
|
||||
_emitTopLevelName(field.element),
|
||||
_visitInitializer(field.initializer, field.element)
|
||||
]),
|
||||
field.element,
|
||||
field));
|
||||
moduleItems.add(js.statement('# = #;', [
|
||||
_emitTopLevelName(field.element),
|
||||
_visitInitializer(field.initializer, field.element)
|
||||
]));
|
||||
} else {
|
||||
lazyFields.add(field);
|
||||
}
|
||||
|
@ -4332,41 +4281,24 @@ class CodeGenerator extends Object
|
|||
for (var node in fields) {
|
||||
var element = node.element;
|
||||
var access = emitFieldName(element);
|
||||
accessors.add(closureAnnotate(
|
||||
JS.Method(
|
||||
access,
|
||||
js.call('function() { return #; }',
|
||||
_visitInitializer(node.initializer, element)) as JS.Fun,
|
||||
isGetter: true)
|
||||
..sourceInformation =
|
||||
_hoverComment(JS.PropertyAccess(objExpr, access), node.name),
|
||||
_findAccessor(element, getter: true),
|
||||
node));
|
||||
accessors.add(JS.Method(
|
||||
access,
|
||||
js.call('function() { return #; }',
|
||||
_visitInitializer(node.initializer, element)) as JS.Fun,
|
||||
isGetter: true)
|
||||
..sourceInformation =
|
||||
_hoverComment(JS.PropertyAccess(objExpr, access), node.name));
|
||||
|
||||
// TODO(jmesserly): currently uses a dummy setter to indicate writable.
|
||||
if (!node.isFinal && !node.isConst) {
|
||||
accessors.add(closureAnnotate(
|
||||
JS.Method(access, js.call('function(_) {}') as JS.Fun,
|
||||
isSetter: true),
|
||||
_findAccessor(element, getter: false),
|
||||
node));
|
||||
accessors.add(JS.Method(access, js.call('function(_) {}') as JS.Fun,
|
||||
isSetter: true));
|
||||
}
|
||||
}
|
||||
|
||||
return runtimeStatement('defineLazy(#, { # })', [objExpr, accessors]);
|
||||
}
|
||||
|
||||
PropertyAccessorElement _findAccessor(VariableElement element,
|
||||
{bool getter}) {
|
||||
var parent = element.enclosingElement;
|
||||
if (parent is ClassElement) {
|
||||
return getter
|
||||
? parent.getGetter(element.name)
|
||||
: parent.getSetter(element.name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
JS.Expression _emitConstructorName(DartType type, String name) {
|
||||
return _emitJSInterop(type.element) ??
|
||||
JS.PropertyAccess(_emitConstructorAccess(type), _constructorName(name));
|
||||
|
@ -6219,15 +6151,6 @@ class CodeGenerator extends Object
|
|||
() => JS.TemporaryId(jsLibraryName(_libraryRoot, library)));
|
||||
}
|
||||
|
||||
T closureAnnotate<T extends JS.Node>(
|
||||
T node, Element element, AnnotatedNode original) {
|
||||
if (options.closure) {
|
||||
node.closureAnnotation =
|
||||
closureAnnotationFor(node, original, element, namedArgumentTemp.name);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/// Return true if this is one of the methods/properties on all Dart Objects
|
||||
/// (toString, hashCode, noSuchMethod, runtimeType).
|
||||
///
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
|
||||
|
||||
import '../js_ast/js_ast.dart' as JS;
|
||||
import 'module_compiler.dart' show CompilerOptions;
|
||||
import 'js_interop.dart';
|
||||
|
||||
/// Mixin with logic to generate [TypeRef]s out of [DartType]s.
|
||||
abstract class JSTypeRefCodegen {
|
||||
final _resolved = <DartType, JS.TypeRef>{};
|
||||
|
||||
// Mixin dependencies:
|
||||
CompilerOptions get options;
|
||||
TypeProvider get types;
|
||||
LibraryElement get dartJSLibrary;
|
||||
JS.Identifier get namedArgumentTemp;
|
||||
JS.Identifier emitLibraryName(LibraryElement e);
|
||||
|
||||
/// Finds the qualified path to the type.
|
||||
JS.TypeRef _emitTopLevelTypeRef(DartType type) {
|
||||
var e = type.element;
|
||||
return JS.TypeRef.qualified([
|
||||
emitLibraryName(e.library),
|
||||
JS.Identifier(getJSExportName(e) ?? e.name)
|
||||
]);
|
||||
}
|
||||
|
||||
JS.TypeRef emitTypeRef(DartType type) {
|
||||
if (!options.closure) return null;
|
||||
|
||||
return _resolved.putIfAbsent(type, () {
|
||||
if (type == null) JS.TypeRef.unknown();
|
||||
// TODO(ochafik): Consider calling _loader.declareBeforeUse(type.element).
|
||||
if (type.isBottom || type.isDynamic) JS.TypeRef.any();
|
||||
if (type.isVoid) return JS.TypeRef.void_();
|
||||
|
||||
if (type == types.intType) return JS.TypeRef.number().orNull();
|
||||
if (type == types.numType) return JS.TypeRef.number().orNull();
|
||||
if (type == types.doubleType) return JS.TypeRef.number().orNull();
|
||||
if (type == types.boolType) return JS.TypeRef.boolean().orNull();
|
||||
if (type == types.stringType) return JS.TypeRef.string();
|
||||
|
||||
if (type is TypeParameterType) return JS.TypeRef.named(type.name);
|
||||
if (type is ParameterizedType) {
|
||||
JS.TypeRef rawType;
|
||||
if (type is FunctionType && type.name == null) {
|
||||
var args = <JS.Identifier, JS.TypeRef>{};
|
||||
for (var param in type.parameters) {
|
||||
if (param.isNamed) break;
|
||||
var type = emitTypeRef(param.type);
|
||||
args[JS.Identifier(param.name)] =
|
||||
param.isPositional ? type.toOptional() : type;
|
||||
}
|
||||
var namedParamType = emitNamedParamsArgType(type.parameters);
|
||||
if (namedParamType != null) {
|
||||
args[namedArgumentTemp] = namedParamType.toOptional();
|
||||
}
|
||||
|
||||
rawType = JS.TypeRef.function(emitTypeRef(type.returnType), args);
|
||||
} else {
|
||||
var jsTypeRef = _getDartJsTypeRef(type);
|
||||
if (jsTypeRef != null) return jsTypeRef;
|
||||
|
||||
rawType = _emitTopLevelTypeRef(type);
|
||||
}
|
||||
var typeArgs = _getOwnTypeArguments(type).map(emitTypeRef);
|
||||
return typeArgs.isEmpty
|
||||
? rawType
|
||||
: JS.TypeRef.generic(rawType, typeArgs);
|
||||
}
|
||||
return JS.TypeRef.unknown();
|
||||
});
|
||||
}
|
||||
|
||||
JS.TypeRef emitNamedParamsArgType(Iterable<ParameterElement> params) {
|
||||
if (!options.closure) return null;
|
||||
|
||||
var namedArgs = <JS.Identifier, JS.TypeRef>{};
|
||||
for (ParameterElement param in params) {
|
||||
if (param.isPositional) continue;
|
||||
namedArgs[JS.Identifier(param.name)] =
|
||||
emitTypeRef(param.type).toOptional();
|
||||
}
|
||||
if (namedArgs.isEmpty) return null;
|
||||
return JS.TypeRef.record(namedArgs);
|
||||
}
|
||||
|
||||
/// Gets the "own" type arguments of [type].
|
||||
///
|
||||
/// Method argument with adhoc unnamed [FunctionType] inherit any type params
|
||||
/// from their enclosing class:
|
||||
///
|
||||
/// class Foo<T> {
|
||||
/// void method(f()); // f has [T] as type arguments,
|
||||
/// } // but [] as its "own" type arguments.
|
||||
Iterable<DartType> _getOwnTypeArguments(ParameterizedType type) sync* {
|
||||
for (int i = 0, n = type.typeParameters.length; i < n; i++) {
|
||||
if (type.typeParameters[i].enclosingElement == type.element) {
|
||||
yield type.typeArguments[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Special treatment of types from dart:js
|
||||
/// TODO(ochafik): Is this the right thing to do? And what about package:js?
|
||||
JS.TypeRef _getDartJsTypeRef(DartType type) {
|
||||
if (type.element.library == dartJSLibrary) {
|
||||
switch (type.name) {
|
||||
case 'JsArray':
|
||||
return JS.TypeRef.array(
|
||||
type is InterfaceType && type.typeArguments.length == 1
|
||||
? emitTypeRef(type.typeArguments.single)
|
||||
: null);
|
||||
case 'JsObject':
|
||||
return JS.TypeRef.object();
|
||||
case 'JsFunction':
|
||||
return JS.TypeRef.function();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -6,8 +6,7 @@ import 'dart:collection' show HashSet, Queue;
|
|||
import 'dart:convert' show json;
|
||||
import 'dart:io' show File;
|
||||
|
||||
import 'package:analyzer/analyzer.dart'
|
||||
show AnalysisError, CompilationUnit, ErrorSeverity;
|
||||
import 'package:analyzer/analyzer.dart' show AnalysisError, CompilationUnit;
|
||||
import 'package:analyzer/dart/analysis/declared_variables.dart';
|
||||
import 'package:analyzer/dart/element/element.dart'
|
||||
show LibraryElement, UriReferencedElement;
|
||||
|
@ -16,7 +15,6 @@ import 'package:analyzer/file_system/physical_file_system.dart'
|
|||
show PhysicalResourceProvider;
|
||||
import 'package:analyzer/src/context/builder.dart' show ContextBuilder;
|
||||
import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
|
||||
import 'package:analyzer/src/error/codes.dart' show StaticTypeWarningCode;
|
||||
import 'package:analyzer/src/generated/engine.dart'
|
||||
show AnalysisContext, AnalysisEngine;
|
||||
import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
|
||||
|
@ -129,21 +127,6 @@ class ModuleCompiler {
|
|||
return ModuleCompiler._(context, summaryData);
|
||||
}
|
||||
|
||||
bool _isFatalError(AnalysisError e, CompilerOptions options) {
|
||||
if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false;
|
||||
|
||||
// These errors are not fatal in the REPL compile mode as we
|
||||
// allow access to private members across library boundaries
|
||||
// and those accesses will show up as undefined members unless
|
||||
// additional analyzer changes are made to support them.
|
||||
// TODO(jacobr): consider checking that the identifier name
|
||||
// referenced by the error is private.
|
||||
return !options.replCompile ||
|
||||
(e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER &&
|
||||
e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER &&
|
||||
e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD);
|
||||
}
|
||||
|
||||
/// Compiles a single Dart build unit into a JavaScript module.
|
||||
///
|
||||
/// *Warning* - this may require resolving the entire world.
|
||||
|
@ -263,9 +246,6 @@ class CompilerOptions {
|
|||
/// to private members across library boundaries.
|
||||
final bool replCompile;
|
||||
|
||||
/// Whether to emit Closure Compiler-friendly code.
|
||||
final bool closure;
|
||||
|
||||
/// Mapping from absolute file paths to bazel short path to substitute in
|
||||
/// source maps.
|
||||
final Map<String, String> bazelMapping;
|
||||
|
@ -284,7 +264,6 @@ class CompilerOptions {
|
|||
this.replCompile = false,
|
||||
this.emitMetadata = false,
|
||||
this.enableAsserts = true,
|
||||
this.closure = false,
|
||||
this.bazelMapping = const {},
|
||||
this.summaryOutPath});
|
||||
|
||||
|
@ -298,7 +277,6 @@ class CompilerOptions {
|
|||
replCompile = args['repl-compile'] as bool,
|
||||
emitMetadata = args['emit-metadata'] as bool,
|
||||
enableAsserts = args['enable-asserts'] as bool,
|
||||
closure = args['closure-experimental'] as bool,
|
||||
bazelMapping =
|
||||
_parseBazelMappings(args['bazel-mapping'] as List<String>),
|
||||
summaryOutPath = args['summary-out'] as String;
|
||||
|
@ -432,9 +410,7 @@ class JSModuleFile {
|
|||
JSModuleCode getCode(ModuleFormat format, String jsUrl, String mapUrl,
|
||||
{bool singleOutFile = false}) {
|
||||
var opts = JS.JavaScriptPrintingOptions(
|
||||
emitTypes: options.closure,
|
||||
allowKeywordsInProperties: true,
|
||||
allowSingleLineIfStatements: true);
|
||||
allowKeywordsInProperties: true, allowSingleLineIfStatements: true);
|
||||
JS.SimpleJavaScriptPrintingContext printer;
|
||||
SourceMapBuilder sourceMap;
|
||||
if (options.sourceMap) {
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
import '../js_ast/js_ast.dart' as JS show TypeRef, ClosureTypePrinter;
|
||||
|
||||
/// Set of closure annotations that can be [toString]ed to a single JsDoc comment.
|
||||
/// See https://developers.google.com/closure/compiler/docs/js-for-compiler
|
||||
///
|
||||
/// TODO(ochafik): Support inclusion of 'normal' comments (including @param comments).
|
||||
class ClosureAnnotation {
|
||||
final String comment;
|
||||
final bool isConst;
|
||||
final bool isConstructor;
|
||||
final bool isFinal;
|
||||
final bool isNoCollapse;
|
||||
final bool isNoSideEffects;
|
||||
final bool isOverride;
|
||||
final bool isPrivate;
|
||||
final bool isProtected;
|
||||
final bool isStruct;
|
||||
final bool isTypedef;
|
||||
final JS.TypeRef lendsToType;
|
||||
final JS.TypeRef returnType;
|
||||
final JS.TypeRef superType;
|
||||
final JS.TypeRef thisType;
|
||||
final JS.TypeRef throwsType;
|
||||
final JS.TypeRef type;
|
||||
final List<JS.TypeRef> interfaces;
|
||||
final List<String> templates;
|
||||
final Map<String, JS.TypeRef> paramTypes;
|
||||
|
||||
ClosureAnnotation(
|
||||
{this.comment,
|
||||
this.interfaces = const [],
|
||||
this.isConst = false,
|
||||
this.isConstructor = false,
|
||||
this.isFinal = false,
|
||||
this.isNoCollapse = false,
|
||||
this.isNoSideEffects = false,
|
||||
this.isOverride = false,
|
||||
this.isPrivate = false,
|
||||
this.isProtected = false,
|
||||
this.isStruct = false,
|
||||
this.isTypedef = false,
|
||||
this.lendsToType,
|
||||
this.paramTypes = const {},
|
||||
this.returnType,
|
||||
this.superType,
|
||||
this.templates = const [],
|
||||
this.thisType,
|
||||
this.throwsType,
|
||||
this.type});
|
||||
|
||||
@override
|
||||
int get hashCode => _cachedString.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is ClosureAnnotation && _cachedString == other._cachedString;
|
||||
|
||||
@override
|
||||
String toString([String indent = '']) =>
|
||||
_cachedString.replaceAll('\n', '\n$indent');
|
||||
|
||||
String _print(JS.TypeRef t) => (JS.ClosureTypePrinter()..visit(t)).toString();
|
||||
|
||||
String __cachedString;
|
||||
String get _cachedString {
|
||||
if (__cachedString == null) {
|
||||
bool isNonWildcard(JS.TypeRef t) => t != null && !t.isAny && !t.isUnknown;
|
||||
|
||||
var lines = <String>[];
|
||||
if (comment != null) lines.addAll(comment.split('\n'));
|
||||
if (templates != null && templates.isNotEmpty) {
|
||||
lines.add('@template ${templates.join(', ')}');
|
||||
}
|
||||
if (thisType != null) lines.add('@this {${_print(thisType)}}');
|
||||
if (isOverride) lines.add('@override');
|
||||
if (isNoSideEffects) lines.add('@nosideeffects');
|
||||
if (isNoCollapse) lines.add('@nocollapse');
|
||||
if (lendsToType != null) lines.add('@lends {${_print(lendsToType)}}');
|
||||
|
||||
{
|
||||
var typeHolders = <String>[];
|
||||
if (isPrivate) typeHolders.add('@private');
|
||||
if (isProtected) typeHolders.add('@protected');
|
||||
if (isFinal) typeHolders.add('@final');
|
||||
if (isConst) typeHolders.add('@const');
|
||||
if (isTypedef) typeHolders.add('@typedef');
|
||||
if (isNonWildcard(type)) {
|
||||
if (typeHolders.isEmpty) typeHolders.add('@type');
|
||||
typeHolders.add('{${_print(type)}}');
|
||||
}
|
||||
if (!typeHolders.isEmpty) lines.add(typeHolders.join(' '));
|
||||
}
|
||||
|
||||
{
|
||||
List constructorLine = [];
|
||||
if (isConstructor) constructorLine.add('@constructor');
|
||||
if (isStruct) constructorLine.add('@struct');
|
||||
if (isNonWildcard(superType)) {
|
||||
constructorLine.add('@extends {${_print(superType)}}');
|
||||
}
|
||||
|
||||
if (constructorLine.isNotEmpty) lines.add(constructorLine.join(' '));
|
||||
}
|
||||
|
||||
if (interfaces != null) {
|
||||
for (var interface in interfaces) {
|
||||
if (isNonWildcard(interface))
|
||||
lines.add('@implements {${_print(interface)}}');
|
||||
}
|
||||
}
|
||||
|
||||
if (paramTypes != null) {
|
||||
paramTypes.forEach((String paramName, JS.TypeRef paramType) {
|
||||
// Must output params even with wildcard type.
|
||||
lines.add('@param {${_print(paramType)}} $paramName');
|
||||
});
|
||||
}
|
||||
if (isNonWildcard(returnType))
|
||||
lines.add('@return {${_print(returnType)}}');
|
||||
if (isNonWildcard(throwsType))
|
||||
lines.add('@throws {${_print(throwsType)}}');
|
||||
|
||||
if (lines.length == 0) return '';
|
||||
if (lines.length == 1) return '/** ${lines.single} */';
|
||||
__cachedString = '/**\n' + lines.map((l) => ' * $l').join('\n') + '\n */';
|
||||
}
|
||||
return __cachedString;
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
|
||||
|
||||
import '../js_ast/js_ast.dart' as JS show Node, TypeRef;
|
||||
|
||||
import 'closure_annotation.dart';
|
||||
|
||||
/// Mixin that can generate [ClosureAnnotation]s for Dart elements and types.
|
||||
abstract class ClosureAnnotator {
|
||||
TypeProvider get types;
|
||||
|
||||
JS.TypeRef emitTypeRef(DartType type);
|
||||
|
||||
// TODO(ochafik): Handle destructured params when Closure supports it.
|
||||
ClosureAnnotation closureAnnotationFor(JS.Node node, AnnotatedNode original,
|
||||
Element e, String namedArgsMapName) {
|
||||
// Note: Dart and Closure privacy are not compatible: don't set `isPrivate: e.isPrivate`.
|
||||
return ClosureAnnotation(
|
||||
comment: original?.documentationComment?.toSource(),
|
||||
// Note: we don't set isConst here because Closure's constness and
|
||||
// Dart's are not really compatible.
|
||||
isFinal: e is VariableElement && (e.isFinal || e.isConst),
|
||||
type: e is VariableElement
|
||||
? emitTypeRef(e.type /*, forceTypeDefExpansion: true*/)
|
||||
: null,
|
||||
superType: e is ClassElement ? emitTypeRef(e.supertype) : null,
|
||||
interfaces:
|
||||
e is ClassElement ? e.interfaces.map(emitTypeRef).toList() : null,
|
||||
isOverride: e.isOverride,
|
||||
isTypedef: e is FunctionTypeAliasElement);
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
/// Poor-man's representation of a Closure type.
|
||||
/// See https://developers.google.com/closure/compiler/docs/js-for-compiler
|
||||
///
|
||||
/// The goal here is not to completely support Closure's type system, but to
|
||||
/// be able to generate just the types needed for DDC's JS output.
|
||||
///
|
||||
/// TODO(ochafik): Consider convergence with TypeScript, which has no nullability-awareness
|
||||
/// (see http://www.typescriptlang.org/Handbook).
|
||||
class ClosureType {
|
||||
static const ClosureType _ALL = ClosureType._("*");
|
||||
static const ClosureType _UNKNOWN = ClosureType._("?");
|
||||
|
||||
final String _representation;
|
||||
final bool isNullable;
|
||||
|
||||
const ClosureType._(this._representation, {this.isNullable = true});
|
||||
|
||||
bool get isAll => _representation == "*";
|
||||
bool get isUnknown => _representation == "?";
|
||||
|
||||
@override
|
||||
toString() => _representation;
|
||||
|
||||
factory ClosureType.all() => _ALL;
|
||||
factory ClosureType.unknown() => _UNKNOWN;
|
||||
|
||||
factory ClosureType.record(Map<String, ClosureType> fieldTypes) {
|
||||
var entries = <String>[];
|
||||
fieldTypes.forEach((n, t) => entries.add('$n: $t'));
|
||||
return ClosureType._('{${entries.join(', ')}}');
|
||||
}
|
||||
factory ClosureType.function(
|
||||
[List<ClosureType> paramTypes, ClosureType returnType]) {
|
||||
if (paramTypes == null && returnType == null) {
|
||||
return ClosureType.type("Function");
|
||||
}
|
||||
var suffix = returnType == null ? '' : ':$returnType';
|
||||
return ClosureType._(
|
||||
'function(${paramTypes == null ? '...*' : paramTypes.join(', ')})$suffix');
|
||||
}
|
||||
|
||||
factory ClosureType.map([ClosureType keyType, ClosureType valueType]) =>
|
||||
ClosureType._("Object<${keyType ?? _ALL}, ${valueType ?? _ALL}>");
|
||||
|
||||
factory ClosureType.type([String className = "Object"]) =>
|
||||
ClosureType._(className);
|
||||
|
||||
factory ClosureType.array([ClosureType componentType]) =>
|
||||
ClosureType._("Array<${componentType ?? _ALL}>");
|
||||
|
||||
factory ClosureType.undefined() =>
|
||||
ClosureType._("undefined", isNullable: false);
|
||||
factory ClosureType.number() => ClosureType._("number", isNullable: false);
|
||||
factory ClosureType.boolean() => ClosureType._("boolean", isNullable: false);
|
||||
factory ClosureType.string() => ClosureType._("string");
|
||||
|
||||
ClosureType toOptional() => ClosureType._("$this=");
|
||||
|
||||
ClosureType toNullable() => isNullable
|
||||
? this
|
||||
: ClosureType._(
|
||||
_representation.startsWith('!')
|
||||
? _representation.substring(1)
|
||||
: "?$this",
|
||||
isNullable: true);
|
||||
|
||||
ClosureType toNonNullable() => !isNullable
|
||||
? this
|
||||
: ClosureType._(
|
||||
_representation.startsWith('?')
|
||||
? _representation.substring(1)
|
||||
: "!$this",
|
||||
isNullable: false);
|
||||
|
||||
/// TODO(ochafik): See which optimizations make sense here (it could be that `(*|undefined)`
|
||||
/// cannot be optimized to `*` when used to model optional record fields).
|
||||
ClosureType or(ClosureType other) => ClosureType._("($this|$other)",
|
||||
isNullable: isNullable || other.isNullable);
|
||||
|
||||
ClosureType orUndefined() => or(ClosureType.undefined());
|
||||
}
|
|
@ -17,8 +17,7 @@ Fun simplifyPassThroughArrowFunCallBody(Fun fn) {
|
|||
innerFun.params.isEmpty) {
|
||||
var body = innerFun.body;
|
||||
if (body is Block) {
|
||||
return Fun(fn.params, body,
|
||||
typeParams: fn.typeParams, returnType: fn.returnType);
|
||||
return Fun(fn.params, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,8 @@ library js_ast;
|
|||
|
||||
import 'precedence.dart';
|
||||
import 'characters.dart' as charCodes;
|
||||
import '../closure/closure_annotation.dart';
|
||||
|
||||
part 'nodes.dart';
|
||||
part 'builder.dart';
|
||||
part 'js_types.dart';
|
||||
part 'printer.dart';
|
||||
part 'template.dart';
|
||||
part 'type_printer.dart';
|
||||
|
|
|
@ -1,202 +0,0 @@
|
|||
// 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;
|
||||
|
||||
final _any = AnyTypeRef._();
|
||||
final _unknown = UnknownTypeRef._();
|
||||
final _null = NullTypeRef();
|
||||
|
||||
/// JavaScript type reference, designed to support a subset of the type systems
|
||||
/// of the Closure Compiler and TypeScript:
|
||||
/// - https://developers.google.com/closure/compiler/docs/js-for-compiler#types
|
||||
/// - https://github.com/Microsoft/TypeScript/blob/v1.8.0-beta/doc/spec.md#3
|
||||
///
|
||||
/// Note that some subtleties like "nullability" or "optionality" are handled
|
||||
/// using unions (with a [NullTypeRef] or with an "undefined" named typeref).
|
||||
/// Also, primitives aren't modeled differently than named / qualified types,
|
||||
/// as it brings little value for now. Primitive-specific type formatting is
|
||||
/// handled by the type printers (for instance, the knowledge that
|
||||
/// `number|null` is just `number` in TypeScript, and is `number?` in Closure).
|
||||
abstract class TypeRef extends Expression {
|
||||
int get precedenceLevel => PRIMARY;
|
||||
|
||||
TypeRef();
|
||||
|
||||
factory TypeRef.any() => _any;
|
||||
|
||||
factory TypeRef.void_() => TypeRef.named('void');
|
||||
|
||||
factory TypeRef.unknown() => _unknown;
|
||||
|
||||
factory TypeRef.generic(TypeRef rawType, Iterable<TypeRef> typeArgs) {
|
||||
if (typeArgs.isEmpty) {
|
||||
throw ArgumentError.value(typeArgs, "typeArgs", "is empty");
|
||||
}
|
||||
return GenericTypeRef(rawType, typeArgs.toList());
|
||||
}
|
||||
|
||||
factory TypeRef.array([TypeRef elementType]) => ArrayTypeRef(elementType);
|
||||
|
||||
factory TypeRef.object([TypeRef keyType, TypeRef valueType]) {
|
||||
// TODO(ochafik): Roll out a dedicated ObjectTypeRef?
|
||||
var rawType = TypeRef.named('Object');
|
||||
return keyType == null && valueType == null
|
||||
? rawType
|
||||
: GenericTypeRef(rawType, [keyType ?? _any, valueType ?? _any]);
|
||||
}
|
||||
|
||||
factory TypeRef.function(
|
||||
[TypeRef returnType, Map<Identifier, TypeRef> paramTypes]) =>
|
||||
FunctionTypeRef(returnType, paramTypes);
|
||||
|
||||
factory TypeRef.record(Map<Identifier, TypeRef> types) =>
|
||||
RecordTypeRef(types);
|
||||
|
||||
factory TypeRef.string() => TypeRef.named('string');
|
||||
|
||||
factory TypeRef.number() => TypeRef.named('number');
|
||||
|
||||
factory TypeRef.undefined() => TypeRef.named('undefined');
|
||||
|
||||
factory TypeRef.boolean() => TypeRef.named('boolean');
|
||||
|
||||
factory TypeRef.qualified(List<Identifier> path) => QualifiedTypeRef(path);
|
||||
|
||||
factory TypeRef.named(String name) =>
|
||||
TypeRef.qualified(<Identifier>[Identifier(name)]);
|
||||
|
||||
bool get isAny => this is AnyTypeRef;
|
||||
bool get isUnknown => this is UnknownTypeRef;
|
||||
bool get isNull => this is NullTypeRef;
|
||||
|
||||
TypeRef or(TypeRef other) => UnionTypeRef([this, other]);
|
||||
|
||||
TypeRef orUndefined() => or(TypeRef.undefined());
|
||||
TypeRef orNull() => or(_null);
|
||||
|
||||
TypeRef toOptional() => OptionalTypeRef(this);
|
||||
}
|
||||
|
||||
class AnyTypeRef extends TypeRef {
|
||||
AnyTypeRef._() : super();
|
||||
|
||||
factory AnyTypeRef() => _any;
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitAnyTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {}
|
||||
_clone() => AnyTypeRef();
|
||||
}
|
||||
|
||||
class NullTypeRef extends QualifiedTypeRef {
|
||||
NullTypeRef() : super([Identifier("null")]);
|
||||
_clone() => NullTypeRef();
|
||||
}
|
||||
|
||||
class UnknownTypeRef extends TypeRef {
|
||||
UnknownTypeRef._() : super();
|
||||
|
||||
factory UnknownTypeRef() => _unknown;
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitUnknownTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {}
|
||||
_clone() => UnknownTypeRef();
|
||||
}
|
||||
|
||||
class QualifiedTypeRef extends TypeRef {
|
||||
final List<Identifier> path;
|
||||
QualifiedTypeRef(this.path);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitQualifiedTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) =>
|
||||
path.forEach((p) => p.accept(visitor));
|
||||
_clone() => QualifiedTypeRef(path);
|
||||
}
|
||||
|
||||
class ArrayTypeRef extends TypeRef {
|
||||
final TypeRef elementType;
|
||||
ArrayTypeRef(this.elementType);
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitArrayTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {
|
||||
elementType.accept(visitor);
|
||||
}
|
||||
|
||||
_clone() => ArrayTypeRef(elementType);
|
||||
}
|
||||
|
||||
class GenericTypeRef extends TypeRef {
|
||||
final TypeRef rawType;
|
||||
final List<TypeRef> typeArgs;
|
||||
GenericTypeRef(this.rawType, this.typeArgs);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitGenericTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {
|
||||
rawType.accept(visitor);
|
||||
typeArgs.forEach((p) => p.accept(visitor));
|
||||
}
|
||||
|
||||
_clone() => GenericTypeRef(rawType, typeArgs);
|
||||
}
|
||||
|
||||
class UnionTypeRef extends TypeRef {
|
||||
final List<TypeRef> types;
|
||||
UnionTypeRef(this.types);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitUnionTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {
|
||||
types.forEach((p) => p.accept(visitor));
|
||||
}
|
||||
|
||||
_clone() => UnionTypeRef(types);
|
||||
|
||||
@override
|
||||
TypeRef or(TypeRef other) {
|
||||
if (types.contains(other)) return this;
|
||||
return UnionTypeRef([]
|
||||
..addAll(types)
|
||||
..add(other));
|
||||
}
|
||||
}
|
||||
|
||||
class OptionalTypeRef extends TypeRef {
|
||||
final TypeRef type;
|
||||
OptionalTypeRef(this.type);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitOptionalTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {
|
||||
type.accept(visitor);
|
||||
}
|
||||
|
||||
_clone() => OptionalTypeRef(type);
|
||||
|
||||
@override
|
||||
TypeRef orUndefined() => this;
|
||||
}
|
||||
|
||||
class RecordTypeRef extends TypeRef {
|
||||
final Map<Identifier, TypeRef> types;
|
||||
RecordTypeRef(this.types);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitRecordTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {
|
||||
types.values.forEach((p) => p.accept(visitor));
|
||||
}
|
||||
|
||||
_clone() => RecordTypeRef(types);
|
||||
}
|
||||
|
||||
class FunctionTypeRef extends TypeRef {
|
||||
final TypeRef returnType;
|
||||
final Map<Identifier, TypeRef> paramTypes;
|
||||
FunctionTypeRef(this.returnType, this.paramTypes);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitFunctionTypeRef(this);
|
||||
void visitChildren(NodeVisitor visitor) {
|
||||
returnType.accept(visitor);
|
||||
paramTypes.forEach((n, t) {
|
||||
n.accept(visitor);
|
||||
t.accept(visitor);
|
||||
});
|
||||
}
|
||||
|
||||
_clone() => FunctionTypeRef(returnType, paramTypes);
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
part of js_ast;
|
||||
|
||||
abstract class NodeVisitor<T> implements TypeRefVisitor<T> {
|
||||
abstract class NodeVisitor<T> {
|
||||
T visitProgram(Program node);
|
||||
|
||||
T visitBlock(Block node);
|
||||
|
@ -95,18 +95,6 @@ abstract class NodeVisitor<T> implements TypeRefVisitor<T> {
|
|||
T visitSimpleBindingPattern(SimpleBindingPattern node);
|
||||
}
|
||||
|
||||
abstract class TypeRefVisitor<T> {
|
||||
T visitQualifiedTypeRef(QualifiedTypeRef node);
|
||||
T visitGenericTypeRef(GenericTypeRef node);
|
||||
T visitUnionTypeRef(UnionTypeRef node);
|
||||
T visitRecordTypeRef(RecordTypeRef node);
|
||||
T visitOptionalTypeRef(OptionalTypeRef node);
|
||||
T visitFunctionTypeRef(FunctionTypeRef node);
|
||||
T visitAnyTypeRef(AnyTypeRef node);
|
||||
T visitUnknownTypeRef(UnknownTypeRef node);
|
||||
T visitArrayTypeRef(ArrayTypeRef node);
|
||||
}
|
||||
|
||||
class BaseVisitor<T> implements NodeVisitor<T> {
|
||||
T visitNode(Node node) {
|
||||
node.visitChildren(this);
|
||||
|
@ -229,17 +217,6 @@ class BaseVisitor<T> implements NodeVisitor<T> {
|
|||
visitBindingPattern(node);
|
||||
T visitDestructuredVariable(DestructuredVariable node) => visitNode(node);
|
||||
T visitSimpleBindingPattern(SimpleBindingPattern node) => visitNode(node);
|
||||
|
||||
T visitTypeRef(TypeRef node) => visitNode(node);
|
||||
T visitQualifiedTypeRef(QualifiedTypeRef node) => visitTypeRef(node);
|
||||
T visitGenericTypeRef(GenericTypeRef node) => visitTypeRef(node);
|
||||
T visitOptionalTypeRef(OptionalTypeRef node) => visitTypeRef(node);
|
||||
T visitRecordTypeRef(RecordTypeRef node) => visitTypeRef(node);
|
||||
T visitUnionTypeRef(UnionTypeRef node) => visitTypeRef(node);
|
||||
T visitFunctionTypeRef(FunctionTypeRef node) => visitTypeRef(node);
|
||||
T visitAnyTypeRef(AnyTypeRef node) => visitTypeRef(node);
|
||||
T visitUnknownTypeRef(UnknownTypeRef node) => visitTypeRef(node);
|
||||
T visitArrayTypeRef(ArrayTypeRef node) => visitTypeRef(node);
|
||||
}
|
||||
|
||||
abstract class Node {
|
||||
|
@ -247,9 +224,6 @@ abstract class Node {
|
|||
/// setting this after construction.
|
||||
Object sourceInformation;
|
||||
|
||||
/// Closure annotation of this node.
|
||||
ClosureAnnotation closureAnnotation;
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor);
|
||||
void visitChildren(NodeVisitor visitor);
|
||||
|
||||
|
@ -892,13 +866,9 @@ class DestructuredVariable extends Expression implements Parameter {
|
|||
|
||||
final BindingPattern structure;
|
||||
final Expression defaultValue;
|
||||
final TypeRef type;
|
||||
|
||||
DestructuredVariable(
|
||||
{this.name,
|
||||
this.property,
|
||||
this.structure,
|
||||
this.defaultValue,
|
||||
this.type}) {
|
||||
{this.name, this.property, this.structure, this.defaultValue}) {
|
||||
assert(name != null || structure != null);
|
||||
}
|
||||
|
||||
|
@ -1177,16 +1147,13 @@ class Postfix extends Expression {
|
|||
int get precedenceLevel => UNARY;
|
||||
}
|
||||
|
||||
abstract class Parameter implements Expression, VariableBinding {
|
||||
TypeRef get type;
|
||||
}
|
||||
abstract class Parameter implements Expression, VariableBinding {}
|
||||
|
||||
class Identifier extends Expression implements Parameter {
|
||||
final String name;
|
||||
final bool allowRename;
|
||||
final TypeRef type;
|
||||
|
||||
Identifier(this.name, {this.allowRename = true, this.type}) {
|
||||
Identifier(this.name, {this.allowRename = true}) {
|
||||
if (!_identifierRE.hasMatch(name)) {
|
||||
throw ArgumentError.value(name, "name", "not a valid identifier");
|
||||
}
|
||||
|
@ -1204,7 +1171,6 @@ class Identifier extends Expression implements Parameter {
|
|||
// This is an expression for convenience in the AST.
|
||||
class RestParameter extends Expression implements Parameter {
|
||||
final Identifier parameter;
|
||||
TypeRef get type => null;
|
||||
|
||||
RestParameter(this.parameter);
|
||||
|
||||
|
@ -1278,24 +1244,13 @@ class NamedFunction extends Expression {
|
|||
}
|
||||
|
||||
abstract class FunctionExpression extends Expression {
|
||||
Node get body; // Expression or block
|
||||
List<Parameter> get params;
|
||||
|
||||
get body; // Expression or block
|
||||
/// Type parameters passed to this generic function, if any. `null` otherwise.
|
||||
// TODO(ochafik): Support type bounds.
|
||||
List<Identifier> get typeParams;
|
||||
|
||||
/// Return type of this function, if any. `null` otherwise.
|
||||
TypeRef get returnType;
|
||||
}
|
||||
|
||||
class Fun extends FunctionExpression {
|
||||
final List<Parameter> params;
|
||||
final Block body;
|
||||
@override
|
||||
final List<Identifier> typeParams;
|
||||
@override
|
||||
final TypeRef returnType;
|
||||
|
||||
/** Whether this is a JS generator (`function*`) that may contain `yield`. */
|
||||
final bool isGenerator;
|
||||
|
@ -1304,9 +1259,7 @@ class Fun extends FunctionExpression {
|
|||
|
||||
Fun(this.params, this.body,
|
||||
{this.isGenerator = false,
|
||||
this.asyncModifier = const AsyncModifier.sync(),
|
||||
this.typeParams,
|
||||
this.returnType});
|
||||
this.asyncModifier = const AsyncModifier.sync()});
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitFun(this);
|
||||
|
||||
|
@ -1324,12 +1277,8 @@ class Fun extends FunctionExpression {
|
|||
class ArrowFun extends FunctionExpression {
|
||||
final List<Parameter> params;
|
||||
final body; // Expression or Block
|
||||
@override
|
||||
final List<Identifier> typeParams;
|
||||
@override
|
||||
final TypeRef returnType;
|
||||
|
||||
ArrowFun(this.params, this.body, {this.typeParams, this.returnType});
|
||||
ArrowFun(this.params, this.body);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitArrowFun(this);
|
||||
|
||||
|
@ -1627,15 +1576,7 @@ class ClassExpression extends Expression {
|
|||
final Expression heritage; // Can be null.
|
||||
final List<Method> methods;
|
||||
|
||||
/// Type parameters of this class, if any. `null` otherwise.
|
||||
// TODO(ochafik): Support type bounds.
|
||||
final List<Identifier> typeParams;
|
||||
|
||||
/// Field declarations of this class (TypeScript / ES6_TYPED).
|
||||
final List<VariableDeclarationList> fields;
|
||||
|
||||
ClassExpression(this.name, this.heritage, this.methods,
|
||||
{this.typeParams, this.fields});
|
||||
ClassExpression(this.name, this.heritage, this.methods);
|
||||
|
||||
T accept<T>(NodeVisitor<T> visitor) => visitor.visitClassExpression(this);
|
||||
|
||||
|
@ -1643,23 +1584,12 @@ class ClassExpression extends Expression {
|
|||
name.accept(visitor);
|
||||
if (heritage != null) heritage.accept(visitor);
|
||||
for (Method element in methods) element.accept(visitor);
|
||||
if (fields != null) {
|
||||
for (var field in fields) {
|
||||
field.accept(visitor);
|
||||
}
|
||||
}
|
||||
if (typeParams != null) {
|
||||
for (var typeParam in typeParams) {
|
||||
typeParam.accept(visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
ClassDeclaration toStatement() => ClassDeclaration(this);
|
||||
|
||||
ClassExpression _clone() => ClassExpression(name, heritage, methods,
|
||||
typeParams: typeParams, fields: fields);
|
||||
ClassExpression _clone() => ClassExpression(name, heritage, methods);
|
||||
|
||||
int get precedenceLevel => PRIMARY_LOW_PRECEDENCE;
|
||||
}
|
||||
|
@ -1726,7 +1656,6 @@ class InterpolatedParameter extends Expression
|
|||
with InterpolatedNode
|
||||
implements Identifier {
|
||||
final nameOrPosition;
|
||||
TypeRef get type => null;
|
||||
|
||||
String get name {
|
||||
throw "InterpolatedParameter.name must not be invoked";
|
||||
|
@ -1797,7 +1726,6 @@ class InterpolatedIdentifier extends Expression
|
|||
with InterpolatedNode
|
||||
implements Identifier {
|
||||
final nameOrPosition;
|
||||
TypeRef get type => null;
|
||||
|
||||
InterpolatedIdentifier(this.nameOrPosition);
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ class JavaScriptPrintingOptions {
|
|||
final bool shouldCompressOutput;
|
||||
final bool minifyLocalVariables;
|
||||
final bool preferSemicolonToNewlineInMinifiedOutput;
|
||||
final bool emitTypes;
|
||||
final bool allowSingleLineIfStatements;
|
||||
|
||||
/// True to allow keywords in properties, such as `obj.var` or `obj.function`
|
||||
|
@ -19,7 +18,6 @@ class JavaScriptPrintingOptions {
|
|||
{this.shouldCompressOutput = false,
|
||||
this.minifyLocalVariables = false,
|
||||
this.preferSemicolonToNewlineInMinifiedOutput = false,
|
||||
this.emitTypes = false,
|
||||
this.allowKeywordsInProperties = false,
|
||||
this.allowSingleLineIfStatements = false});
|
||||
}
|
||||
|
@ -58,7 +56,7 @@ class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
|
|||
|
||||
// TODO(ochafik): Inline the body of [TypeScriptTypePrinter] here if/when it no
|
||||
// longer needs to share utils with [ClosureTypePrinter].
|
||||
class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
||||
class Printer implements NodeVisitor {
|
||||
final JavaScriptPrintingOptions options;
|
||||
final JavaScriptPrintingContext context;
|
||||
final bool shouldCompressOutput;
|
||||
|
@ -296,7 +294,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
|
||||
visitExpressionStatement(ExpressionStatement expressionStatement) {
|
||||
indent();
|
||||
outClosureAnnotation(expressionStatement);
|
||||
visitNestedExpression(expressionStatement.expression, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: true);
|
||||
outSemicolonLn();
|
||||
|
@ -558,14 +555,12 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
localNamer.enterScope(fun);
|
||||
outTypeParams(fun.typeParams);
|
||||
out("(");
|
||||
if (fun.params != null) {
|
||||
visitCommaSeparated(fun.params, PRIMARY,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
out(")");
|
||||
outTypeAnnotation(fun.returnType);
|
||||
switch (fun.asyncModifier) {
|
||||
case const AsyncModifier.sync():
|
||||
break;
|
||||
|
@ -585,7 +580,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
|
||||
visitFunctionDeclaration(FunctionDeclaration declaration) {
|
||||
indent();
|
||||
outClosureAnnotation(declaration);
|
||||
var f = declaration.function;
|
||||
context.enterNode(f);
|
||||
functionOut(f, declaration.name);
|
||||
|
@ -623,7 +617,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
}
|
||||
|
||||
visitVariableDeclarationList(VariableDeclarationList list) {
|
||||
outClosureAnnotation(list);
|
||||
// Note: keyword can be null for non-static field declarations.
|
||||
if (list.keyword != null) {
|
||||
out(list.keyword);
|
||||
|
@ -665,7 +658,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
}
|
||||
visit(structure);
|
||||
}
|
||||
outTypeAnnotation(node.type);
|
||||
var defaultValue = node.defaultValue;
|
||||
if (defaultValue != null) {
|
||||
spaceOut();
|
||||
|
@ -695,7 +687,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
}
|
||||
|
||||
visitVariableInitialization(VariableInitialization init) {
|
||||
outClosureAnnotation(init);
|
||||
visitNestedExpression(init.declaration, LEFT_HAND_SIDE,
|
||||
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
|
||||
if (init.value != null) {
|
||||
|
@ -898,7 +889,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
|
||||
visitIdentifier(Identifier node) {
|
||||
out(localNamer.getName(node));
|
||||
outTypeAnnotation(node.type);
|
||||
}
|
||||
|
||||
visitRestParameter(RestParameter node) {
|
||||
|
@ -966,9 +956,7 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
|
||||
visitArrowFun(ArrowFun fun) {
|
||||
localNamer.enterScope(fun);
|
||||
if (fun.params.length == 1 &&
|
||||
fun.params[0] is Identifier &&
|
||||
(!options.emitTypes || fun.params[0].type == null)) {
|
||||
if (fun.params.length == 1 && fun.params[0] is Identifier) {
|
||||
visitNestedExpression(fun.params.single, SPREAD,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
} else {
|
||||
|
@ -977,7 +965,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
}
|
||||
outTypeAnnotation(fun.returnType);
|
||||
spaceOut();
|
||||
out("=>");
|
||||
var body = fun.body;
|
||||
|
@ -1116,24 +1103,10 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
lineOut();
|
||||
}
|
||||
|
||||
void outTypeParams(Iterable<Identifier> typeParams) {
|
||||
if (typeParams != null && options.emitTypes && typeParams.isNotEmpty) {
|
||||
out("<");
|
||||
var first = true;
|
||||
for (var typeParam in typeParams) {
|
||||
if (!first) out(", ");
|
||||
first = false;
|
||||
visit(typeParam);
|
||||
}
|
||||
out(">");
|
||||
}
|
||||
}
|
||||
|
||||
visitClassExpression(ClassExpression node) {
|
||||
localNamer.enterScope(node);
|
||||
out('class ');
|
||||
visit(node.name);
|
||||
outTypeParams(node.typeParams);
|
||||
if (node.heritage != null) {
|
||||
out(' extends ');
|
||||
visit(node.heritage);
|
||||
|
@ -1143,14 +1116,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
out('{');
|
||||
lineOut();
|
||||
indentMore();
|
||||
if (options.emitTypes && node.fields != null) {
|
||||
for (var field in node.fields) {
|
||||
indent();
|
||||
visit(field);
|
||||
out(";");
|
||||
lineOut();
|
||||
}
|
||||
}
|
||||
for (var method in node.methods) {
|
||||
indent();
|
||||
visit(method);
|
||||
|
@ -1166,7 +1131,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
}
|
||||
|
||||
visitMethod(Method node) {
|
||||
outClosureAnnotation(node);
|
||||
if (node.isStatic) {
|
||||
out('static ');
|
||||
}
|
||||
|
@ -1198,17 +1162,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
localNamer.leaveScope();
|
||||
}
|
||||
|
||||
void outClosureAnnotation(Node node) {
|
||||
if (node != null && node.closureAnnotation != null) {
|
||||
String comment = node.closureAnnotation.toString(indentation);
|
||||
if (comment.isNotEmpty) {
|
||||
out(comment);
|
||||
lineOut();
|
||||
indent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void propertyNameOut(Expression node,
|
||||
{bool inMethod = false, bool inAccess = false}) {
|
||||
if (node is LiteralNumber) {
|
||||
|
@ -1404,18 +1357,6 @@ class Printer extends TypeScriptTypePrinter implements NodeVisitor {
|
|||
out("await ");
|
||||
visit(node.expression);
|
||||
}
|
||||
|
||||
void outTypeAnnotation(TypeRef node) {
|
||||
if (node == null || !options.emitTypes || node.isUnknown) return;
|
||||
|
||||
if (node is OptionalTypeRef) {
|
||||
out("?: ");
|
||||
visit(node.type);
|
||||
} else {
|
||||
out(": ");
|
||||
visit(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collects all the var declarations in the function. We need to do this in a
|
||||
|
|
|
@ -598,7 +598,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
|
||||
Instantiator<ArrowFun> visitArrowFun(ArrowFun node) {
|
||||
var paramMakers = node.params.map(visitSplayable).toList();
|
||||
Instantiator makeBody = visit(node.body as Node);
|
||||
Instantiator makeBody = visit(node.body);
|
||||
return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a));
|
||||
}
|
||||
|
||||
|
@ -700,32 +700,6 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
Instantiator visitExportClause(ExportClause node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitAnyTypeRef(AnyTypeRef node) => throw UnimplementedError();
|
||||
|
||||
Instantiator visitUnknownTypeRef(UnknownTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitArrayTypeRef(ArrayTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitFunctionTypeRef(FunctionTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitGenericTypeRef(GenericTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitQualifiedTypeRef(QualifiedTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitOptionalTypeRef(OptionalTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitRecordTypeRef(RecordTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Instantiator visitUnionTypeRef(UnionTypeRef node) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Instantiator<DestructuredVariable> visitDestructuredVariable(
|
||||
DestructuredVariable node) {
|
||||
|
|
|
@ -1,227 +0,0 @@
|
|||
// 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 = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4839,8 +4839,7 @@ class ProgramCompiler extends Object
|
|||
|
||||
// Convert `function(...) { ... }` to `(...) => ...`
|
||||
// This is for readability, but it also ensures correct `this` binding.
|
||||
return JS.ArrowFun(f.params, body,
|
||||
typeParams: f.typeParams, returnType: f.returnType);
|
||||
return JS.ArrowFun(f.params, body);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
library dev_compiler.test.closure_annotation_test;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:dev_compiler/src/closure/closure_annotation.dart';
|
||||
import 'package:dev_compiler/src/js_ast/js_ast.dart' show TypeRef, Identifier;
|
||||
|
||||
void main() {
|
||||
group('ClosureAnnotation', () {
|
||||
var anyType = TypeRef.any();
|
||||
var unknownType = TypeRef.unknown();
|
||||
var numberType = TypeRef.number();
|
||||
var stringType = TypeRef.string();
|
||||
var booleanType = TypeRef.boolean();
|
||||
var fooType = TypeRef.qualified([Identifier("foo"), Identifier("Foo")]);
|
||||
var barType = TypeRef.named("Bar");
|
||||
var bazType = TypeRef.named("Baz");
|
||||
var bamType = TypeRef.named("Bam");
|
||||
var batType = TypeRef.named("Bat");
|
||||
|
||||
test('gives empty comment when no has no meaningful info', () {
|
||||
expect(ClosureAnnotation().toString(), "");
|
||||
expect(ClosureAnnotation(type: anyType).toString(), "");
|
||||
expect(ClosureAnnotation(type: unknownType).toString(), "");
|
||||
});
|
||||
|
||||
test('gives single line comment when it fits', () {
|
||||
expect(ClosureAnnotation(type: numberType).toString(),
|
||||
"/** @type {number} */");
|
||||
expect(ClosureAnnotation(paramTypes: {'foo': anyType}).toString(),
|
||||
"/** @param {*} foo */");
|
||||
expect(ClosureAnnotation(paramTypes: {'foo': unknownType}).toString(),
|
||||
"/** @param {?} foo */");
|
||||
});
|
||||
|
||||
test('gives multiple line comment when it it does not fit on one line', () {
|
||||
expect(
|
||||
ClosureAnnotation(
|
||||
returnType: stringType,
|
||||
paramTypes: {'foo': numberType}).toString(),
|
||||
"/**\n"
|
||||
" * @param {number} foo\n"
|
||||
" * @return {string}\n"
|
||||
" */");
|
||||
});
|
||||
|
||||
test('inserts indentation', () {
|
||||
expect(
|
||||
ClosureAnnotation(
|
||||
returnType: stringType,
|
||||
paramTypes: {'foo': numberType}).toString(" "),
|
||||
"/**\n" // No indent on first line.
|
||||
" * @param {number} foo\n"
|
||||
" * @return {string}\n"
|
||||
" */");
|
||||
});
|
||||
|
||||
test('compresses @type, @final, @const, @private, @protected, @typedef',
|
||||
() {
|
||||
expect(ClosureAnnotation(type: stringType).toString(),
|
||||
"/** @type {string} */");
|
||||
expect(ClosureAnnotation(type: stringType, isConst: true).toString(),
|
||||
"/** @const {string} */");
|
||||
expect(ClosureAnnotation(type: stringType, isFinal: true).toString(),
|
||||
"/** @final {string} */");
|
||||
expect(ClosureAnnotation(type: stringType, isPrivate: true).toString(),
|
||||
"/** @private {string} */");
|
||||
expect(ClosureAnnotation(type: stringType, isTypedef: true).toString(),
|
||||
"/** @typedef {string} */");
|
||||
expect(ClosureAnnotation(type: stringType, isProtected: true).toString(),
|
||||
"/** @protected {string} */");
|
||||
expect(
|
||||
ClosureAnnotation(
|
||||
type: stringType,
|
||||
isPrivate: true,
|
||||
isConst: true,
|
||||
isFinal: true,
|
||||
isProtected: true,
|
||||
isTypedef: true)
|
||||
.toString(),
|
||||
"/** @private @protected @final @const @typedef {string} */");
|
||||
});
|
||||
|
||||
test('supports a full constructor annotation', () {
|
||||
expect(
|
||||
ClosureAnnotation(
|
||||
returnType: booleanType,
|
||||
throwsType: bamType,
|
||||
thisType: fooType,
|
||||
superType: barType,
|
||||
lendsToType: batType,
|
||||
interfaces: [bazType],
|
||||
isStruct: true,
|
||||
isPrivate: true,
|
||||
isProtected: true,
|
||||
isOverride: true,
|
||||
isFinal: true,
|
||||
isConst: true,
|
||||
isConstructor: true,
|
||||
isNoSideEffects: true,
|
||||
isNoCollapse: true,
|
||||
paramTypes: {'x': stringType, 'y': numberType},
|
||||
templates: ['A', 'B']).toString(),
|
||||
'/**\n'
|
||||
' * @template A, B\n'
|
||||
' * @this {foo.Foo}\n'
|
||||
' * @override\n'
|
||||
' * @nosideeffects\n'
|
||||
' * @nocollapse\n'
|
||||
' * @lends {Bat}\n'
|
||||
' * @private @protected @final @const\n'
|
||||
' * @constructor @struct @extends {Bar}\n'
|
||||
' * @implements {Baz}\n'
|
||||
' * @param {string} x\n'
|
||||
' * @param {number} y\n'
|
||||
' * @return {boolean}\n'
|
||||
' * @throws {Bam}\n'
|
||||
' */');
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
library dev_compiler.test.closure_type_test;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:dev_compiler/src/closure/closure_type.dart';
|
||||
|
||||
void main() {
|
||||
expectToString(ClosureType t, String s,
|
||||
{String nullable, String nonNullable}) {
|
||||
expect(t.toString(), s);
|
||||
if (nullable != null) {
|
||||
expect(t.toNullable().toString(), nullable);
|
||||
}
|
||||
if (nonNullable != null) {
|
||||
expect(t.toNonNullable().toString(), nonNullable);
|
||||
}
|
||||
}
|
||||
|
||||
group('ClosureType', () {
|
||||
test('supports simple types', () {
|
||||
expectToString(ClosureType.number(), "number",
|
||||
nullable: "?number", nonNullable: "number");
|
||||
expectToString(ClosureType.boolean(), "boolean",
|
||||
nullable: "?boolean", nonNullable: "boolean");
|
||||
expectToString(ClosureType.string(), "string",
|
||||
nullable: "string", nonNullable: "!string");
|
||||
expectToString(ClosureType.type("foo.Bar"), "foo.Bar",
|
||||
nullable: "foo.Bar", nonNullable: "!foo.Bar");
|
||||
});
|
||||
|
||||
test('supports array types', () {
|
||||
expectToString(ClosureType.array(), "Array<*>",
|
||||
nullable: "Array<*>", nonNullable: "!Array<*>");
|
||||
expectToString(ClosureType.array(ClosureType.type("Foo")), "Array<Foo>",
|
||||
nullable: "Array<Foo>", nonNullable: "!Array<Foo>");
|
||||
});
|
||||
|
||||
test('supports map types', () {
|
||||
expectToString(
|
||||
ClosureType.map(ClosureType.type("Foo"), ClosureType.type("Bar")),
|
||||
"Object<Foo, Bar>",
|
||||
nullable: "Object<Foo, Bar>",
|
||||
nonNullable: "!Object<Foo, Bar>");
|
||||
expectToString(ClosureType.map(), "Object<*, *>",
|
||||
nullable: "Object<*, *>", nonNullable: "!Object<*, *>");
|
||||
});
|
||||
|
||||
test('supports function types', () {
|
||||
expectToString(ClosureType.function(), "Function",
|
||||
nullable: "Function", nonNullable: "!Function");
|
||||
expectToString(
|
||||
ClosureType.function([ClosureType.number()]), "function(number)");
|
||||
expectToString(ClosureType.function(null, ClosureType.number()),
|
||||
"function(...*):number");
|
||||
expectToString(
|
||||
ClosureType.function([ClosureType.number(), ClosureType.string()],
|
||||
ClosureType.boolean()),
|
||||
"function(number, string):boolean");
|
||||
});
|
||||
|
||||
test('supports union types', () {
|
||||
expectToString(
|
||||
ClosureType.number().or(ClosureType.boolean()), "(number|boolean)");
|
||||
expectToString(ClosureType.number().orUndefined(), "(number|undefined)");
|
||||
});
|
||||
|
||||
test('supports record types', () {
|
||||
expectToString(
|
||||
ClosureType.record(
|
||||
{'x': ClosureType.number(), 'y': ClosureType.boolean()}),
|
||||
"{x: number, y: boolean}");
|
||||
});
|
||||
|
||||
test('supports optional pseudo-types', () {
|
||||
expectToString(ClosureType.number().toOptional(), "number=");
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue