Index: lib/src/closure/closure_annotator.dart |
diff --git a/lib/src/closure/closure_annotator.dart b/lib/src/closure/closure_annotator.dart |
index 7229a1da9983d0bcd6ee110fca69d112d8ab61a9..d527b3df035ca75b72828c69142e1bf662403ea6 100644 |
--- a/lib/src/closure/closure_annotator.dart |
+++ b/lib/src/closure/closure_annotator.dart |
@@ -2,141 +2,40 @@ |
// 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/analyzer.dart' show ParameterKind; |
+import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
import 'package:analyzer/src/generated/element.dart'; |
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
+import '../js/js_ast.dart' as JS show Node, Expression, TypeRef; |
+ |
import 'closure_annotation.dart'; |
-import 'closure_type.dart'; |
/// Mixin that can generate [ClosureAnnotation]s for Dart elements and types. |
abstract class ClosureAnnotator { |
TypeProvider get types; |
- /// Must return a JavaScript qualified name that can be used to refer to [type]. |
- String getQualifiedName(TypeDefiningElement type); |
- |
- ClosureAnnotation closureAnnotationForVariable(VariableElement e) => |
- new ClosureAnnotation( |
- type: _closureTypeForDartType(e.type), |
- // Note: we don't set isConst here because Closure's constness and |
- // Dart's are not really compatible. |
- isFinal: e.isFinal || e.isConst); |
- |
- /// We don't use Closure's `@typedef` annotations |
- ClosureAnnotation closureAnnotationForTypeDef(FunctionTypeAliasElement e) => |
- new ClosureAnnotation( |
- type: _closureTypeForDartType(e.type, forceTypeDefExpansion: true), |
- isTypedef: true); |
- |
- ClosureAnnotation closureAnnotationForDefaultConstructor(ClassElement e) => |
- new ClosureAnnotation( |
- superType: _closureTypeForDartType(e.supertype), |
- interfaces: e.interfaces.map(_closureTypeForDartType).toList()); |
+ JS.TypeRef emitTypeRef(DartType type); |
// TODO(ochafik): Handle destructured params when Closure supports it. |
ClosureAnnotation closureAnnotationFor( |
- ExecutableElement e, String namedArgsMapName) { |
- var paramTypes = <String, ClosureType>{}; |
- var namedArgs = <String, ClosureType>{}; |
- for (var param in e.parameters) { |
- var t = _closureTypeForDartType(param.type); |
- switch (param.parameterKind) { |
- case ParameterKind.NAMED: |
- namedArgs[param.name] = t.orUndefined(); |
- break; |
- case ParameterKind.POSITIONAL: |
- paramTypes[param.name] = t.toOptional(); |
- break; |
- case ParameterKind.REQUIRED: |
- paramTypes[param.name] = t; |
- break; |
- } |
- } |
- if (namedArgs.isNotEmpty) { |
- paramTypes[namedArgsMapName] = |
- new ClosureType.record(namedArgs).toOptional(); |
+ JS.Node node, AstNode original, Element e, String namedArgsMapName) { |
+ String comment; |
+ if (original is AnnotatedNode && original.documentationComment != null) { |
+ comment = original.documentationComment.toSource(); |
} |
- |
- var returnType = e is ConstructorElement |
- ? (e.isFactory ? _closureTypeForClass(e.enclosingElement) : null) |
- : _closureTypeForDartType(e.returnType); |
- |
+ // Note: Dart and Closure privacy are not compatible: don't set `isPrivate: e.isPrivate`. |
return new ClosureAnnotation( |
+ comment: comment, |
+ // 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, |
- // Note: Dart and Closure privacy are not compatible: don't set `isPrivate: e.isPrivate`. |
- paramTypes: paramTypes, |
- returnType: returnType); |
+ isTypedef: e is FunctionTypeAliasElement); |
} |
- |
- Map<DartType, ClosureType> __commonTypes; |
- Map<DartType, ClosureType> get _commonTypes { |
- if (__commonTypes == null) { |
- var numberType = new ClosureType.number().toNullable(); |
- __commonTypes = { |
- types.intType: numberType, |
- types.numType: numberType, |
- types.doubleType: numberType, |
- types.boolType: new ClosureType.boolean().toNullable(), |
- types.stringType: new ClosureType.string(), |
- }; |
- } |
- return __commonTypes; |
- } |
- |
- ClosureType _closureTypeForClass(ClassElement classElement, [DartType type]) { |
- ClosureType closureType = _commonTypes[type]; |
- if (closureType != null) return closureType; |
- |
- var fullName = _getFullName(classElement); |
- switch (fullName) { |
- // TODO(ochafik): Test DartTypes directly if possible. |
- case "dart.js.JsArray": |
- return new ClosureType.array( |
- type is InterfaceType && type.typeArguments.length == 1 |
- ? _closureTypeForDartType(type.typeArguments.single) |
- : null); |
- case "dart.js.JsObject": |
- return new ClosureType.map(); |
- case "dart.js.JsFunction": |
- return new ClosureType.function(); |
- default: |
- return new ClosureType.type(getQualifiedName(classElement)); |
- } |
- } |
- |
- ClosureType _closureTypeForDartType(DartType type, |
- {bool forceTypeDefExpansion: false}) { |
- if (type == null || type.isBottom || type.isDynamic) { |
- return new ClosureType.unknown(); |
- } |
- if (type.isVoid) return null; |
- if (type is FunctionType) { |
- if (!forceTypeDefExpansion && type.element.name != '') { |
- return new ClosureType.type(getQualifiedName(type.element)); |
- } |
- |
- var args = [] |
- ..addAll(type.normalParameterTypes.map(_closureTypeForDartType)) |
- ..addAll(type.optionalParameterTypes |
- .map((t) => _closureTypeForDartType(t).toOptional())); |
- if (type.namedParameterTypes.isNotEmpty) { |
- var namedArgs = <String, ClosureType>{}; |
- type.namedParameterTypes.forEach((n, t) { |
- namedArgs[n] = _closureTypeForDartType(t).orUndefined(); |
- }); |
- args.add(new ClosureType.record(namedArgs).toOptional()); |
- } |
- return new ClosureType.function( |
- args, _closureTypeForDartType(type.returnType)); |
- } |
- if (type is InterfaceType) { |
- return _closureTypeForClass(type.element, type); |
- } |
- return new ClosureType.unknown(); |
- } |
- |
- /// TODO(ochafik): Use a package-and-file-uri-dependent naming, since libraries can collide. |
- String _getFullName(ClassElement type) => |
- type.library.name == '' ? type.name : '${type.library.name}.${type.name}'; |
} |