| OLD | NEW |
| 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 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 if (_isNumberInJS(from) && _isNumberInJS(to)) { | 451 if (_isNumberInJS(from) && _isNumberInJS(to)) { |
| 452 // Make sure to check when converting to int. | 452 // Make sure to check when converting to int. |
| 453 if (from != types.intType && to == types.intType) { | 453 if (from != types.intType && to == types.intType) { |
| 454 return js.call('dart.asInt(#)', [fromExpr]); | 454 return js.call('dart.asInt(#)', [fromExpr]); |
| 455 } | 455 } |
| 456 | 456 |
| 457 // A no-op in JavaScript. | 457 // A no-op in JavaScript. |
| 458 return fromExpr; | 458 return fromExpr; |
| 459 } | 459 } |
| 460 | 460 |
| 461 return js.call('dart.as(#, #)', [fromExpr, _emitTypeName(to)]); | 461 return js.call('dart.as(#, #)', [fromExpr, _emitType(to)]); |
| 462 } | 462 } |
| 463 | 463 |
| 464 @override | 464 @override |
| 465 visitIsExpression(IsExpression node) { | 465 visitIsExpression(IsExpression node) { |
| 466 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. | 466 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. |
| 467 JS.Expression result; | 467 JS.Expression result; |
| 468 var type = node.type.type; | 468 var type = node.type.type; |
| 469 var lhs = _visit(node.expression); | 469 var lhs = _visit(node.expression); |
| 470 var typeofName = _jsTypeofName(type); | 470 var typeofName = _jsTypeofName(type); |
| 471 if (typeofName != null) { | 471 if (typeofName != null) { |
| 472 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]); | 472 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]); |
| 473 } else { | 473 } else { |
| 474 // Always go through a runtime helper, because implicit interfaces. | 474 // Always go through a runtime helper, because implicit interfaces. |
| 475 result = js.call('dart.is(#, #)', [lhs, _emitTypeName(type)]); | 475 result = js.call('dart.is(#, #)', [lhs, _emitType(type)]); |
| 476 } | 476 } |
| 477 | 477 |
| 478 if (node.notOperator != null) { | 478 if (node.notOperator != null) { |
| 479 return js.call('!#', result); | 479 return js.call('!#', result); |
| 480 } | 480 } |
| 481 return result; | 481 return result; |
| 482 } | 482 } |
| 483 | 483 |
| 484 String _jsTypeofName(DartType t) { | 484 String _jsTypeofName(DartType t) { |
| 485 if (_isNumberInJS(t)) return 'number'; | 485 if (_isNumberInJS(t)) return 'number'; |
| 486 if (t == types.stringType) return 'string'; | 486 if (t == types.stringType) return 'string'; |
| 487 if (t == types.boolType) return 'boolean'; | 487 if (t == types.boolType) return 'boolean'; |
| 488 return null; | 488 return null; |
| 489 } | 489 } |
| 490 | 490 |
| 491 @override | 491 @override |
| 492 visitFunctionTypeAlias(FunctionTypeAlias node) { | 492 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 493 FunctionTypeAliasElement element = node.element; | 493 FunctionTypeAliasElement element = node.element; |
| 494 | 494 |
| 495 JS.Expression body = annotate( | 495 JS.Expression body = annotate( |
| 496 js.call('dart.typedef(#, () => #)', [ | 496 js.call('dart.typedef(#, () => #)', [ |
| 497 js.string(element.name, "'"), | 497 js.string(element.name, "'"), |
| 498 _emitTypeName(element.type, lowerTypedef: true) | 498 _emitType(element.type, lowerTypedef: true) |
| 499 ]), | 499 ]), |
| 500 node, | 500 node, |
| 501 element); | 501 element); |
| 502 | 502 |
| 503 var typeFormals = element.typeParameters; | 503 var typeFormals = element.typeParameters; |
| 504 if (typeFormals.isNotEmpty) { | 504 if (typeFormals.isNotEmpty) { |
| 505 return _defineClassTypeArguments(element, typeFormals, | 505 return _defineClassTypeArguments(element, typeFormals, |
| 506 js.statement('const # = #;', [element.name, body])); | 506 js.statement('const # = #;', [element.name, body])); |
| 507 } else { | 507 } else { |
| 508 return js.statement('# = #;', [_emitTopLevelName(element), body]); | 508 return js.statement('# = #;', [_emitTopLevelName(element), body]); |
| 509 } | 509 } |
| 510 } | 510 } |
| 511 | 511 |
| 512 @override | 512 @override |
| 513 JS.Expression visitTypeName(TypeName node) { | 513 JS.Expression visitTypeName(TypeName node) { |
| 514 // TODO(jmesserly): should only happen for erroneous code. | 514 // TODO(jmesserly): should only happen for erroneous code. |
| 515 if (node.type == null) return js.call('dart.dynamic'); | 515 if (node.type == null) return js.call('dart.dynamic'); |
| 516 return _emitTypeName(node.type); | 516 return _emitType(node.type); |
| 517 } | 517 } |
| 518 | 518 |
| 519 @override | 519 @override |
| 520 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { | 520 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { |
| 521 ClassElement element = node.element; | 521 ClassElement element = node.element; |
| 522 | 522 |
| 523 // Forward all generative constructors from the base class. | 523 // Forward all generative constructors from the base class. |
| 524 var methods = <JS.Method>[]; | 524 var methods = <JS.Method>[]; |
| 525 | 525 |
| 526 var supertype = element.supertype; | 526 var supertype = element.supertype; |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 // Create static fields for each enum value | 734 // Create static fields for each enum value |
| 735 for (var i = 0; i < fields.length; ++i) { | 735 for (var i = 0; i < fields.length; ++i) { |
| 736 result.add(js.statement('#.# = dart.const(new #(#));', | 736 result.add(js.statement('#.# = dart.const(new #(#));', |
| 737 [id, fields[i].name, id, js.number(i)])); | 737 [id, fields[i].name, id, js.number(i)])); |
| 738 } | 738 } |
| 739 | 739 |
| 740 // Create static values list | 740 // Create static values list |
| 741 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( | 741 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( |
| 742 fields.map((f) => js.call('#.#', [id, f.name])))); | 742 fields.map((f) => js.call('#.#', [id, f.name])))); |
| 743 result.add(js.statement('#.values = dart.const(dart.list(#, #));', | 743 result.add(js.statement('#.values = dart.const(dart.list(#, #));', |
| 744 [id, values, _emitTypeName(type)])); | 744 [id, values, _emitType(type)])); |
| 745 | 745 |
| 746 return _statement(result); | 746 return _statement(result); |
| 747 } | 747 } |
| 748 | 748 |
| 749 /// Wraps a possibly generic class in its type arguments. | 749 /// Wraps a possibly generic class in its type arguments. |
| 750 JS.Statement _defineClassTypeArguments(TypeDefiningElement element, | 750 JS.Statement _defineClassTypeArguments(TypeDefiningElement element, |
| 751 List<TypeParameterElement> formals, JS.Statement body) { | 751 List<TypeParameterElement> formals, JS.Statement body) { |
| 752 assert(formals.isNotEmpty); | 752 assert(formals.isNotEmpty); |
| 753 var genericDef = | 753 var genericDef = |
| 754 js.statement('# = dart.generic((#) => { #; return #; });', [ | 754 js.statement('# = dart.generic((#) => { #; return #; });', [ |
| 755 _emitTopLevelName(element, suffix: r'$'), | 755 _emitTopLevelName(element, suffix: r'$'), |
| 756 _emitTypeFormals(formals), | 756 _emitTypeFormals(formals), |
| 757 body, | 757 body, |
| 758 element.name | 758 element.name |
| 759 ]); | 759 ]); |
| 760 | 760 |
| 761 var dynType = fillDynamicTypeArgs(element.type); | 761 var dynType = fillDynamicTypeArgs(element.type); |
| 762 var genericInst = _emitTypeName(dynType, lowerGeneric: true); | 762 var genericInst = _emitType(dynType, lowerGeneric: true); |
| 763 return js.statement( | 763 return js.statement( |
| 764 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); | 764 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); |
| 765 } | 765 } |
| 766 | 766 |
| 767 bool _deferIfNeeded(DartType type, ClassElement current) { | 767 bool _deferIfNeeded(DartType type, ClassElement current) { |
| 768 if (type is ParameterizedType) { | 768 if (type is ParameterizedType) { |
| 769 var typeArguments = type.typeArguments; | 769 var typeArguments = type.typeArguments; |
| 770 for (var typeArg in typeArguments) { | 770 for (var typeArg in typeArguments) { |
| 771 var typeElement = typeArg.element; | 771 var typeElement = typeArg.element; |
| 772 // FIXME(vsm): This does not track mutual recursive dependences. | 772 // FIXME(vsm): This does not track mutual recursive dependences. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 797 _loader.startTopLevel(element); | 797 _loader.startTopLevel(element); |
| 798 | 798 |
| 799 // Find the super type | 799 // Find the super type |
| 800 JS.Expression heritage; | 800 JS.Expression heritage; |
| 801 var supertype = type.superclass; | 801 var supertype = type.superclass; |
| 802 if (_deferIfNeeded(supertype, element)) { | 802 if (_deferIfNeeded(supertype, element)) { |
| 803 // Fall back to raw type. | 803 // Fall back to raw type. |
| 804 supertype = fillDynamicTypeArgs(supertype.element.type); | 804 supertype = fillDynamicTypeArgs(supertype.element.type); |
| 805 _hasDeferredSupertype.add(element); | 805 _hasDeferredSupertype.add(element); |
| 806 } | 806 } |
| 807 heritage = _emitTypeName(supertype); | 807 heritage = _emitType(supertype); |
| 808 | 808 |
| 809 if (type.mixins.isNotEmpty) { | 809 if (type.mixins.isNotEmpty) { |
| 810 var mixins = type.mixins.map(_emitTypeName).toList(); | 810 var mixins = type.mixins.map(_emitType).toList(); |
| 811 mixins.insert(0, heritage); | 811 mixins.insert(0, heritage); |
| 812 heritage = js.call('dart.mixin(#)', [mixins]); | 812 heritage = js.call('dart.mixin(#)', [mixins]); |
| 813 } | 813 } |
| 814 | 814 |
| 815 _loader.finishTopLevel(element); | 815 _loader.finishTopLevel(element); |
| 816 | 816 |
| 817 return heritage; | 817 return heritage; |
| 818 } | 818 } |
| 819 | 819 |
| 820 /// Provide Dart getters and setters that forward to the underlying native | 820 /// Provide Dart getters and setters that forward to the underlying native |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 } | 1044 } |
| 1045 | 1045 |
| 1046 void _setBaseClass(ClassElement classElem, JS.Expression className, | 1046 void _setBaseClass(ClassElement classElem, JS.Expression className, |
| 1047 List<JS.Statement> body) { | 1047 List<JS.Statement> body) { |
| 1048 String jsPeerName = _getJSPeerName(classElem); | 1048 String jsPeerName = _getJSPeerName(classElem); |
| 1049 JS.Expression newBaseClass; | 1049 JS.Expression newBaseClass; |
| 1050 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { | 1050 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { |
| 1051 // TODO(jmesserly): we should really just extend Array in the first place. | 1051 // TODO(jmesserly): we should really just extend Array in the first place. |
| 1052 newBaseClass = js.call('dart.global.#', [jsPeerName]); | 1052 newBaseClass = js.call('dart.global.#', [jsPeerName]); |
| 1053 } else if (_hasDeferredSupertype.contains(classElem)) { | 1053 } else if (_hasDeferredSupertype.contains(classElem)) { |
| 1054 newBaseClass = _emitTypeName(classElem.type.superclass); | 1054 newBaseClass = _emitType(classElem.type.superclass, |
| 1055 subClass: classElem, className: className); |
| 1055 } | 1056 } |
| 1056 if (newBaseClass != null) { | 1057 if (newBaseClass != null) { |
| 1057 body.add( | 1058 body.add( |
| 1058 js.statement('dart.setBaseClass(#, #);', [className, newBaseClass])); | 1059 js.statement('dart.setBaseClass(#, #);', [className, newBaseClass])); |
| 1059 } | 1060 } |
| 1060 } | 1061 } |
| 1061 | 1062 |
| 1062 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, | 1063 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, |
| 1063 List<JS.Statement> body, JS.Expression className) { | 1064 List<JS.Statement> body, JS.Expression className) { |
| 1064 for (ConstructorDeclaration member in ctors) { | 1065 for (ConstructorDeclaration member in ctors) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 List<MethodDeclaration> methods, | 1130 List<MethodDeclaration> methods, |
| 1130 ClassElement classElem, | 1131 ClassElement classElem, |
| 1131 List<ConstructorDeclaration> ctors, | 1132 List<ConstructorDeclaration> ctors, |
| 1132 List<ExecutableElement> extensions, | 1133 List<ExecutableElement> extensions, |
| 1133 JS.Expression className, | 1134 JS.Expression className, |
| 1134 List<JS.Statement> body) { | 1135 List<JS.Statement> body) { |
| 1135 if (classElem.interfaces.isNotEmpty) { | 1136 if (classElem.interfaces.isNotEmpty) { |
| 1136 body.add(js.statement('#[dart.implements] = () => #;', [ | 1137 body.add(js.statement('#[dart.implements] = () => #;', [ |
| 1137 className, | 1138 className, |
| 1138 new JS.ArrayInitializer(new List<JS.Expression>.from( | 1139 new JS.ArrayInitializer(new List<JS.Expression>.from( |
| 1139 classElem.interfaces.map(_emitTypeName))) | 1140 classElem.interfaces.map(_emitType))) |
| 1140 ])); | 1141 ])); |
| 1141 } | 1142 } |
| 1142 | 1143 |
| 1143 var tStatics = <JS.Property>[]; | 1144 var tStatics = <JS.Property>[]; |
| 1144 var tMethods = <JS.Property>[]; | 1145 var tMethods = <JS.Property>[]; |
| 1145 var sNames = <JS.Expression>[]; | 1146 var sNames = <JS.Expression>[]; |
| 1146 for (MethodDeclaration node in methods) { | 1147 for (MethodDeclaration node in methods) { |
| 1147 if (!(node.isSetter || node.isGetter || node.isAbstract)) { | 1148 if (!(node.isSetter || node.isGetter || node.isAbstract)) { |
| 1148 var name = node.name.name; | 1149 var name = node.name.name; |
| 1149 var element = node.element; | 1150 var element = node.element; |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 body.add(js.statement('if (# === void 0) # = #;', | 1602 body.add(js.statement('if (# === void 0) # = #;', |
| 1602 [jsParam, jsParam, _defaultParamValue(param)])); | 1603 [jsParam, jsParam, _defaultParamValue(param)])); |
| 1603 } | 1604 } |
| 1604 } | 1605 } |
| 1605 | 1606 |
| 1606 // TODO(jmesserly): various problems here, see: | 1607 // TODO(jmesserly): various problems here, see: |
| 1607 // https://github.com/dart-lang/dev_compiler/issues/161 | 1608 // https://github.com/dart-lang/dev_compiler/issues/161 |
| 1608 var paramType = param.element.type; | 1609 var paramType = param.element.type; |
| 1609 if (!constructor && _hasUnsoundTypeParameter(paramType)) { | 1610 if (!constructor && _hasUnsoundTypeParameter(paramType)) { |
| 1610 body.add(js | 1611 body.add(js |
| 1611 .statement('dart.as(#, #);', [jsParam, _emitTypeName(paramType)])); | 1612 .statement('dart.as(#, #);', [jsParam, _emitType(paramType)])); |
| 1612 } | 1613 } |
| 1613 } | 1614 } |
| 1614 return body.isEmpty ? null : _statement(body); | 1615 return body.isEmpty ? null : _statement(body); |
| 1615 } | 1616 } |
| 1616 | 1617 |
| 1617 bool _isUnsoundTypeParameter(DartType t) => | 1618 bool _isUnsoundTypeParameter(DartType t) => |
| 1618 t is TypeParameterType && t.element.enclosingElement is ClassElement; | 1619 t is TypeParameterType && t.element.enclosingElement is ClassElement; |
| 1619 | 1620 |
| 1620 bool _hasUnsoundTypeParameter(DartType t) => | 1621 bool _hasUnsoundTypeParameter(DartType t) => |
| 1621 _isUnsoundTypeParameter(t) || | 1622 _isUnsoundTypeParameter(t) || |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1982 _superAllowed = savedSuperAllowed; | 1983 _superAllowed = savedSuperAllowed; |
| 1983 _asyncStarController = savedController; | 1984 _asyncStarController = savedController; |
| 1984 | 1985 |
| 1985 DartType returnType = _getExpectedReturnType(element); | 1986 DartType returnType = _getExpectedReturnType(element); |
| 1986 JS.Expression gen = new JS.Fun(jsParams, jsBody, | 1987 JS.Expression gen = new JS.Fun(jsParams, jsBody, |
| 1987 isGenerator: true, returnType: emitTypeRef(returnType)); | 1988 isGenerator: true, returnType: emitTypeRef(returnType)); |
| 1988 if (JS.This.foundIn(gen)) { | 1989 if (JS.This.foundIn(gen)) { |
| 1989 gen = js.call('#.bind(this)', gen); | 1990 gen = js.call('#.bind(this)', gen); |
| 1990 } | 1991 } |
| 1991 | 1992 |
| 1992 var T = _emitTypeName(returnType); | 1993 var T = _emitType(returnType); |
| 1993 return js.call('dart.#(#)', [ | 1994 return js.call('dart.#(#)', [ |
| 1994 kind, | 1995 kind, |
| 1995 [gen, T]..addAll(visitFormalParameterList(parameters, destructure: false)) | 1996 [gen, T]..addAll(visitFormalParameterList(parameters, destructure: false)) |
| 1996 ]); | 1997 ]); |
| 1997 } | 1998 } |
| 1998 | 1999 |
| 1999 @override | 2000 @override |
| 2000 JS.Statement visitFunctionDeclarationStatement( | 2001 JS.Statement visitFunctionDeclarationStatement( |
| 2001 FunctionDeclarationStatement node) { | 2002 FunctionDeclarationStatement node) { |
| 2002 var func = node.functionDeclaration; | 2003 var func = node.functionDeclaration; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2045 | 2046 |
| 2046 // Get the original declaring element. If we had a property accessor, this | 2047 // Get the original declaring element. If we had a property accessor, this |
| 2047 // indirects back to a (possibly synthetic) field. | 2048 // indirects back to a (possibly synthetic) field. |
| 2048 var element = accessor; | 2049 var element = accessor; |
| 2049 if (accessor is PropertyAccessorElement) element = accessor.variable; | 2050 if (accessor is PropertyAccessorElement) element = accessor.variable; |
| 2050 | 2051 |
| 2051 _loader.declareBeforeUse(element); | 2052 _loader.declareBeforeUse(element); |
| 2052 | 2053 |
| 2053 // type literal | 2054 // type literal |
| 2054 if (element is TypeDefiningElement) { | 2055 if (element is TypeDefiningElement) { |
| 2055 var typeName = _emitTypeName(fillDynamicTypeArgs(element.type)); | 2056 var typeName = _emitType(fillDynamicTypeArgs(element.type)); |
| 2056 | 2057 |
| 2057 // If the type is a type literal expression in Dart code, wrap the raw | 2058 // If the type is a type literal expression in Dart code, wrap the raw |
| 2058 // runtime type in a "Type" instance. | 2059 // runtime type in a "Type" instance. |
| 2059 if (!_isInForeignJS && _isTypeLiteral(node)) { | 2060 if (!_isInForeignJS && _isTypeLiteral(node)) { |
| 2060 typeName = js.call('dart.wrapType(#)', typeName); | 2061 typeName = js.call('dart.wrapType(#)', typeName); |
| 2061 } | 2062 } |
| 2062 | 2063 |
| 2063 return typeName; | 2064 return typeName; |
| 2064 } | 2065 } |
| 2065 | 2066 |
| 2066 // library member | 2067 // library member |
| 2067 if (element.enclosingElement is CompilationUnitElement) { | 2068 if (element.enclosingElement is CompilationUnitElement) { |
| 2068 return _emitTopLevelName(element); | 2069 return _emitTopLevelName(element); |
| 2069 } | 2070 } |
| 2070 | 2071 |
| 2071 var name = element.name; | 2072 var name = element.name; |
| 2072 | 2073 |
| 2073 // Unqualified class member. This could mean implicit-this, or implicit | 2074 // Unqualified class member. This could mean implicit-this, or implicit |
| 2074 // call to a static from the same class. | 2075 // call to a static from the same class. |
| 2075 if (element is ClassMemberElement && element is! ConstructorElement) { | 2076 if (element is ClassMemberElement && element is! ConstructorElement) { |
| 2076 bool isStatic = element.isStatic; | 2077 bool isStatic = element.isStatic; |
| 2077 var type = element.enclosingElement.type; | 2078 var type = element.enclosingElement.type; |
| 2078 var member = _emitMemberName(name, isStatic: isStatic, type: type); | 2079 var member = _emitMemberName(name, isStatic: isStatic, type: type); |
| 2079 | 2080 |
| 2080 // For static methods, we add the raw type name, without generics or | 2081 // For static methods, we add the raw type name, without generics or |
| 2081 // library prefix. We don't need those because static calls can't use | 2082 // library prefix. We don't need those because static calls can't use |
| 2082 // the generic type. | 2083 // the generic type. |
| 2083 if (isStatic) { | 2084 if (isStatic) { |
| 2084 var dynType = _emitTypeName(fillDynamicTypeArgs(type)); | 2085 var dynType = _emitType(fillDynamicTypeArgs(type)); |
| 2085 return new JS.PropertyAccess(dynType, member); | 2086 return new JS.PropertyAccess(dynType, member); |
| 2086 } | 2087 } |
| 2087 | 2088 |
| 2088 // For instance members, we add implicit-this. | 2089 // For instance members, we add implicit-this. |
| 2089 // For method tear-offs, we ensure it's a bound method. | 2090 // For method tear-offs, we ensure it's a bound method. |
| 2090 var tearOff = element is MethodElement && !inInvocationContext(node); | 2091 var tearOff = element is MethodElement && !inInvocationContext(node); |
| 2091 var code = (tearOff) ? 'dart.bind(this, #)' : 'this.#'; | 2092 var code = (tearOff) ? 'dart.bind(this, #)' : 'this.#'; |
| 2092 return js.call(code, member); | 2093 return js.call(code, member); |
| 2093 } | 2094 } |
| 2094 | 2095 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2150 (p is NormalFormalParameter) | 2151 (p is NormalFormalParameter) |
| 2151 ? p.metadata | 2152 ? p.metadata |
| 2152 : (p as DefaultFormalParameter).parameter.metadata; | 2153 : (p as DefaultFormalParameter).parameter.metadata; |
| 2153 | 2154 |
| 2154 JS.ArrayInitializer _emitTypeNames(List<DartType> types, | 2155 JS.ArrayInitializer _emitTypeNames(List<DartType> types, |
| 2155 [List<FormalParameter> parameters]) { | 2156 [List<FormalParameter> parameters]) { |
| 2156 var result = <JS.Expression>[]; | 2157 var result = <JS.Expression>[]; |
| 2157 for (int i = 0; i < types.length; ++i) { | 2158 for (int i = 0; i < types.length; ++i) { |
| 2158 var metadata = | 2159 var metadata = |
| 2159 parameters != null ? _parameterMetadata(parameters[i]) : []; | 2160 parameters != null ? _parameterMetadata(parameters[i]) : []; |
| 2160 var typeName = _emitTypeName(types[i]); | 2161 var typeName = _emitType(types[i]); |
| 2161 var value = typeName; | 2162 var value = typeName; |
| 2162 // TODO(vsm): Make this optional per #268. | 2163 // TODO(vsm): Make this optional per #268. |
| 2163 if (metadata.isNotEmpty) { | 2164 if (metadata.isNotEmpty) { |
| 2164 metadata = metadata.map(_instantiateAnnotation).toList(); | 2165 metadata = metadata.map(_instantiateAnnotation).toList(); |
| 2165 value = new JS.ArrayInitializer([typeName]..addAll(metadata)); | 2166 value = new JS.ArrayInitializer([typeName]..addAll(metadata)); |
| 2166 } | 2167 } |
| 2167 result.add(value); | 2168 result.add(value); |
| 2168 } | 2169 } |
| 2169 return new JS.ArrayInitializer(result); | 2170 return new JS.ArrayInitializer(result); |
| 2170 } | 2171 } |
| 2171 | 2172 |
| 2172 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { | 2173 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { |
| 2173 var properties = <JS.Property>[]; | 2174 var properties = <JS.Property>[]; |
| 2174 types.forEach((name, type) { | 2175 types.forEach((name, type) { |
| 2175 var key = _propertyName(name); | 2176 var key = _propertyName(name); |
| 2176 var value = _emitTypeName(type); | 2177 var value = _emitType(type); |
| 2177 properties.add(new JS.Property(key, value)); | 2178 properties.add(new JS.Property(key, value)); |
| 2178 }); | 2179 }); |
| 2179 return new JS.ObjectInitializer(properties); | 2180 return new JS.ObjectInitializer(properties); |
| 2180 } | 2181 } |
| 2181 | 2182 |
| 2182 /// Emit the pieces of a function type, as an array of return type, | 2183 /// Emit the pieces of a function type, as an array of return type, |
| 2183 /// regular args, and optional/named args. | 2184 /// regular args, and optional/named args. |
| 2184 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, | 2185 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, |
| 2185 {List<FormalParameter> parameters, bool lowerTypedef: false}) { | 2186 {List<FormalParameter> parameters, bool lowerTypedef: false}) { |
| 2186 var parameterTypes = type.normalParameterTypes; | 2187 var parameterTypes = type.normalParameterTypes; |
| 2187 var optionalTypes = type.optionalParameterTypes; | 2188 var optionalTypes = type.optionalParameterTypes; |
| 2188 var namedTypes = type.namedParameterTypes; | 2189 var namedTypes = type.namedParameterTypes; |
| 2189 var rt = _emitTypeName(type.returnType); | 2190 var rt = _emitType(type.returnType); |
| 2190 var ra = _emitTypeNames(parameterTypes, parameters); | 2191 var ra = _emitTypeNames(parameterTypes, parameters); |
| 2191 | 2192 |
| 2192 List<JS.Expression> typeParts; | 2193 List<JS.Expression> typeParts; |
| 2193 if (namedTypes.isNotEmpty) { | 2194 if (namedTypes.isNotEmpty) { |
| 2194 assert(optionalTypes.isEmpty); | 2195 assert(optionalTypes.isEmpty); |
| 2195 // TODO(vsm): Pass in annotations here as well. | 2196 // TODO(vsm): Pass in annotations here as well. |
| 2196 var na = _emitTypeProperties(namedTypes); | 2197 var na = _emitTypeProperties(namedTypes); |
| 2197 typeParts = [rt, ra, na]; | 2198 typeParts = [rt, ra, na]; |
| 2198 } else if (optionalTypes.isNotEmpty) { | 2199 } else if (optionalTypes.isNotEmpty) { |
| 2199 assert(namedTypes.isEmpty); | 2200 assert(namedTypes.isEmpty); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2214 } | 2215 } |
| 2215 return typeParts; | 2216 return typeParts; |
| 2216 } | 2217 } |
| 2217 | 2218 |
| 2218 /// Emits a Dart [type] into code. | 2219 /// Emits a Dart [type] into code. |
| 2219 /// | 2220 /// |
| 2220 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a | 2221 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a |
| 2221 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form | 2222 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form |
| 2222 /// will be used instead of `List`. These flags are used when generating | 2223 /// will be used instead of `List`. These flags are used when generating |
| 2223 /// the definitions for typedefs and generic types, respectively. | 2224 /// the definitions for typedefs and generic types, respectively. |
| 2224 JS.Expression _emitTypeName(DartType type, | 2225 /// |
| 2225 {bool lowerTypedef: false, bool lowerGeneric: false}) { | 2226 /// If [subClass] is set, then we are setting the base class for the given |
| 2227 /// class and should emit the given [className], which will already be |
| 2228 /// defined. |
| 2229 JS.Expression _emitType(DartType type, |
| 2230 {bool lowerTypedef: false, |
| 2231 bool lowerGeneric: false, |
| 2232 ClassElement subClass, |
| 2233 JS.Expression className}) { |
| 2226 // The void and dynamic types are not defined in core. | 2234 // The void and dynamic types are not defined in core. |
| 2227 if (type.isVoid) { | 2235 if (type.isVoid) { |
| 2228 return js.call('dart.void'); | 2236 return js.call('dart.void'); |
| 2229 } else if (type.isDynamic) { | 2237 } else if (type.isDynamic) { |
| 2230 return js.call('dart.dynamic'); | 2238 return js.call('dart.dynamic'); |
| 2231 } else if (type.isBottom) { | 2239 } else if (type.isBottom) { |
| 2232 return js.call('dart.bottom'); | 2240 return js.call('dart.bottom'); |
| 2233 } | 2241 } |
| 2234 | 2242 |
| 2235 _loader.declareBeforeUse(type.element); | 2243 _loader.declareBeforeUse(type.element); |
| 2236 | 2244 |
| 2237 // TODO(jmesserly): like constants, should we hoist function types out of | 2245 // TODO(jmesserly): like constants, should we hoist function types out of |
| 2238 // methods? Similar issue with generic types. For all of these, we may want | 2246 // methods? Similar issue with generic types. For all of these, we may want |
| 2239 // to canonicalize them too, at least when inside the same library. | 2247 // to canonicalize them too, at least when inside the same library. |
| 2240 var name = type.name; | 2248 var name = type.name; |
| 2241 var element = type.element; | 2249 var element = type.element; |
| 2242 if (name == '' || name == null || lowerTypedef) { | 2250 if (name == '' || name == null || lowerTypedef) { |
| 2243 // TODO(jmesserly): should we change how typedefs work? They currently | 2251 // TODO(jmesserly): should we change how typedefs work? They currently |
| 2244 // go through use similar logic as generic classes. This makes them | 2252 // go through use similar logic as generic classes. This makes them |
| 2245 // different from universal function types. | 2253 // different from universal function types. |
| 2246 var ft = type as FunctionType; | 2254 var ft = type as FunctionType; |
| 2247 var parts = _emitFunctionTypeParts(ft, lowerTypedef: lowerTypedef); | 2255 var parts = _emitFunctionTypeParts(ft, lowerTypedef: lowerTypedef); |
| 2248 return js.call('dart.functionType(#)', [parts]); | 2256 return js.call('dart.functionType(#)', [parts]); |
| 2249 } | 2257 } |
| 2250 | 2258 |
| 2251 if (type is TypeParameterType) { | 2259 if (type is TypeParameterType) { |
| 2252 return new JS.Identifier(name); | 2260 return new JS.Identifier(name); |
| 2253 } | 2261 } |
| 2254 | 2262 |
| 2263 if (type == subClass?.type) { |
| 2264 return className; |
| 2265 } |
| 2266 |
| 2255 if (type is ParameterizedType) { | 2267 if (type is ParameterizedType) { |
| 2256 var args = type.typeArguments; | 2268 var args = type.typeArguments; |
| 2257 Iterable jsArgs = null; | 2269 Iterable jsArgs = null; |
| 2258 if (args.any((a) => !a.isDynamic)) { | 2270 if (args.any((a) => !a.isDynamic)) { |
| 2259 jsArgs = args.map(_emitTypeName); | 2271 jsArgs = args.map( |
| 2272 (x) => _emitType(x, subClass: subClass, className: className)); |
| 2260 } else if (lowerGeneric) { | 2273 } else if (lowerGeneric) { |
| 2261 jsArgs = []; | 2274 jsArgs = []; |
| 2262 } | 2275 } |
| 2263 if (jsArgs != null) { | 2276 if (jsArgs != null) { |
| 2264 var genericName = _emitTopLevelName(element, suffix: '\$'); | 2277 var genericName = _emitTopLevelName(element, suffix: '\$'); |
| 2265 return js.call('#(#)', [genericName, jsArgs]); | 2278 return js.call('#(#)', [genericName, jsArgs]); |
| 2266 } | 2279 } |
| 2267 } | 2280 } |
| 2268 | 2281 |
| 2269 return _emitTopLevelName(element); | 2282 return _emitTopLevelName(element); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2530 | 2543 |
| 2531 /// If `g` is a generic function type, and `f` is an instantiation of it, | 2544 /// If `g` is a generic function type, and `f` is an instantiation of it, |
| 2532 /// then this will return the type arguments to apply, otherwise null. | 2545 /// then this will return the type arguments to apply, otherwise null. |
| 2533 List<JS.Expression> _emitFunctionTypeArguments(DartType g, DartType f, | 2546 List<JS.Expression> _emitFunctionTypeArguments(DartType g, DartType f, |
| 2534 [TypeArgumentList typeArgs]) { | 2547 [TypeArgumentList typeArgs]) { |
| 2535 if (g is FunctionType && | 2548 if (g is FunctionType && |
| 2536 g.typeFormals.isNotEmpty && | 2549 g.typeFormals.isNotEmpty && |
| 2537 f is FunctionType && | 2550 f is FunctionType && |
| 2538 f.typeFormals.isEmpty) { | 2551 f.typeFormals.isEmpty) { |
| 2539 return _recoverTypeArguments(g, f) | 2552 return _recoverTypeArguments(g, f) |
| 2540 .map(_emitTypeName) | 2553 .map(_emitType) |
| 2541 .toList(growable: false); | 2554 .toList(growable: false); |
| 2542 } else if (typeArgs != null) { | 2555 } else if (typeArgs != null) { |
| 2543 // Dynamic calls may have type arguments, even though the function types | 2556 // Dynamic calls may have type arguments, even though the function types |
| 2544 // are not known. | 2557 // are not known. |
| 2545 // TODO(jmesserly): seems to be mostly broken in Analyzer at the moment: | 2558 // TODO(jmesserly): seems to be mostly broken in Analyzer at the moment: |
| 2546 // https://github.com/dart-lang/sdk/issues/26368 | 2559 // https://github.com/dart-lang/sdk/issues/26368 |
| 2547 return typeArgs.arguments.map(visitTypeName).toList(growable: false); | 2560 return typeArgs.arguments.map(visitTypeName).toList(growable: false); |
| 2548 } | 2561 } |
| 2549 return null; | 2562 return null; |
| 2550 } | 2563 } |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2972 if (parent is ClassElement) { | 2985 if (parent is ClassElement) { |
| 2973 return getter | 2986 return getter |
| 2974 ? parent.getGetter(element.name) | 2987 ? parent.getGetter(element.name) |
| 2975 : parent.getSetter(element.name); | 2988 : parent.getSetter(element.name); |
| 2976 } | 2989 } |
| 2977 return null; | 2990 return null; |
| 2978 } | 2991 } |
| 2979 | 2992 |
| 2980 JS.Expression _emitConstructorName( | 2993 JS.Expression _emitConstructorName( |
| 2981 ConstructorElement element, DartType type, SimpleIdentifier name) { | 2994 ConstructorElement element, DartType type, SimpleIdentifier name) { |
| 2982 var typeName = _emitTypeName(type); | 2995 var typeName = _emitType(type); |
| 2983 if (name != null || element.isFactory) { | 2996 if (name != null || element.isFactory) { |
| 2984 var namedCtor = _constructorName(element); | 2997 var namedCtor = _constructorName(element); |
| 2985 return new JS.PropertyAccess(typeName, namedCtor); | 2998 return new JS.PropertyAccess(typeName, namedCtor); |
| 2986 } | 2999 } |
| 2987 return typeName; | 3000 return typeName; |
| 2988 } | 3001 } |
| 2989 | 3002 |
| 2990 @override | 3003 @override |
| 2991 visitConstructorName(ConstructorName node) { | 3004 visitConstructorName(ConstructorName node) { |
| 2992 return _emitConstructorName(node.staticElement, node.type.type, node.name); | 3005 return _emitConstructorName(node.staticElement, node.type.type, node.name); |
| 2993 } | 3006 } |
| 2994 | 3007 |
| 2995 JS.Expression _emitInstanceCreationExpression( | 3008 JS.Expression _emitInstanceCreationExpression( |
| 2996 ConstructorElement element, | 3009 ConstructorElement element, |
| 2997 DartType type, | 3010 DartType type, |
| 2998 SimpleIdentifier name, | 3011 SimpleIdentifier name, |
| 2999 ArgumentList argumentList, | 3012 ArgumentList argumentList, |
| 3000 bool isConst) { | 3013 bool isConst) { |
| 3001 JS.Expression emitNew() { | 3014 JS.Expression emitNew() { |
| 3002 JS.Expression ctor; | 3015 JS.Expression ctor; |
| 3003 bool isFactory = false; | 3016 bool isFactory = false; |
| 3004 // var element = node.staticElement; | 3017 // var element = node.staticElement; |
| 3005 if (element == null) { | 3018 if (element == null) { |
| 3006 // TODO(jmesserly): this only happens if we had a static error. | 3019 // TODO(jmesserly): this only happens if we had a static error. |
| 3007 // Should we generate a throw instead? | 3020 // Should we generate a throw instead? |
| 3008 ctor = _emitTypeName(type); | 3021 ctor = _emitType(type); |
| 3009 if (name != null) { | 3022 if (name != null) { |
| 3010 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); | 3023 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); |
| 3011 } | 3024 } |
| 3012 } else { | 3025 } else { |
| 3013 ctor = _emitConstructorName(element, type, name); | 3026 ctor = _emitConstructorName(element, type, name); |
| 3014 isFactory = element.isFactory; | 3027 isFactory = element.isFactory; |
| 3015 } | 3028 } |
| 3016 var args = _visit(argumentList) as List<JS.Expression>; | 3029 var args = _visit(argumentList) as List<JS.Expression>; |
| 3017 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args); | 3030 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args); |
| 3018 } | 3031 } |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3924 var then = visitCatchClause(clause); | 3937 var then = visitCatchClause(clause); |
| 3925 | 3938 |
| 3926 // Discard following clauses, if any, as they are unreachable. | 3939 // Discard following clauses, if any, as they are unreachable. |
| 3927 if (clause.exceptionType == null) return then; | 3940 if (clause.exceptionType == null) return then; |
| 3928 | 3941 |
| 3929 // TODO(jmesserly): this is inconsistent with [visitIsExpression], which | 3942 // TODO(jmesserly): this is inconsistent with [visitIsExpression], which |
| 3930 // has special case for typeof. | 3943 // has special case for typeof. |
| 3931 return new JS.If( | 3944 return new JS.If( |
| 3932 js.call('dart.is(#, #)', [ | 3945 js.call('dart.is(#, #)', [ |
| 3933 _visit(_catchParameter), | 3946 _visit(_catchParameter), |
| 3934 _emitTypeName(clause.exceptionType.type), | 3947 _emitType(clause.exceptionType.type), |
| 3935 ]), | 3948 ]), |
| 3936 then, | 3949 then, |
| 3937 otherwise); | 3950 otherwise); |
| 3938 } | 3951 } |
| 3939 | 3952 |
| 3940 JS.Statement _statement(List<JS.Statement> statements) { | 3953 JS.Statement _statement(List<JS.Statement> statements) { |
| 3941 // TODO(jmesserly): empty block singleton? | 3954 // TODO(jmesserly): empty block singleton? |
| 3942 if (statements.length == 0) return new JS.Block([]); | 3955 if (statements.length == 0) return new JS.Block([]); |
| 3943 if (statements.length == 1) return statements[0]; | 3956 if (statements.length == 1) return statements[0]; |
| 3944 return new JS.Block(statements); | 3957 return new JS.Block(statements); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4014 | 4027 |
| 4015 @override | 4028 @override |
| 4016 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); | 4029 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); |
| 4017 | 4030 |
| 4018 @override | 4031 @override |
| 4019 visitSymbolLiteral(SymbolLiteral node) { | 4032 visitSymbolLiteral(SymbolLiteral node) { |
| 4020 JS.Expression emitSymbol() { | 4033 JS.Expression emitSymbol() { |
| 4021 // TODO(vsm): When we canonicalize, we need to treat private symbols | 4034 // TODO(vsm): When we canonicalize, we need to treat private symbols |
| 4022 // correctly. | 4035 // correctly. |
| 4023 var name = js.string(node.components.join('.'), "'"); | 4036 var name = js.string(node.components.join('.'), "'"); |
| 4024 return js.call('#.new(#)', [_emitTypeName(types.symbolType), name]); | 4037 return js.call('#.new(#)', [_emitType(types.symbolType), name]); |
| 4025 } | 4038 } |
| 4026 return _emitConst(emitSymbol); | 4039 return _emitConst(emitSymbol); |
| 4027 } | 4040 } |
| 4028 | 4041 |
| 4029 @override | 4042 @override |
| 4030 visitListLiteral(ListLiteral node) { | 4043 visitListLiteral(ListLiteral node) { |
| 4031 JS.Expression emitList() { | 4044 JS.Expression emitList() { |
| 4032 JS.Expression list = new JS.ArrayInitializer( | 4045 JS.Expression list = new JS.ArrayInitializer( |
| 4033 _visitList(node.elements) as List<JS.Expression>); | 4046 _visitList(node.elements) as List<JS.Expression>); |
| 4034 ParameterizedType type = node.staticType; | 4047 ParameterizedType type = node.staticType; |
| 4035 var elementType = type.typeArguments.single; | 4048 var elementType = type.typeArguments.single; |
| 4036 // TODO(jmesserly): analyzer will usually infer `List<Object>` because | 4049 // TODO(jmesserly): analyzer will usually infer `List<Object>` because |
| 4037 // that is the least upper bound of the element types. So we rarely | 4050 // that is the least upper bound of the element types. So we rarely |
| 4038 // generate a plain `List<dynamic>` anymore. | 4051 // generate a plain `List<dynamic>` anymore. |
| 4039 if (!elementType.isDynamic) { | 4052 if (!elementType.isDynamic) { |
| 4040 // dart.list helper internally depends on _interceptors.JSArray. | 4053 // dart.list helper internally depends on _interceptors.JSArray. |
| 4041 _loader.declareBeforeUse(_jsArray); | 4054 _loader.declareBeforeUse(_jsArray); |
| 4042 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]); | 4055 list = js.call('dart.list(#, #)', [list, _emitType(elementType)]); |
| 4043 } | 4056 } |
| 4044 return list; | 4057 return list; |
| 4045 } | 4058 } |
| 4046 if (node.constKeyword != null) return _emitConst(emitList); | 4059 if (node.constKeyword != null) return _emitConst(emitList); |
| 4047 return emitList(); | 4060 return emitList(); |
| 4048 } | 4061 } |
| 4049 | 4062 |
| 4050 @override | 4063 @override |
| 4051 visitMapLiteral(MapLiteral node) { | 4064 visitMapLiteral(MapLiteral node) { |
| 4052 // TODO(jmesserly): we can likely make these faster. | 4065 // TODO(jmesserly): we can likely make these faster. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4068 } else { | 4081 } else { |
| 4069 var values = <JS.Expression>[]; | 4082 var values = <JS.Expression>[]; |
| 4070 for (var e in entries) { | 4083 for (var e in entries) { |
| 4071 values.add(_visit(e.key)); | 4084 values.add(_visit(e.key)); |
| 4072 values.add(_visit(e.value)); | 4085 values.add(_visit(e.value)); |
| 4073 } | 4086 } |
| 4074 mapArguments = new JS.ArrayInitializer(values); | 4087 mapArguments = new JS.ArrayInitializer(values); |
| 4075 } | 4088 } |
| 4076 var types = <JS.Expression>[]; | 4089 var types = <JS.Expression>[]; |
| 4077 if (typeArgs != null) { | 4090 if (typeArgs != null) { |
| 4078 types.addAll(typeArgs.arguments.map((e) => _emitTypeName(e.type))); | 4091 types.addAll(typeArgs.arguments.map((e) => _emitType(e.type))); |
| 4079 } | 4092 } |
| 4080 return js.call('dart.map(#, #)', [mapArguments, types]); | 4093 return js.call('dart.map(#, #)', [mapArguments, types]); |
| 4081 } | 4094 } |
| 4082 if (node.constKeyword != null) return _emitConst(emitMap); | 4095 if (node.constKeyword != null) return _emitConst(emitMap); |
| 4083 return emitMap(); | 4096 return emitMap(); |
| 4084 } | 4097 } |
| 4085 | 4098 |
| 4086 @override | 4099 @override |
| 4087 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => | 4100 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => |
| 4088 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); | 4101 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4394 } | 4407 } |
| 4395 | 4408 |
| 4396 bool isLibraryPrefix(Expression node) => | 4409 bool isLibraryPrefix(Expression node) => |
| 4397 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4410 node is SimpleIdentifier && node.staticElement is PrefixElement; |
| 4398 | 4411 |
| 4399 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4412 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
| 4400 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4413 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
| 4401 | 4414 |
| 4402 bool _isDartRuntime(LibraryElement l) => | 4415 bool _isDartRuntime(LibraryElement l) => |
| 4403 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4416 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
| OLD | NEW |