Chromium Code Reviews| Index: lib/src/codegen/js_codegen.dart |
| diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart |
| index 9650a36306b195dc94a98398d8b63c6e0951ea0b..2280bbd061bac151a8a4985d9b31a3d9a240ff60 100644 |
| --- a/lib/src/codegen/js_codegen.dart |
| +++ b/lib/src/codegen/js_codegen.dart |
| @@ -8,6 +8,7 @@ import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
| import 'package:analyzer/src/generated/constant.dart'; |
| import 'package:analyzer/src/generated/element.dart'; |
| +import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
| import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| import 'package:analyzer/src/generated/scanner.dart' |
| show StringToken, Token, TokenType; |
| @@ -428,9 +429,17 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { |
| String jsPeerName; |
| var jsPeer = findAnnotation(classElem, isJsPeerInterface); |
| + // Only look at "Native" annotations on registered extension types. |
| + // E.g., we're current ignoring the ones in dart:html. |
| + if (jsPeer == null && _extensionTypes.contains(classElem)) { |
| + jsPeer = findAnnotation(classElem, isNativeAnnotation); |
| + } |
| if (jsPeer != null) { |
| jsPeerName = |
| getConstantField(jsPeer, 'name', types.stringType)?.toStringValue(); |
| + if (jsPeerName.contains(',')) { |
| + jsPeerName = jsPeerName.split(',')[0]; |
| + } |
| } |
| var body = _finishClassMembers(classElem, classExpr, ctors, fields, |
| @@ -1274,14 +1283,39 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { |
| } |
| JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { |
| - if (node.isAbstract || _externalOrNative(node)) { |
| + if (node.isAbstract) { |
| return null; |
| } |
| var params = _visit(node.parameters) as List<JS.Parameter>; |
| if (params == null) params = <JS.Parameter>[]; |
| - JS.Fun fn = _emitFunctionBody(params, node.body); |
| + JS.Fun fn; |
| + if (_externalOrNative(node)) { |
| + if (node.isStatic) { |
|
Jennifer Messerly
2016/02/10 00:20:30
Perhaps factor this out into _emitNativeFunctionBo
vsm
2016/02/11 22:36:06
Done.
|
| + // TODO(vsm): Do we need to handle this case? |
| + return null; |
| + } |
| + |
| + String name = node.name.name; |
| + var annotation = findAnnotation(node.element, isJsName); |
| + if (annotation != null) { |
| + name = getConstantField(annotation, 'name', types.stringType) |
| + ?.toStringValue(); |
| + } |
| + if (node.isGetter) { |
| + fn = new JS.Fun(params, js.statement('{ return this.#; }', [name])); |
| + } else if (node.isSetter) { |
| + fn = new JS.Fun( |
| + params, js.statement('{ this.# = #; }', [name, params.last])); |
| + } else { |
| + fn = new JS.Fun( |
| + params, js.statement('{ return this.#(#); }', [name, params])); |
| + } |
| + } else { |
| + fn = _emitFunctionBody(params, node.body); |
| + } |
| + |
| if (node.operatorKeyword != null && |
| node.name.name == '[]=' && |
| params.isNotEmpty) { |
| @@ -3555,27 +3589,18 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { |
| } |
| } |
| -class JSGenerator extends CodeGenerator { |
| - final _extensionTypes = new HashSet<ClassElement>(); |
| +class _ExtensionFinder extends GeneralizingElementVisitor { |
| + final AnalysisContext _context; |
| + final HashSet<ClassElement> _extensionTypes; |
| final TypeProvider _types; |
| - JSGenerator(AbstractCompiler compiler) |
| - : _types = compiler.context.typeProvider, |
| - super(compiler) { |
| - // TODO(jacobr): determine the the set of types with extension methods from |
| - // the annotations rather than hard coding the list once the analyzer |
| - // supports summaries. |
| - var context = compiler.context; |
| - var src = context.sourceFactory.forUri('dart:_interceptors'); |
| - var interceptors = context.computeLibraryElement(src); |
| - for (var t in ['JSArray', 'JSString', 'JSNumber', 'JSBool']) { |
| - _addExtensionType(interceptors.getType(t).type); |
| + |
| + _ExtensionFinder(this._context, this._extensionTypes, this._types); |
| + |
| + visitClassElement(ClassElement element) { |
| + if (findAnnotation(element, isJsPeerInterface) != null || |
| + findAnnotation(element, isNativeAnnotation) != null) { |
| + _addExtensionType(element.type); |
| } |
| - // TODO(jmesserly): manually add `int` and `double` |
| - // Unfortunately our current analyzer rejects "implements int". |
| - // Fix was landed, so we can remove this hack once we're updated: |
| - // https://github.com/dart-lang/sdk/commit/d7cd11f86a02f55269fc8d9843e7758ebeeb81c8 |
| - _addExtensionType(_types.intType); |
| - _addExtensionType(_types.doubleType); |
| } |
| void _addExtensionType(InterfaceType t) { |
| @@ -3586,6 +3611,35 @@ class JSGenerator extends CodeGenerator { |
| _addExtensionType(t.superclass); |
| } |
| + void _addExtensionTypes(String libraryUri) { |
| + var sourceFactory = _context.sourceFactory.forUri(libraryUri); |
| + var library = _context.computeLibraryElement(sourceFactory); |
| + visitLibraryElement(library); |
| + } |
| +} |
| + |
| +class JSGenerator extends CodeGenerator { |
| + final _extensionTypes = new HashSet<ClassElement>(); |
| + final TypeProvider _types; |
| + |
| + JSGenerator(AbstractCompiler compiler) |
| + : _types = compiler.context.typeProvider, |
| + super(compiler) { |
| + // TODO(vsm): Eventually, we want to make this extensible - i.e., find |
| + // annotations in user code as well. It would need to be summarized in |
| + // the element model - not searched this way on every compile. |
| + var finder = new _ExtensionFinder(context, _extensionTypes, _types); |
| + finder._addExtensionTypes('dart:_interceptors'); |
| + finder._addExtensionTypes('dart:_native_typed_data'); |
| + |
| + // TODO(vsm): If we're analyzing against the main SDK, those |
| + // types are not explicitly annotated. |
| + finder._addExtensionType(_types.intType); |
| + finder._addExtensionType(_types.doubleType); |
| + finder._addExtensionType(_types.boolType); |
| + finder._addExtensionType(_types.stringType); |
| + } |
| + |
| String generateLibrary(LibraryUnit unit) { |
| // Clone the AST first, so we can mutate it. |
| unit = unit.clone(); |