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

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, 7 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
« no previous file with comments | « lib/src/analyzer/context.dart ('k') | lib/src/compiler/element_helpers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 return module; 278 return module;
279 } 279 }
280 } 280 }
281 281
282 List<String> _getJSName(Element e) { 282 List<String> _getJSName(Element e) {
283 if (findAnnotation(e.library, isPublicJSAnnotation) == null) { 283 if (findAnnotation(e.library, isPublicJSAnnotation) == null) {
284 return null; 284 return null;
285 } 285 }
286 286
287 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation); 287 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation);
288 var libraryPrefix = []; 288 var libraryPrefix = <String>[];
289 if (libraryJSName != null && libraryJSName.isNotEmpty) { 289 if (libraryJSName != null && libraryJSName.isNotEmpty) {
290 libraryPrefix.addAll(libraryJSName.split('.')); 290 libraryPrefix.addAll(libraryJSName.split('.'));
291 } 291 }
292 292
293 var elementJSName; 293 String elementJSName;
294 if (findAnnotation(e, isPublicJSAnnotation) != null) { 294 if (findAnnotation(e, isPublicJSAnnotation) != null) {
295 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? ''; 295 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? '';
296 } 296 }
297 if (e is TopLevelVariableElement && 297 if (e is TopLevelVariableElement &&
298 e.getter != null && 298 e.getter != null &&
299 (e.getter.isExternal || 299 (e.getter.isExternal ||
300 findAnnotation(e.getter, isPublicJSAnnotation) != null)) { 300 findAnnotation(e.getter, isPublicJSAnnotation) != null)) {
301 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? ''; 301 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? '';
302 } 302 }
303 if (elementJSName == null) return null; 303 if (elementJSName == null) return null;
304 304
305 var elementJSParts = []; 305 var elementJSParts = <String>[];
306 if (elementJSName.isNotEmpty) { 306 if (elementJSName.isNotEmpty) {
307 elementJSParts.addAll(elementJSName.split('.')); 307 elementJSParts.addAll(elementJSName.split('.'));
308 } else { 308 } else {
309 elementJSParts.add(e.name); 309 elementJSParts.add(e.name);
310 } 310 }
311 311
312 return libraryPrefix..addAll(elementJSParts); 312 return libraryPrefix..addAll(elementJSParts);
313 } 313 }
314 314
315 JS.Expression _emitJSInterop(Element e) { 315 JS.Expression _emitJSInterop(Element e) {
316 var jsName = _getJSName(e); 316 var jsName = _getJSName(e);
317 if (jsName == null) return null; 317 if (jsName == null) return null;
318 var fullName = ['global']..addAll(jsName); 318 var fullName = ['global']..addAll(jsName);
319 var access = _runtimeLibVar; 319 JS.Expression access = _runtimeLibVar;
320 for (var part in fullName) { 320 for (var part in fullName) {
321 access = new JS.PropertyAccess(access, js.string(part)); 321 access = new JS.PropertyAccess(access, js.string(part));
322 } 322 }
323 return access; 323 return access;
324 } 324 }
325 325
326 /// Flattens blocks in [items] to a single list. 326 /// Flattens blocks in [items] to a single list.
327 /// 327 ///
328 /// This will not flatten blocks that are marked as being scopes. 328 /// This will not flatten blocks that are marked as being scopes.
329 void _copyAndFlattenBlocks( 329 void _copyAndFlattenBlocks(
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 692
693 JS.Expression className; 693 JS.Expression className;
694 if (classElem.typeParameters.isNotEmpty) { 694 if (classElem.typeParameters.isNotEmpty) {
695 // Generic classes will be defined inside a function that closes over the 695 // Generic classes will be defined inside a function that closes over the
696 // type parameter. So we can use their local variable name directly. 696 // type parameter. So we can use their local variable name directly.
697 className = new JS.Identifier(classElem.name); 697 className = new JS.Identifier(classElem.name);
698 } else { 698 } else {
699 className = _emitTopLevelName(classElem); 699 className = _emitTopLevelName(classElem);
700 } 700 }
701 701
702 var allFields = new List.from(fields)..addAll(staticFields); 702 var allFields = fields.toList()..addAll(staticFields);
703 var superclasses = getSuperclasses(classElem); 703 var superclasses = getSuperclasses(classElem);
704 var virtualFields = <FieldElement, JS.TemporaryId>{}; 704 var virtualFields = <FieldElement, JS.TemporaryId>{};
705 var virtualFieldSymbols = <JS.Statement>[]; 705 var virtualFieldSymbols = <JS.Statement>[];
706 var staticFieldOverrides = new HashSet<FieldElement>(); 706 var staticFieldOverrides = new HashSet<FieldElement>();
707 _registerPropertyOverrides(classElem, className, superclasses, allFields, 707 _registerPropertyOverrides(classElem, className, superclasses, allFields,
708 virtualFields, virtualFieldSymbols, staticFieldOverrides); 708 virtualFields, virtualFieldSymbols, staticFieldOverrides);
709 709
710 var classExpr = _emitClassExpression(classElem, 710 var classExpr = _emitClassExpression(classElem,
711 _emitClassMethods(node, ctors, fields, superclasses, virtualFields), 711 _emitClassMethods(node, ctors, fields, superclasses, virtualFields),
712 fields: allFields); 712 fields: allFields);
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 /// conflicts. They will be installed as extension methods on the underlying 942 /// conflicts. They will be installed as extension methods on the underlying
943 /// native type. 943 /// native type.
944 List<JS.Method> _emitNativeFieldAccessors(FieldDeclaration node) { 944 List<JS.Method> _emitNativeFieldAccessors(FieldDeclaration node) {
945 // TODO(vsm): Can this by meta-programmed? 945 // TODO(vsm): Can this by meta-programmed?
946 // E.g., dart.nativeField(symbol, jsName) 946 // E.g., dart.nativeField(symbol, jsName)
947 // Alternatively, perhaps it could be meta-programmed directly in 947 // Alternatively, perhaps it could be meta-programmed directly in
948 // dart.registerExtensions? 948 // dart.registerExtensions?
949 var jsMethods = <JS.Method>[]; 949 var jsMethods = <JS.Method>[];
950 if (!node.isStatic) { 950 if (!node.isStatic) {
951 for (var decl in node.fields.variables) { 951 for (var decl in node.fields.variables) {
952 var field = decl.element; 952 var field = decl.element as FieldElement;
953 var name = getAnnotationName(field, isJsName) ?? field.name; 953 var name = getAnnotationName(field, isJsName) ?? field.name;
954 // Generate getter 954 // Generate getter
955 var fn = new JS.Fun([], js.statement('{ return this.#; }', [name])); 955 var fn = new JS.Fun([], js.statement('{ return this.#; }', [name]));
956 var method = 956 var method =
957 new JS.Method(_elementMemberName(field.getter), fn, isGetter: true); 957 new JS.Method(_elementMemberName(field.getter), fn, isGetter: true);
958 jsMethods.add(method); 958 jsMethods.add(method);
959 959
960 // Generate setter 960 // Generate setter
961 if (!decl.isFinal) { 961 if (!decl.isFinal) {
962 var value = new JS.TemporaryId('value'); 962 var value = new JS.TemporaryId('value');
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1344 List<MethodDeclaration> methods, 1344 List<MethodDeclaration> methods,
1345 List<FieldDeclaration> fields, 1345 List<FieldDeclaration> fields,
1346 List<JS.Statement> body) { 1346 List<JS.Statement> body) {
1347 if (_extensionTypes.hasNativeSubtype(classElem.type)) { 1347 if (_extensionTypes.hasNativeSubtype(classElem.type)) {
1348 var dartxNames = <JS.Expression>[]; 1348 var dartxNames = <JS.Expression>[];
1349 for (var m in methods) { 1349 for (var m in methods) {
1350 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 1350 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
1351 dartxNames.add(_elementMemberName(m.element, useExtension: false)); 1351 dartxNames.add(_elementMemberName(m.element, useExtension: false));
1352 } 1352 }
1353 } 1353 }
1354 for (var f in fields) { 1354 for (var fieldDecl in fields) {
1355 if (!f.isStatic) { 1355 if (!fieldDecl.isStatic) {
1356 for (var d in f.fields.variables) { 1356 for (var field in fieldDecl.fields.variables) {
1357 if (d.element.isPublic) { 1357 var e = field.element as FieldElement;
1358 dartxNames.add( 1358 if (e.isPublic) {
1359 _elementMemberName(d.element.getter, useExtension: false)); 1359 dartxNames.add(_elementMemberName(e.getter, useExtension: false));
1360 } 1360 }
1361 } 1361 }
1362 } 1362 }
1363 } 1363 }
1364 if (dartxNames.isNotEmpty) { 1364 if (dartxNames.isNotEmpty) {
1365 body.add(js.statement('dart.defineExtensionNames(#)', 1365 body.add(js.statement('dart.defineExtensionNames(#)',
1366 [new JS.ArrayInitializer(dartxNames, multiline: true)])); 1366 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
1367 } 1367 }
1368 } 1368 }
1369 } 1369 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1535 if (jsSuper != null) body.add(jsSuper); 1535 if (jsSuper != null) body.add(jsSuper);
1536 1536
1537 body.add(_visit(node.body)); 1537 body.add(_visit(node.body));
1538 return new JS.Block(body)..sourceInformation = node; 1538 return new JS.Block(body)..sourceInformation = node;
1539 } 1539 }
1540 1540
1541 @override 1541 @override
1542 JS.Statement visitRedirectingConstructorInvocation( 1542 JS.Statement visitRedirectingConstructorInvocation(
1543 RedirectingConstructorInvocation node) { 1543 RedirectingConstructorInvocation node) {
1544 var ctor = node.staticElement; 1544 var ctor = node.staticElement;
1545 var cls = ctor.enclosingElement as ClassElement; 1545 var cls = ctor.enclosingElement;
1546 // We can't dispatch to the constructor with `this.new` as that might hit a 1546 // We can't dispatch to the constructor with `this.new` as that might hit a
1547 // derived class constructor with the same name. 1547 // derived class constructor with the same name.
1548 return js.statement('#.prototype.#.call(this, #);', [ 1548 return js.statement('#.prototype.#.call(this, #);', [
1549 new JS.Identifier(cls.name), 1549 new JS.Identifier(cls.name),
1550 _constructorName(ctor), 1550 _constructorName(ctor),
1551 _visit(node.argumentList) 1551 _visit(node.argumentList)
1552 ]); 1552 ]);
1553 } 1553 }
1554 1554
1555 JS.Statement _superConstructorCall(ClassElement element, 1555 JS.Statement _superConstructorCall(ClassElement element,
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1841 assert(node.parent is CompilationUnit); 1841 assert(node.parent is CompilationUnit);
1842 1842
1843 if (_externalOrNative(node)) return null; 1843 if (_externalOrNative(node)) return null;
1844 1844
1845 // If we have a getter/setter pair, they need to be defined together. 1845 // If we have a getter/setter pair, they need to be defined together.
1846 if (node.isGetter) { 1846 if (node.isGetter) {
1847 PropertyAccessorElement element = node.element; 1847 PropertyAccessorElement element = node.element;
1848 var props = <JS.Method>[_emitTopLevelProperty(node)]; 1848 var props = <JS.Method>[_emitTopLevelProperty(node)];
1849 var setter = element.correspondingSetter; 1849 var setter = element.correspondingSetter;
1850 if (setter != null) { 1850 if (setter != null) {
1851 props.add(_loader.emitDeclaration(setter, _emitTopLevelProperty)); 1851 props.add(_loader.emitDeclaration(
1852 setter, (node) => _emitTopLevelProperty(node)));
1852 } 1853 }
1853 return js.statement('dart.copyProperties(#, { # });', 1854 return js.statement('dart.copyProperties(#, { # });',
1854 [emitLibraryName(currentLibrary), props]); 1855 [emitLibraryName(currentLibrary), props]);
1855 } 1856 }
1856 if (node.isSetter) { 1857 if (node.isSetter) {
1857 PropertyAccessorElement element = node.element; 1858 PropertyAccessorElement element = node.element;
1858 var props = <JS.Method>[_emitTopLevelProperty(node)]; 1859 var props = <JS.Method>[_emitTopLevelProperty(node)];
1859 var getter = element.correspondingGetter; 1860 var getter = element.correspondingGetter;
1860 if (getter != null) { 1861 if (getter != null) {
1861 props.add(_loader.emitDeclaration(getter, _emitTopLevelProperty)); 1862 props.add(_loader.emitDeclaration(
1863 getter, (node) => _emitTopLevelProperty(node)));
1862 } 1864 }
1863 return js.statement('dart.copyProperties(#, { # });', 1865 return js.statement('dart.copyProperties(#, { # });',
1864 [emitLibraryName(currentLibrary), props]); 1866 [emitLibraryName(currentLibrary), props]);
1865 } 1867 }
1866 1868
1867 var body = <JS.Statement>[]; 1869 var body = <JS.Statement>[];
1868 var fn = _emitFunction(node.functionExpression); 1870 var fn = _emitFunction(node.functionExpression);
1869 1871
1870 if (currentLibrary.source.isInSystemLibrary && 1872 if (currentLibrary.source.isInSystemLibrary &&
1871 _isInlineJSFunction(node.functionExpression)) { 1873 _isInlineJSFunction(node.functionExpression)) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1976 @override 1978 @override
1977 JS.Expression visitFunctionExpression(FunctionExpression node) { 1979 JS.Expression visitFunctionExpression(FunctionExpression node) {
1978 assert(node.parent is! FunctionDeclaration && 1980 assert(node.parent is! FunctionDeclaration &&
1979 node.parent is! MethodDeclaration); 1981 node.parent is! MethodDeclaration);
1980 return _emitFunctionTagged(_emitArrowFunction(node), getStaticType(node), 1982 return _emitFunctionTagged(_emitArrowFunction(node), getStaticType(node),
1981 topLevel: _executesAtTopLevel(node)); 1983 topLevel: _executesAtTopLevel(node));
1982 } 1984 }
1983 1985
1984 JS.ArrowFun _emitArrowFunction(FunctionExpression node) { 1986 JS.ArrowFun _emitArrowFunction(FunctionExpression node) {
1985 JS.Fun f = _emitFunctionBody(node.element, node.parameters, node.body); 1987 JS.Fun f = _emitFunctionBody(node.element, node.parameters, node.body);
1986 var body = f.body; 1988 JS.Node body = f.body;
1987 1989
1988 // Simplify `=> { return e; }` to `=> e` 1990 // Simplify `=> { return e; }` to `=> e`
1989 if (body is JS.Block) { 1991 if (body is JS.Block) {
1990 JS.Block block = body; 1992 JS.Block block = body;
1991 if (block.statements.length == 1) { 1993 if (block.statements.length == 1) {
1992 JS.Statement s = block.statements[0]; 1994 JS.Statement s = block.statements[0];
1993 if (s is JS.Return) body = s.value; 1995 if (s is JS.Return) body = s.value;
1994 } 1996 }
1995 } 1997 }
1996 1998
1997 // Convert `function(...) { ... }` to `(...) => ...` 1999 // Convert `function(...) { ... }` to `(...) => ...`
1998 // This is for readability, but it also ensures correct `this` binding. 2000 // This is for readability, but it also ensures correct `this` binding.
1999 var fn = new JS.ArrowFun(f.params, body, 2001 var fn = new JS.ArrowFun(f.params, body,
2000 typeParams: f.typeParams, returnType: f.returnType); 2002 typeParams: f.typeParams, returnType: f.returnType);
2001 2003
2002 return annotate(_makeGenericFunction(fn), node); 2004 return annotate(_makeGenericArrowFun(fn), node);
2003 } 2005 }
2004 2006
2005 JS.FunctionExpression/*=T*/ _makeGenericFunction 2007 JS.ArrowFun _makeGenericArrowFun(JS.ArrowFun fn) {
2006 /*<T extends JS.FunctionExpression>*/(JS.FunctionExpression/*=T*/ fn) { 2008 if (fn.typeParams == null || fn.typeParams.isEmpty) return fn;
2009 return new JS.ArrowFun(fn.typeParams, fn);
2010 }
2011
2012 JS.Fun _makeGenericFunction(JS.Fun fn) {
2007 if (fn.typeParams == null || fn.typeParams.isEmpty) return fn; 2013 if (fn.typeParams == null || fn.typeParams.isEmpty) return fn;
2008 2014
2009 // TODO(jmesserly): we could make these default to `dynamic`. 2015 // TODO(jmesserly): we could make these default to `dynamic`.
2010 var typeParams = fn.typeParams;
2011 if (fn is JS.ArrowFun) {
2012 return new JS.ArrowFun(typeParams, fn);
2013 }
2014 var f = fn as JS.Fun;
2015 return new JS.Fun( 2016 return new JS.Fun(
2016 typeParams, 2017 fn.typeParams,
2017 new JS.Block([ 2018 new JS.Block([
2018 // Convert the function to an => function, to ensure `this` binding. 2019 // Convert the function to an => function, to ensure `this` binding.
2019 new JS.Return(new JS.ArrowFun(f.params, f.body, 2020 new JS.Return(new JS.ArrowFun(fn.params, fn.body,
2020 typeParams: f.typeParams, returnType: f.returnType)) 2021 typeParams: fn.typeParams, returnType: fn.returnType))
2021 ])); 2022 ]));
2022 } 2023 }
2023 2024
2024 /// Emits a non-arrow FunctionExpression node. 2025 /// Emits a non-arrow FunctionExpression node.
2025 /// 2026 ///
2026 /// This should be used for all places in Dart's AST where FunctionExpression 2027 /// This should be used for all places in Dart's AST where FunctionExpression
2027 /// appears but the function is not actually in an Expression context, such 2028 /// appears but the function is not actually in an Expression context, such
2028 /// as methods, properties, and top-level functions. 2029 /// as methods, properties, and top-level functions.
2029 /// 2030 ///
2030 /// Contrast with [visitFunctionExpression]. 2031 /// Contrast with [visitFunctionExpression].
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 // In the body of a `sync*` and `async`, `yield`/`await` are both generated 2085 // In the body of a `sync*` and `async`, `yield`/`await` are both generated
2085 // simply as `yield`. 2086 // simply as `yield`.
2086 // 2087 //
2087 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream` 2088 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream`
2088 // argument to the generator, which is used for passing values to the 2089 // argument to the generator, which is used for passing values to the
2089 // _AsyncStarStreamController implementation type. 2090 // _AsyncStarStreamController implementation type.
2090 // `yield` is specially generated inside `async*`, see visitYieldStatement. 2091 // `yield` is specially generated inside `async*`, see visitYieldStatement.
2091 // `await` is generated as `yield`. 2092 // `await` is generated as `yield`.
2092 // runtime/_generators.js has an example of what the code is generated as. 2093 // runtime/_generators.js has an example of what the code is generated as.
2093 var savedController = _asyncStarController; 2094 var savedController = _asyncStarController;
2094 List jsParams = visitFormalParameterList(parameters); 2095 var jsParams = visitFormalParameterList(parameters);
2095 if (kind == 'asyncStar') { 2096 if (kind == 'asyncStar') {
2096 _asyncStarController = new JS.TemporaryId('stream'); 2097 _asyncStarController = new JS.TemporaryId('stream');
2097 jsParams.insert(0, _asyncStarController); 2098 jsParams.insert(0, _asyncStarController);
2098 } else { 2099 } else {
2099 _asyncStarController = null; 2100 _asyncStarController = null;
2100 } 2101 }
2101 var savedSuperAllowed = _superAllowed; 2102 var savedSuperAllowed = _superAllowed;
2102 _superAllowed = false; 2103 _superAllowed = false;
2103 // Visit the body with our async* controller set. 2104 // Visit the body with our async* controller set.
2104 var jsBody = _visit(body); 2105 var jsBody = _visit(body);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 List<DartType> types, List<FormalParameter> parameters, 2279 List<DartType> types, List<FormalParameter> parameters,
2279 {bool nameType: true, bool hoistType: true}) { 2280 {bool nameType: true, bool hoistType: true}) {
2280 var result = <JS.Expression>[]; 2281 var result = <JS.Expression>[];
2281 for (int i = 0; i < types.length; ++i) { 2282 for (int i = 0; i < types.length; ++i) {
2282 var metadata = 2283 var metadata =
2283 parameters != null ? _parameterMetadata(parameters[i]) : []; 2284 parameters != null ? _parameterMetadata(parameters[i]) : [];
2284 var typeName = 2285 var typeName =
2285 _emitType(types[i], nameType: nameType, hoistType: hoistType); 2286 _emitType(types[i], nameType: nameType, hoistType: hoistType);
2286 var value = typeName; 2287 var value = typeName;
2287 if (options.emitMetadata && metadata.isNotEmpty) { 2288 if (options.emitMetadata && metadata.isNotEmpty) {
2288 metadata = metadata.map(_instantiateAnnotation).toList(); 2289 value = new JS.ArrayInitializer(
2289 value = new JS.ArrayInitializer([typeName]..addAll(metadata)); 2290 [typeName]..addAll(metadata.map(_instantiateAnnotation)));
2290 } 2291 }
2291 result.add(value); 2292 result.add(value);
2292 } 2293 }
2293 return new JS.ArrayInitializer(result); 2294 return new JS.ArrayInitializer(result);
2294 } 2295 }
2295 2296
2296 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { 2297 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) {
2297 var properties = <JS.Property>[]; 2298 var properties = <JS.Property>[];
2298 types.forEach((name, type) { 2299 types.forEach((name, type) {
2299 var key = _propertyName(name); 2300 var key = _propertyName(name);
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
2592 2593
2593 var target = _getTarget(node); 2594 var target = _getTarget(node);
2594 if (target == null || isLibraryPrefix(target)) { 2595 if (target == null || isLibraryPrefix(target)) {
2595 return _emitFunctionCall(node); 2596 return _emitFunctionCall(node);
2596 } 2597 }
2597 2598
2598 return _emitMethodCall(target, node); 2599 return _emitMethodCall(target, node);
2599 } 2600 }
2600 2601
2601 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { 2602 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) {
2602 List<JS.Expression> args = _visit(node.argumentList); 2603 var args = _visit(node.argumentList) as List<JS.Expression>;
2603 var typeArgs = _emitInvokeTypeArguments(node); 2604 var typeArgs = _emitInvokeTypeArguments(node);
2604 2605
2605 if (target is SuperExpression && !_superAllowed) { 2606 if (target is SuperExpression && !_superAllowed) {
2606 return _emitSuperHelperCall(typeArgs, args, target, node); 2607 return _emitSuperHelperCall(typeArgs, args, target, node);
2607 } 2608 }
2608 2609
2609 return _emitMethodCallInternal(target, node, args, typeArgs); 2610 return _emitMethodCallInternal(target, node, args, typeArgs);
2610 } 2611 }
2611 2612
2612 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs, 2613 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2679 jsTarget = new JS.PropertyAccess(jsTarget, memberName); 2680 jsTarget = new JS.PropertyAccess(jsTarget, memberName);
2680 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs); 2681 if (typeArgs != null) jsTarget = new JS.Call(jsTarget, typeArgs);
2681 2682
2682 return new JS.Call(jsTarget, args); 2683 return new JS.Call(jsTarget, args);
2683 } 2684 }
2684 2685
2685 /// Emits a function call, to a top-level function, local function, or 2686 /// Emits a function call, to a top-level function, local function, or
2686 /// an expression. 2687 /// an expression.
2687 JS.Expression _emitFunctionCall(InvocationExpression node) { 2688 JS.Expression _emitFunctionCall(InvocationExpression node) {
2688 var fn = _visit(node.function); 2689 var fn = _visit(node.function);
2689 var args = _visit(node.argumentList); 2690 var args = _visit(node.argumentList) as List<JS.Expression>;
2690 if (DynamicInvoke.get(node.function)) { 2691 if (DynamicInvoke.get(node.function)) {
2691 var typeArgs = _emitInvokeTypeArguments(node); 2692 var typeArgs = _emitInvokeTypeArguments(node);
2692 if (typeArgs != null) { 2693 if (typeArgs != null) {
2693 return js.call('dart.dgcall(#, #, #)', 2694 return js.call('dart.dgcall(#, #, #)',
2694 [fn, new JS.ArrayInitializer(typeArgs), args]); 2695 [fn, new JS.ArrayInitializer(typeArgs), args]);
2695 } else { 2696 } else {
2696 if (_inAngularTemplate) { 2697 if (_inAngularTemplate) {
2697 return new JS.Call(fn, args); 2698 return new JS.Call(fn, args);
2698 } 2699 }
2699 return js.call('dart.dcall(#, #)', [fn, args]); 2700 return js.call('dart.dcall(#, #)', [fn, args]);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2759 return f.typeArguments.skip(g.typeArguments.length); 2760 return f.typeArguments.skip(g.typeArguments.length);
2760 } 2761 }
2761 2762
2762 /// Emits code for the `JS(...)` macro. 2763 /// Emits code for the `JS(...)` macro.
2763 _emitForeignJS(MethodInvocation node) { 2764 _emitForeignJS(MethodInvocation node) {
2764 var e = node.methodName.staticElement; 2765 var e = node.methodName.staticElement;
2765 if (isInlineJS(e)) { 2766 if (isInlineJS(e)) {
2766 var args = node.argumentList.arguments; 2767 var args = node.argumentList.arguments;
2767 // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer` 2768 // arg[0] is static return type, used in `RestrictedStaticTypeAnalyzer`
2768 var code = args[1]; 2769 var code = args[1];
2769 var templateArgs; 2770 List<AstNode> templateArgs;
2770 var source; 2771 var source;
2771 if (code is StringInterpolation) { 2772 if (code is StringInterpolation) {
2772 if (args.length > 2) { 2773 if (args.length > 2) {
2773 throw new ArgumentError( 2774 throw new ArgumentError(
2774 "Can't mix template args and string interpolation in JS calls."); 2775 "Can't mix template args and string interpolation in JS calls.");
2775 } 2776 }
2776 templateArgs = <Expression>[]; 2777 templateArgs = <Expression>[];
2777 source = code.elements.map((element) { 2778 source = code.elements.map((element) {
2778 if (element is InterpolationExpression) { 2779 if (element is InterpolationExpression) {
2779 templateArgs.add(element.expression); 2780 templateArgs.add(element.expression);
2780 return '#'; 2781 return '#';
2781 } else { 2782 } else {
2782 return (element as InterpolationString).value; 2783 return (element as InterpolationString).value;
2783 } 2784 }
2784 }).join(); 2785 }).join();
2785 } else { 2786 } else {
2786 templateArgs = args.skip(2); 2787 templateArgs = args.skip(2).toList();
2787 source = (code as StringLiteral).stringValue; 2788 source = (code as StringLiteral).stringValue;
2788 } 2789 }
2789 2790
2790 // TODO(rnystrom): The JS() calls are almost never nested, and probably 2791 // TODO(rnystrom): The JS() calls are almost never nested, and probably
2791 // really shouldn't be, but there are at least a couple of calls in the 2792 // really shouldn't be, but there are at least a couple of calls in the
2792 // HTML library where an argument to JS() is itself a JS() call. If those 2793 // HTML library where an argument to JS() is itself a JS() call. If those
2793 // go away, this can just assert(!_isInForeignJS). 2794 // go away, this can just assert(!_isInForeignJS).
2794 // Inside JS(), type names evaluate to the raw runtime type, not the 2795 // Inside JS(), type names evaluate to the raw runtime type, not the
2795 // wrapped Type object. 2796 // wrapped Type object.
2796 var wasInForeignJS = _isInForeignJS; 2797 var wasInForeignJS = _isInForeignJS;
(...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after
4058 // await iter.cancel(); 4059 // await iter.cancel();
4059 // } 4060 // }
4060 // 4061 //
4061 // Like the Dart VM, we call cancel() always, as it's safe to call if the 4062 // Like the Dart VM, we call cancel() always, as it's safe to call if the
4062 // stream has already been cancelled. 4063 // stream has already been cancelled.
4063 // 4064 //
4064 // TODO(jmesserly): we may want a helper if these become common. For now the 4065 // TODO(jmesserly): we may want a helper if these become common. For now the
4065 // full desugaring seems okay. 4066 // full desugaring seems okay.
4066 var streamIterator = rules.instantiateToBounds(_asyncStreamIterator); 4067 var streamIterator = rules.instantiateToBounds(_asyncStreamIterator);
4067 var createStreamIter = _emitInstanceCreationExpression( 4068 var createStreamIter = _emitInstanceCreationExpression(
4068 streamIterator.element.unnamedConstructor, 4069 (streamIterator.element as ClassElement).unnamedConstructor,
4069 streamIterator, 4070 streamIterator,
4070 null, 4071 null,
4071 AstBuilder.argumentList([node.iterable]), 4072 AstBuilder.argumentList([node.iterable]),
4072 false); 4073 false);
4073 var iter = _visit(_createTemporary('it', streamIterator, nullable: false)); 4074 var iter = _visit(_createTemporary('it', streamIterator, nullable: false));
4074 4075
4075 var init = _visit(node.identifier); 4076 var init = _visit(node.identifier);
4076 if (init == null) { 4077 if (init == null) {
4077 init = js 4078 init = js
4078 .call('let # = #.current', [node.loopVariable.identifier.name, iter]); 4079 .call('let # = #.current', [node.loopVariable.identifier.name, iter]);
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
4359 _visit(AstNode node) { 4360 _visit(AstNode node) {
4360 if (node == null) return null; 4361 if (node == null) return null;
4361 var result = node.accept(this); 4362 var result = node.accept(this);
4362 if (result is JS.Node) result = annotate(result, node); 4363 if (result is JS.Node) result = annotate(result, node);
4363 return result; 4364 return result;
4364 } 4365 }
4365 4366
4366 List/*<T>*/ _visitList/*<T extends AstNode>*/(Iterable/*<T>*/ nodes) { 4367 List/*<T>*/ _visitList/*<T extends AstNode>*/(Iterable/*<T>*/ nodes) {
4367 if (nodes == null) return null; 4368 if (nodes == null) return null;
4368 var result = /*<T>*/ []; 4369 var result = /*<T>*/ [];
4369 for (var node in nodes) result.add(_visit(node)); 4370 for (var node in nodes) result.add(_visit(node) as dynamic/*=T*/);
4370 return result; 4371 return result;
4371 } 4372 }
4372 4373
4373 /// Visits a list of expressions, creating a comma expression if needed in JS. 4374 /// Visits a list of expressions, creating a comma expression if needed in JS.
4374 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) { 4375 JS.Expression _visitListToBinary(List<Expression> nodes, String operator) {
4375 if (nodes == null || nodes.isEmpty) return null; 4376 if (nodes == null || nodes.isEmpty) return null;
4376 return new JS.Expression.binary( 4377 return new JS.Expression.binary(
4377 _visitList(nodes) as List<JS.Expression>, operator); 4378 _visitList(nodes) as List<JS.Expression>, operator);
4378 } 4379 }
4379 4380
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
4492 // conflict. We could use practically any character for this. 4493 // conflict. We could use practically any character for this.
4493 name = '+$name'; 4494 name = '+$name';
4494 } 4495 }
4495 4496
4496 var result = _propertyName(name); 4497 var result = _propertyName(name);
4497 4498
4498 if (useExtension == null) { 4499 if (useExtension == null) {
4499 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 4500 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
4500 var baseType = type; 4501 var baseType = type;
4501 while (baseType is TypeParameterType) { 4502 while (baseType is TypeParameterType) {
4502 baseType = baseType.element.bound; 4503 baseType = (baseType.element as TypeParameterElement).bound;
4503 } 4504 }
4504 useExtension = baseType != null && 4505 useExtension = baseType != null &&
4505 _extensionTypes.hasNativeSubtype(baseType) && 4506 _extensionTypes.hasNativeSubtype(baseType) &&
4506 !isObjectMember(name); 4507 !isObjectMember(name);
4507 } 4508 }
4508 4509
4509 return useExtension ? js.call('dartx.#', result) : result; 4510 return useExtension ? js.call('dartx.#', result) : result;
4510 } 4511 }
4511 4512
4512 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) { 4513 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) {
(...skipping 19 matching lines...) Expand all
4532 return _libraries[library] ?? 4533 return _libraries[library] ??
4533 _imports.putIfAbsent(library, 4534 _imports.putIfAbsent(library,
4534 () => new JS.TemporaryId(jsLibraryName(_buildRoot, library))); 4535 () => new JS.TemporaryId(jsLibraryName(_buildRoot, library)));
4535 } 4536 }
4536 4537
4537 JS.Node/*=T*/ annotate/*<T extends JS.Node>*/( 4538 JS.Node/*=T*/ annotate/*<T extends JS.Node>*/(
4538 JS.Node/*=T*/ node, AstNode original, 4539 JS.Node/*=T*/ node, AstNode original,
4539 [Element element]) { 4540 [Element element]) {
4540 if (options.closure && element != null) { 4541 if (options.closure && element != null) {
4541 node = node.withClosureAnnotation(closureAnnotationFor( 4542 node = node.withClosureAnnotation(closureAnnotationFor(
4542 node, original, element, namedArgumentTemp.name)); 4543 node, original, element, namedArgumentTemp.name)) as dynamic/*=T*/;
4543 } 4544 }
4544 return node..sourceInformation = original; 4545 return node..sourceInformation = original;
4545 } 4546 }
4546 4547
4547 /// Returns true if this is any kind of object represented by `Number` in JS. 4548 /// Returns true if this is any kind of object represented by `Number` in JS.
4548 /// 4549 ///
4549 /// In practice, this is 4 types: num, int, double, and JSNumber. 4550 /// In practice, this is 4 types: num, int, double, and JSNumber.
4550 /// 4551 ///
4551 /// JSNumber is the type that actually "implements" all numbers, hence it's 4552 /// JSNumber is the type that actually "implements" all numbers, hence it's
4552 /// a subtype of int and double (and num). It's in our "dart:_interceptors". 4553 /// 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
4660 } 4661 }
4661 4662
4662 bool isLibraryPrefix(Expression node) => 4663 bool isLibraryPrefix(Expression node) =>
4663 node is SimpleIdentifier && node.staticElement is PrefixElement; 4664 node is SimpleIdentifier && node.staticElement is PrefixElement;
4664 4665
4665 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4666 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4666 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4667 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4667 4668
4668 bool _isDartRuntime(LibraryElement l) => 4669 bool _isDartRuntime(LibraryElement l) =>
4669 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4670 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « lib/src/analyzer/context.dart ('k') | lib/src/compiler/element_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698