Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1176)

Side by Side Diff: lib/src/compiler/code_generator.dart

Issue 2016483002: Enable strong mode in DDC, fix all warnings/errors (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:collection' show HashMap, HashSet; 5 import 'dart:collection' show HashMap, HashSet;
6 import 'dart:math' show min, max; 6 import 'dart:math' show min, max;
7 7
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return module; 276 return module;
277 } 277 }
278 } 278 }
279 279
280 List<String> _getJSName(Element e) { 280 List<String> _getJSName(Element e) {
281 if (findAnnotation(e.library, isPublicJSAnnotation) == null) { 281 if (findAnnotation(e.library, isPublicJSAnnotation) == null) {
282 return null; 282 return null;
283 } 283 }
284 284
285 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation); 285 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation);
286 var libraryPrefix = []; 286 var libraryPrefix = <String>[];
287 if (libraryJSName != null && libraryJSName.isNotEmpty) { 287 if (libraryJSName != null && libraryJSName.isNotEmpty) {
288 libraryPrefix.addAll(libraryJSName.split('.')); 288 libraryPrefix.addAll(libraryJSName.split('.'));
289 } 289 }
290 290
291 var elementJSName; 291 String elementJSName;
292 if (findAnnotation(e, isPublicJSAnnotation) != null) { 292 if (findAnnotation(e, isPublicJSAnnotation) != null) {
293 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? ''; 293 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? '';
294 } 294 }
295 if (e is TopLevelVariableElement && 295 if (e is TopLevelVariableElement &&
296 e.getter != null && 296 e.getter != null &&
297 (e.getter.isExternal || 297 (e.getter.isExternal ||
298 findAnnotation(e.getter, isPublicJSAnnotation) != null)) { 298 findAnnotation(e.getter, isPublicJSAnnotation) != null)) {
299 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? ''; 299 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? '';
300 } 300 }
301 if (elementJSName == null) return null; 301 if (elementJSName == null) return null;
302 302
303 var elementJSParts = []; 303 var elementJSParts = <String>[];
304 if (elementJSName.isNotEmpty) { 304 if (elementJSName.isNotEmpty) {
305 elementJSParts.addAll(elementJSName.split('.')); 305 elementJSParts.addAll(elementJSName.split('.'));
306 } else { 306 } else {
307 elementJSParts.add(e.name); 307 elementJSParts.add(e.name);
308 } 308 }
309 309
310 return libraryPrefix..addAll(elementJSParts); 310 return libraryPrefix..addAll(elementJSParts);
311 } 311 }
312 312
313 JS.Expression _emitJSInterop(Element e) { 313 JS.Expression _emitJSInterop(Element e) {
314 var jsName = _getJSName(e); 314 var jsName = _getJSName(e);
315 if (jsName == null) return null; 315 if (jsName == null) return null;
316 var fullName = ['global']..addAll(jsName); 316 var fullName = ['global']..addAll(jsName);
317 var access = _runtimeLibVar; 317 JS.Expression access = _runtimeLibVar;
318 for (var part in fullName) { 318 for (var part in fullName) {
319 access = new JS.PropertyAccess(access, js.string(part)); 319 access = new JS.PropertyAccess(access, js.string(part));
320 } 320 }
321 return access; 321 return access;
322 } 322 }
323 323
324 /// Flattens blocks in [items] to a single list. 324 /// Flattens blocks in [items] to a single list.
325 /// 325 ///
326 /// This will not flatten blocks that are marked as being scopes. 326 /// This will not flatten blocks that are marked as being scopes.
327 void _copyAndFlattenBlocks( 327 void _copyAndFlattenBlocks(
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 685
686 JS.Expression className; 686 JS.Expression className;
687 if (classElem.typeParameters.isNotEmpty) { 687 if (classElem.typeParameters.isNotEmpty) {
688 // Generic classes will be defined inside a function that closes over the 688 // Generic classes will be defined inside a function that closes over the
689 // type parameter. So we can use their local variable name directly. 689 // type parameter. So we can use their local variable name directly.
690 className = new JS.Identifier(classElem.name); 690 className = new JS.Identifier(classElem.name);
691 } else { 691 } else {
692 className = _emitTopLevelName(classElem); 692 className = _emitTopLevelName(classElem);
693 } 693 }
694 694
695 var allFields = new List.from(fields)..addAll(staticFields); 695 var allFields = fields.toList()..addAll(staticFields);
696 var superclasses = getSuperclasses(classElem); 696 var superclasses = getSuperclasses(classElem);
697 var virtualFields = <FieldElement, JS.TemporaryId>{}; 697 var virtualFields = <FieldElement, JS.TemporaryId>{};
698 var virtualFieldSymbols = <JS.Statement>[]; 698 var virtualFieldSymbols = <JS.Statement>[];
699 var staticFieldOverrides = new HashSet<FieldElement>(); 699 var staticFieldOverrides = new HashSet<FieldElement>();
700 _registerPropertyOverrides(classElem, className, superclasses, allFields, 700 _registerPropertyOverrides(classElem, className, superclasses, allFields,
701 virtualFields, virtualFieldSymbols, staticFieldOverrides); 701 virtualFields, virtualFieldSymbols, staticFieldOverrides);
702 702
703 var classExpr = _emitClassExpression(classElem, 703 var classExpr = _emitClassExpression(classElem,
704 _emitClassMethods(node, ctors, fields, superclasses, virtualFields), 704 _emitClassMethods(node, ctors, fields, superclasses, virtualFields),
705 fields: allFields); 705 fields: allFields);
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 /// conflicts. They will be installed as extension methods on the underlying 935 /// conflicts. They will be installed as extension methods on the underlying
936 /// native type. 936 /// native type.
937 List<JS.Method> _emitNativeFieldAccessors(FieldDeclaration node) { 937 List<JS.Method> _emitNativeFieldAccessors(FieldDeclaration node) {
938 // TODO(vsm): Can this by meta-programmed? 938 // TODO(vsm): Can this by meta-programmed?
939 // E.g., dart.nativeField(symbol, jsName) 939 // E.g., dart.nativeField(symbol, jsName)
940 // Alternatively, perhaps it could be meta-programmed directly in 940 // Alternatively, perhaps it could be meta-programmed directly in
941 // dart.registerExtensions? 941 // dart.registerExtensions?
942 var jsMethods = <JS.Method>[]; 942 var jsMethods = <JS.Method>[];
943 if (!node.isStatic) { 943 if (!node.isStatic) {
944 for (var decl in node.fields.variables) { 944 for (var decl in node.fields.variables) {
945 var field = decl.element; 945 var field = decl.element as FieldElement;
946 var name = getAnnotationName(field, isJsName) ?? field.name; 946 var name = getAnnotationName(field, isJsName) ?? field.name;
947 // Generate getter 947 // Generate getter
948 var fn = new JS.Fun([], js.statement('{ return this.#; }', [name])); 948 var fn = new JS.Fun([], js.statement('{ return this.#; }', [name]));
949 var method = 949 var method =
950 new JS.Method(_elementMemberName(field.getter), fn, isGetter: true); 950 new JS.Method(_elementMemberName(field.getter), fn, isGetter: true);
951 jsMethods.add(method); 951 jsMethods.add(method);
952 952
953 // Generate setter 953 // Generate setter
954 if (!decl.isFinal) { 954 if (!decl.isFinal) {
955 var value = new JS.TemporaryId('value'); 955 var value = new JS.TemporaryId('value');
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 List<MethodDeclaration> methods, 1337 List<MethodDeclaration> methods,
1338 List<FieldDeclaration> fields, 1338 List<FieldDeclaration> fields,
1339 List<JS.Statement> body) { 1339 List<JS.Statement> body) {
1340 if (_extensionTypes.hasNativeSubtype(classElem.type)) { 1340 if (_extensionTypes.hasNativeSubtype(classElem.type)) {
1341 var dartxNames = <JS.Expression>[]; 1341 var dartxNames = <JS.Expression>[];
1342 for (var m in methods) { 1342 for (var m in methods) {
1343 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 1343 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
1344 dartxNames.add(_elementMemberName(m.element, useExtension: false)); 1344 dartxNames.add(_elementMemberName(m.element, useExtension: false));
1345 } 1345 }
1346 } 1346 }
1347 for (var f in fields) { 1347 for (var fieldDecl in fields) {
1348 if (!f.isStatic) { 1348 if (!fieldDecl.isStatic) {
1349 for (var d in f.fields.variables) { 1349 for (var field in fieldDecl.fields.variables) {
1350 if (d.element.isPublic) { 1350 var e = field.element as FieldElement;
1351 dartxNames.add( 1351 if (e.isPublic) {
1352 _elementMemberName(d.element.getter, useExtension: false)); 1352 dartxNames.add(_elementMemberName(e.getter, useExtension: false));
1353 } 1353 }
1354 } 1354 }
1355 } 1355 }
1356 } 1356 }
1357 if (dartxNames.isNotEmpty) { 1357 if (dartxNames.isNotEmpty) {
1358 body.add(js.statement('dart.defineExtensionNames(#)', 1358 body.add(js.statement('dart.defineExtensionNames(#)',
1359 [new JS.ArrayInitializer(dartxNames, multiline: true)])); 1359 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
1360 } 1360 }
1361 } 1361 }
1362 } 1362 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 if (jsSuper != null) body.add(jsSuper); 1528 if (jsSuper != null) body.add(jsSuper);
1529 1529
1530 body.add(_visit(node.body)); 1530 body.add(_visit(node.body));
1531 return new JS.Block(body)..sourceInformation = node; 1531 return new JS.Block(body)..sourceInformation = node;
1532 } 1532 }
1533 1533
1534 @override 1534 @override
1535 JS.Statement visitRedirectingConstructorInvocation( 1535 JS.Statement visitRedirectingConstructorInvocation(
1536 RedirectingConstructorInvocation node) { 1536 RedirectingConstructorInvocation node) {
1537 var ctor = node.staticElement; 1537 var ctor = node.staticElement;
1538 var cls = ctor.enclosingElement as ClassElement; 1538 var cls = ctor.enclosingElement;
1539 // We can't dispatch to the constructor with `this.new` as that might hit a 1539 // We can't dispatch to the constructor with `this.new` as that might hit a
1540 // derived class constructor with the same name. 1540 // derived class constructor with the same name.
1541 return js.statement('#.prototype.#.call(this, #);', [ 1541 return js.statement('#.prototype.#.call(this, #);', [
1542 new JS.Identifier(cls.name), 1542 new JS.Identifier(cls.name),
1543 _constructorName(ctor), 1543 _constructorName(ctor),
1544 _visit(node.argumentList) 1544 _visit(node.argumentList)
1545 ]); 1545 ]);
1546 } 1546 }
1547 1547
1548 JS.Statement _superConstructorCall(ClassElement element, 1548 JS.Statement _superConstructorCall(ClassElement element,
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1832 assert(node.parent is CompilationUnit); 1832 assert(node.parent is CompilationUnit);
1833 1833
1834 if (_externalOrNative(node)) return null; 1834 if (_externalOrNative(node)) return null;
1835 1835
1836 // If we have a getter/setter pair, they need to be defined together. 1836 // If we have a getter/setter pair, they need to be defined together.
1837 if (node.isGetter) { 1837 if (node.isGetter) {
1838 PropertyAccessorElement element = node.element; 1838 PropertyAccessorElement element = node.element;
1839 var props = <JS.Method>[_emitTopLevelProperty(node)]; 1839 var props = <JS.Method>[_emitTopLevelProperty(node)];
1840 var setter = element.correspondingSetter; 1840 var setter = element.correspondingSetter;
1841 if (setter != null) { 1841 if (setter != null) {
1842 props.add(_loader.emitDeclaration(setter, _emitTopLevelProperty)); 1842 props.add(_loader.emitDeclaration(
1843 setter, (node) => _emitTopLevelProperty(node)));
Leaf 2016/05/26 17:53:37 Annoying. I guess alternatively emitDeclaration c
Jennifer Messerly 2016/05/26 18:11:48 yeah, that was my thought too. Seems like either w
1843 } 1844 }
1844 return js.statement('dart.copyProperties(#, { # });', 1845 return js.statement('dart.copyProperties(#, { # });',
1845 [emitLibraryName(currentLibrary), props]); 1846 [emitLibraryName(currentLibrary), props]);
1846 } 1847 }
1847 if (node.isSetter) { 1848 if (node.isSetter) {
1848 PropertyAccessorElement element = node.element; 1849 PropertyAccessorElement element = node.element;
1849 var props = <JS.Method>[_emitTopLevelProperty(node)]; 1850 var props = <JS.Method>[_emitTopLevelProperty(node)];
1850 var getter = element.correspondingGetter; 1851 var getter = element.correspondingGetter;
1851 if (getter != null) { 1852 if (getter != null) {
1852 props.add(_loader.emitDeclaration(getter, _emitTopLevelProperty)); 1853 props.add(_loader.emitDeclaration(
1854 getter, (node) => _emitTopLevelProperty(node)));
1853 } 1855 }
1854 return js.statement('dart.copyProperties(#, { # });', 1856 return js.statement('dart.copyProperties(#, { # });',
1855 [emitLibraryName(currentLibrary), props]); 1857 [emitLibraryName(currentLibrary), props]);
1856 } 1858 }
1857 1859
1858 var body = <JS.Statement>[]; 1860 var body = <JS.Statement>[];
1859 var fn = _emitFunction(node.functionExpression); 1861 var fn = _emitFunction(node.functionExpression);
1860 1862
1861 if (currentLibrary.source.isInSystemLibrary && 1863 if (currentLibrary.source.isInSystemLibrary &&
1862 _isInlineJSFunction(node.functionExpression)) { 1864 _isInlineJSFunction(node.functionExpression)) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1967 @override 1969 @override
1968 JS.Expression visitFunctionExpression(FunctionExpression node) { 1970 JS.Expression visitFunctionExpression(FunctionExpression node) {
1969 assert(node.parent is! FunctionDeclaration && 1971 assert(node.parent is! FunctionDeclaration &&
1970 node.parent is! MethodDeclaration); 1972 node.parent is! MethodDeclaration);
1971 return _emitFunctionTagged(_emitArrowFunction(node), getStaticType(node), 1973 return _emitFunctionTagged(_emitArrowFunction(node), getStaticType(node),
1972 topLevel: _executesAtTopLevel(node)); 1974 topLevel: _executesAtTopLevel(node));
1973 } 1975 }
1974 1976
1975 JS.ArrowFun _emitArrowFunction(FunctionExpression node) { 1977 JS.ArrowFun _emitArrowFunction(FunctionExpression node) {
1976 JS.Fun f = _emitFunctionBody(node.element, node.parameters, node.body); 1978 JS.Fun f = _emitFunctionBody(node.element, node.parameters, node.body);
1977 var body = f.body; 1979 JS.Node body = f.body;
1978 1980
1979 // Simplify `=> { return e; }` to `=> e` 1981 // Simplify `=> { return e; }` to `=> e`
1980 if (body is JS.Block) { 1982 if (body is JS.Block) {
1981 JS.Block block = body; 1983 JS.Block block = body;
1982 if (block.statements.length == 1) { 1984 if (block.statements.length == 1) {
1983 JS.Statement s = block.statements[0]; 1985 JS.Statement s = block.statements[0];
1984 if (s is JS.Return) body = s.value; 1986 if (s is JS.Return) body = s.value;
1985 } 1987 }
1986 } 1988 }
1987 1989
1988 // Convert `function(...) { ... }` to `(...) => ...` 1990 // Convert `function(...) { ... }` to `(...) => ...`
1989 // This is for readability, but it also ensures correct `this` binding. 1991 // This is for readability, but it also ensures correct `this` binding.
1990 var fn = new JS.ArrowFun(f.params, body, 1992 var fn = new JS.ArrowFun(f.params, body,
1991 typeParams: f.typeParams, returnType: f.returnType); 1993 typeParams: f.typeParams, returnType: f.returnType);
1992 1994
1993 return annotate(_makeGenericFunction(fn), node); 1995 return annotate(_makeGenericArrowFun(fn), node);
1994 } 1996 }
1995 1997
1996 JS.FunctionExpression/*=T*/ _makeGenericFunction 1998 JS.ArrowFun _makeGenericArrowFun(JS.ArrowFun fn) {
1997 /*<T extends JS.FunctionExpression>*/(JS.FunctionExpression/*=T*/ fn) { 1999 if (fn.typeParams == null || fn.typeParams.isEmpty) return fn;
2000 return new JS.ArrowFun(fn.typeParams, fn);
2001 }
2002
2003 JS.Fun _makeGenericFunction(JS.Fun fn) {
1998 if (fn.typeParams == null || fn.typeParams.isEmpty) return fn; 2004 if (fn.typeParams == null || fn.typeParams.isEmpty) return fn;
1999 2005
2000 // TODO(jmesserly): we could make these default to `dynamic`. 2006 // TODO(jmesserly): we could make these default to `dynamic`.
2001 var typeParams = fn.typeParams;
2002 if (fn is JS.ArrowFun) {
2003 return new JS.ArrowFun(typeParams, fn);
2004 }
2005 var f = fn as JS.Fun;
2006 return new JS.Fun( 2007 return new JS.Fun(
2007 typeParams, 2008 fn.typeParams,
2008 new JS.Block([ 2009 new JS.Block([
2009 // Convert the function to an => function, to ensure `this` binding. 2010 // Convert the function to an => function, to ensure `this` binding.
2010 new JS.Return(new JS.ArrowFun(f.params, f.body, 2011 new JS.Return(new JS.ArrowFun(fn.params, fn.body,
2011 typeParams: f.typeParams, returnType: f.returnType)) 2012 typeParams: fn.typeParams, returnType: fn.returnType))
2012 ])); 2013 ]));
2013 } 2014 }
2014 2015
2015 /// Emits a non-arrow FunctionExpression node. 2016 /// Emits a non-arrow FunctionExpression node.
2016 /// 2017 ///
2017 /// This should be used for all places in Dart's AST where FunctionExpression 2018 /// This should be used for all places in Dart's AST where FunctionExpression
2018 /// appears but the function is not actually in an Expression context, such 2019 /// appears but the function is not actually in an Expression context, such
2019 /// as methods, properties, and top-level functions. 2020 /// as methods, properties, and top-level functions.
2020 /// 2021 ///
2021 /// Contrast with [visitFunctionExpression]. 2022 /// Contrast with [visitFunctionExpression].
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2075 // In the body of a `sync*` and `async`, `yield`/`await` are both generated 2076 // In the body of a `sync*` and `async`, `yield`/`await` are both generated
2076 // simply as `yield`. 2077 // simply as `yield`.
2077 // 2078 //
2078 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream` 2079 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream`
2079 // argument to the generator, which is used for passing values to the 2080 // argument to the generator, which is used for passing values to the
2080 // _AsyncStarStreamController implementation type. 2081 // _AsyncStarStreamController implementation type.
2081 // `yield` is specially generated inside `async*`, see visitYieldStatement. 2082 // `yield` is specially generated inside `async*`, see visitYieldStatement.
2082 // `await` is generated as `yield`. 2083 // `await` is generated as `yield`.
2083 // runtime/_generators.js has an example of what the code is generated as. 2084 // runtime/_generators.js has an example of what the code is generated as.
2084 var savedController = _asyncStarController; 2085 var savedController = _asyncStarController;
2085 List jsParams = visitFormalParameterList(parameters); 2086 var jsParams = visitFormalParameterList(parameters);
2086 if (kind == 'asyncStar') { 2087 if (kind == 'asyncStar') {
2087 _asyncStarController = new JS.TemporaryId('stream'); 2088 _asyncStarController = new JS.TemporaryId('stream');
2088 jsParams.insert(0, _asyncStarController); 2089 jsParams.insert(0, _asyncStarController);
2089 } else { 2090 } else {
2090 _asyncStarController = null; 2091 _asyncStarController = null;
2091 } 2092 }
2092 var savedSuperAllowed = _superAllowed; 2093 var savedSuperAllowed = _superAllowed;
2093 _superAllowed = false; 2094 _superAllowed = false;
2094 // Visit the body with our async* controller set. 2095 // Visit the body with our async* controller set.
2095 var jsBody = _visit(body); 2096 var jsBody = _visit(body);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2269 List<DartType> types, List<FormalParameter> parameters, 2270 List<DartType> types, List<FormalParameter> parameters,
2270 {bool nameType: true, bool hoistType: true}) { 2271 {bool nameType: true, bool hoistType: true}) {
2271 var result = <JS.Expression>[]; 2272 var result = <JS.Expression>[];
2272 for (int i = 0; i < types.length; ++i) { 2273 for (int i = 0; i < types.length; ++i) {
2273 var metadata = 2274 var metadata =
2274 parameters != null ? _parameterMetadata(parameters[i]) : []; 2275 parameters != null ? _parameterMetadata(parameters[i]) : [];
2275 var typeName = 2276 var typeName =
2276 _emitType(types[i], nameType: nameType, hoistType: hoistType); 2277 _emitType(types[i], nameType: nameType, hoistType: hoistType);
2277 var value = typeName; 2278 var value = typeName;
2278 if (options.emitMetadata && metadata.isNotEmpty) { 2279 if (options.emitMetadata && metadata.isNotEmpty) {
2279 metadata = metadata.map(_instantiateAnnotation).toList(); 2280 value = new JS.ArrayInitializer(
2280 value = new JS.ArrayInitializer([typeName]..addAll(metadata)); 2281 [typeName]..addAll(metadata.map(_instantiateAnnotation)));
2281 } 2282 }
2282 result.add(value); 2283 result.add(value);
2283 } 2284 }
2284 return new JS.ArrayInitializer(result); 2285 return new JS.ArrayInitializer(result);
2285 } 2286 }
2286 2287
2287 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { 2288 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) {
2288 var properties = <JS.Property>[]; 2289 var properties = <JS.Property>[];
2289 types.forEach((name, type) { 2290 types.forEach((name, type) {
2290 var key = _propertyName(name); 2291 var key = _propertyName(name);
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
2580 2581
2581 var target = _getTarget(node); 2582 var target = _getTarget(node);
2582 if (target == null || isLibraryPrefix(target)) { 2583 if (target == null || isLibraryPrefix(target)) {
2583 return _emitFunctionCall(node); 2584 return _emitFunctionCall(node);
2584 } 2585 }
2585 2586
2586 return _emitMethodCall(target, node); 2587 return _emitMethodCall(target, node);
2587 } 2588 }
2588 2589
2589 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { 2590 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
2590 List<JS.Expression> args = _visit(node.argumentList); 2591 var args = _visit(node.argumentList) as List<JS.Expression>;
2591 var typeArgs = _emitInvokeTypeArguments(node); 2592 var typeArgs = _emitInvokeTypeArguments(node);
2592 2593
2593 if (target is SuperExpression && !_superAllowed) { 2594 if (target is SuperExpression && !_superAllowed) {
2594 return _emitSuperHelperCall(typeArgs, args, target, node); 2595 return _emitSuperHelperCall(typeArgs, args, target, node);
2595 } 2596 }
2596 2597
2597 return _emitMethodCallInternal(target, node, args, typeArgs); 2598 return _emitMethodCallInternal(target, node, args, typeArgs);
2598 } 2599 }
2599 2600
2600 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs, 2601 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2662 jsTarget = new JS.PropertyAccess(jsTarget, memberName); 2663 jsTarget = new JS.PropertyAccess(jsTarget, memberName);
2663 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); 2664 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
2664 2665
2665 return new JS.Call(jsTarget, args); 2666 return new JS.Call(jsTarget, args);
2666 } 2667 }
2667 2668
2668 /// Emits a function call, to a top-level function, local function, or 2669 /// Emits a function call, to a top-level function, local function, or
2669 /// an expression. 2670 /// an expression.
2670 JS.Expression _emitFunctionCall(InvocationExpression node) { 2671 JS.Expression _emitFunctionCall(InvocationExpression node) {
2671 var fn = _visit(node.function); 2672 var fn = _visit(node.function);
2672 var args = _visit(node.argumentList); 2673 var args = _visit(node.argumentList) as List<JS.Expression>;
2673 if (DynamicInvoke.get(node.function)) { 2674 if (DynamicInvoke.get(node.function)) {
2674 var typeArgs = _emitInvokeTypeArguments(node); 2675 var typeArgs = _emitInvokeTypeArguments(node);
2675 if (typeArgs != null) { 2676 if (typeArgs != null) {
2676 return js.call('dart.dgcall(#, #, #)', 2677 return js.call('dart.dgcall(#, #, #)',
2677 [fn, new JS.ArrayInitializer(typeArgs), args]); 2678 [fn, new JS.ArrayInitializer(typeArgs), args]);
2678 } else { 2679 } else {
2679 return js.call('dart.dcall(#, #)', [fn, args]); 2680 return js.call('dart.dcall(#, #)', [fn, args]);
2680 } 2681 }
2681 } else { 2682 } else {
2682 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); 2683 return new JS.Call(_applyInvokeTypeArguments(fn, node), args);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2739 return f.typeArguments.skip(g.typeArguments.length); 2740 return f.typeArguments.skip(g.typeArguments.length);
2740 } 2741 }
2741 2742
2742 /// Emits code for the `JS(...)` macro. 2743 /// Emits code for the `JS(...)` macro.
2743 _emitForeignJS(MethodInvocation node) { 2744 _emitForeignJS(MethodInvocation node) {
2744 var e = node.methodName.staticElement; 2745 var e = node.methodName.staticElement;
2745 if (isInlineJS(e)) { 2746 if (isInlineJS(e)) {
2746 var args = node.argumentList.arguments; 2747 var args = node.argumentList.arguments;
2747 // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer` 2748 // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer`
2748 var code = args[1]; 2749 var code = args[1];
2749 var templateArgs; 2750 List<AstNode> templateArgs;
2750 var source; 2751 var source;
2751 if (code is StringInterpolation) { 2752 if (code is StringInterpolation) {
2752 if (args.length > 2) { 2753 if (args.length > 2) {
2753 throw new ArgumentError( 2754 throw new ArgumentError(
2754 "Can't mix template args and string interpolation in JS calls."); 2755 "Can't mix template args and string interpolation in JS calls.");
2755 } 2756 }
2756 templateArgs = <Expression>[]; 2757 templateArgs = <Expression>[];
2757 source = code.elements.map((element) { 2758 source = code.elements.map((element) {
2758 if (element is InterpolationExpression) { 2759 if (element is InterpolationExpression) {
2759 templateArgs.add(element.expression); 2760 templateArgs.add(element.expression);
2760 return '#'; 2761 return '#';
2761 } else { 2762 } else {
2762 return (element as InterpolationString).value; 2763 return (element as InterpolationString).value;
2763 } 2764 }
2764 }).join(); 2765 }).join();
2765 } else { 2766 } else {
2766 templateArgs = args.skip(2); 2767 templateArgs = args.skip(2).toList();
2767 source = (code as StringLiteral).stringValue; 2768 source = (code as StringLiteral).stringValue;
2768 } 2769 }
2769 2770
2770 // TODO(rnystrom): The JS() calls are almost never nested, and probably 2771 // TODO(rnystrom): The JS() calls are almost never nested, and probably
2771 // really shouldn't be, but there are at least a couple of calls in the 2772 // really shouldn't be, but there are at least a couple of calls in the
2772 // HTML library where an argument to JS() is itself a JS() call. If those 2773 // HTML library where an argument to JS() is itself a JS() call. If those
2773 // go away, this can just assert(!_isInForeignJS). 2774 // go away, this can just assert(!_isInForeignJS).
2774 // Inside JS(), type names evaluate to the raw runtime type, not the 2775 // Inside JS(), type names evaluate to the raw runtime type, not the
2775 // wrapped Type object. 2776 // wrapped Type object.
2776 var wasInForeignJS = _isInForeignJS; 2777 var wasInForeignJS = _isInForeignJS;
(...skipping 1253 matching lines...) Expand 10 before | Expand all | Expand 10 after
4030 // await iter.cancel(); 4031 // await iter.cancel();
4031 // } 4032 // }
4032 // 4033 //
4033 // Like the Dart VM, we call cancel() always, as it's safe to call if the 4034 // Like the Dart VM, we call cancel() always, as it's safe to call if the
4034 // stream has already been cancelled. 4035 // stream has already been cancelled.
4035 // 4036 //
4036 // TODO(jmesserly): we may want a helper if these become common. For now the 4037 // TODO(jmesserly): we may want a helper if these become common. For now the
4037 // full desugaring seems okay. 4038 // full desugaring seems okay.
4038 var streamIterator = rules.instantiateToBounds(_asyncStreamIterator); 4039 var streamIterator = rules.instantiateToBounds(_asyncStreamIterator);
4039 var createStreamIter = _emitInstanceCreationExpression( 4040 var createStreamIter = _emitInstanceCreationExpression(
4040 streamIterator.element.unnamedConstructor, 4041 (streamIterator.element as ClassElement).unnamedConstructor,
4041 streamIterator, 4042 streamIterator,
4042 null, 4043 null,
4043 AstBuilder.argumentList([node.iterable]), 4044 AstBuilder.argumentList([node.iterable]),
4044 false); 4045 false);
4045 var iter = _visit(_createTemporary('it', streamIterator, nullable: false)); 4046 var iter = _visit(_createTemporary('it', streamIterator, nullable: false));
4046 4047
4047 var init = _visit(node.identifier); 4048 var init = _visit(node.identifier);
4048 if (init == null) { 4049 if (init == null) {
4049 init = js 4050 init = js
4050 .call('let # = #.current', [node.loopVariable.identifier.name, iter]); 4051 .call('let # = #.current', [node.loopVariable.identifier.name, iter]);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
4326 _visit(AstNode node) { 4327 _visit(AstNode node) {
4327 if (node == null) return null; 4328 if (node == null) return null;
4328 var result = node.accept(this); 4329 var result = node.accept(this);
4329 if (result is JS.Node) result = annotate(result, node); 4330 if (result is JS.Node) result = annotate(result, node);
4330 return result; 4331 return result;
4331 } 4332 }
4332 4333
4333 List/*<T>*/ _visitList/*<T extends AstNode>*/(Iterable/*<T>*/ nodes) { 4334 List/*<T>*/ _visitList/*<T extends AstNode>*/(Iterable/*<T>*/ nodes) {
4334 if (nodes == null) return null; 4335 if (nodes == null) return null;
4335 var result = /*<T>*/ []; 4336 var result = /*<T>*/ [];
4336 for (var node in nodes) result.add(_visit(node)); 4337 for (var node in nodes) result.add(_visit(node) as dynamic/*=T*/);
4337 return result; 4338 return result;
4338 } 4339 }
4339 4340
4340 /// Visits a list of expressions, creating a comma expression if needed in JS. 4341 /// Visits a list of expressions, creating a comma expression if needed in JS.
4341 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { 4342 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) {
4342 if (nodes == null || nodes.isEmpty) return null; 4343 if (nodes == null || nodes.isEmpty) return null;
4343 return new JS.Expression.binary( 4344 return new JS.Expression.binary(
4344 _visitList(nodes) as List<JS.Expression>, operator); 4345 _visitList(nodes) as List<JS.Expression>, operator);
4345 } 4346 }
4346 4347
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
4459 // conflict. We could use practically any character for this. 4460 // conflict. We could use practically any character for this.
4460 name = '+$name'; 4461 name = '+$name';
4461 } 4462 }
4462 4463
4463 var result = _propertyName(name); 4464 var result = _propertyName(name);
4464 4465
4465 if (useExtension == null) { 4466 if (useExtension == null) {
4466 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 4467 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
4467 var baseType = type; 4468 var baseType = type;
4468 while (baseType is TypeParameterType) { 4469 while (baseType is TypeParameterType) {
4469 baseType = baseType.element.bound; 4470 baseType = (baseType.element as TypeParameterElement).bound;
4470 } 4471 }
4471 useExtension = baseType != null && 4472 useExtension = baseType != null &&
4472 _extensionTypes.hasNativeSubtype(baseType) && 4473 _extensionTypes.hasNativeSubtype(baseType) &&
4473 !isObjectMember(name); 4474 !isObjectMember(name);
4474 } 4475 }
4475 4476
4476 return useExtension ? js.call('dartx.#', result) : result; 4477 return useExtension ? js.call('dartx.#', result) : result;
4477 } 4478 }
4478 4479
4479 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) { 4480 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) {
(...skipping 19 matching lines...) Expand all
4499 return _libraries[library] ?? 4500 return _libraries[library] ??
4500 _imports.putIfAbsent(library, 4501 _imports.putIfAbsent(library,
4501 () => new JS.TemporaryId(jsLibraryName(_buildRoot, library))); 4502 () => new JS.TemporaryId(jsLibraryName(_buildRoot, library)));
4502 } 4503 }
4503 4504
4504 JS.Node/*=T*/ annotate/*<T extends JS.Node>*/( 4505 JS.Node/*=T*/ annotate/*<T extends JS.Node>*/(
4505 JS.Node/*=T*/ node, AstNode original, 4506 JS.Node/*=T*/ node, AstNode original,
4506 [Element element]) { 4507 [Element element]) {
4507 if (options.closure && element != null) { 4508 if (options.closure && element != null) {
4508 node = node.withClosureAnnotation(closureAnnotationFor( 4509 node = node.withClosureAnnotation(closureAnnotationFor(
4509 node, original, element, namedArgumentTemp.name)); 4510 node, original, element, namedArgumentTemp.name)) as dynamic/*=T*/;
4510 } 4511 }
4511 return node..sourceInformation = original; 4512 return node..sourceInformation = original;
4512 } 4513 }
4513 4514
4514 /// Returns true if this is any kind of object represented by `Number` in JS. 4515 /// Returns true if this is any kind of object represented by `Number` in JS.
4515 /// 4516 ///
4516 /// In practice, this is 4 types: num, int, double, and JSNumber. 4517 /// In practice, this is 4 types: num, int, double, and JSNumber.
4517 /// 4518 ///
4518 /// JSNumber is the type that actually "implements" all numbers, hence it's 4519 /// JSNumber is the type that actually "implements" all numbers, hence it's
4519 /// a subtype of int and double (and num). It's in our "dart:_interceptors". 4520 /// a subtype of int and double (and num). It's in our "dart:_interceptors".
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
4627 } 4628 }
4628 4629
4629 bool isLibraryPrefix(Expression node) => 4630 bool isLibraryPrefix(Expression node) =>
4630 node is SimpleIdentifier && node.staticElement is PrefixElement; 4631 node is SimpleIdentifier && node.staticElement is PrefixElement;
4631 4632
4632 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4633 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4633 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4634 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4634 4635
4635 bool _isDartRuntime(LibraryElement l) => 4636 bool _isDartRuntime(LibraryElement l) =>
4636 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4637 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698