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

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

Issue 1949163003: fix for #520, ListMixin should work again (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/runtime/dart_sdk.js ('k') | lib/src/compiler/compiler.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 849 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 860
861 if (m.element is PropertyAccessorElement) { 861 if (m.element is PropertyAccessorElement) {
862 jsMethods.add(_emitSuperAccessorWrapper(m, type, superclasses)); 862 jsMethods.add(_emitSuperAccessorWrapper(m, type, superclasses));
863 } 863 }
864 864
865 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') { 865 if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') {
866 hasIterator = true; 866 hasIterator = true;
867 jsMethods.add(_emitIterable(type)); 867 jsMethods.add(_emitIterable(type));
868 } 868 }
869 } else if (m is FieldDeclaration) { 869 } else if (m is FieldDeclaration) {
870 if (_extensionTypes.contains(element)) { 870 if (_extensionTypes.isNativeClass(element)) {
871 jsMethods.addAll(_emitNativeFieldAccessors(m)); 871 jsMethods.addAll(_emitNativeFieldAccessors(m));
872 continue; 872 continue;
873 } 873 }
874 if (m.isStatic) continue; 874 if (m.isStatic) continue;
875 for (VariableDeclaration field in m.fields.variables) { 875 for (VariableDeclaration field in m.fields.variables) {
876 if (virtualFields.containsKey(field.element)) { 876 if (virtualFields.containsKey(field.element)) {
877 jsMethods.addAll(_emitVirtualFieldAccessor(field, virtualFields)); 877 jsMethods.addAll(_emitVirtualFieldAccessor(field, virtualFields));
878 } 878 }
879 } 879 }
880 } 880 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 JS.Method _emitSuperAccessorWrapper(MethodDeclaration method, 930 JS.Method _emitSuperAccessorWrapper(MethodDeclaration method,
931 InterfaceType type, List<ClassElement> superclasses) { 931 InterfaceType type, List<ClassElement> superclasses) {
932 var methodElement = method.element as PropertyAccessorElement; 932 var methodElement = method.element as PropertyAccessorElement;
933 var field = methodElement.variable; 933 var field = methodElement.variable;
934 if (!field.isSynthetic) return null; 934 if (!field.isSynthetic) return null;
935 var propertyOverrideResult = checkForPropertyOverride( 935 var propertyOverrideResult = checkForPropertyOverride(
936 methodElement.variable, superclasses, _extensionTypes); 936 methodElement.variable, superclasses, _extensionTypes);
937 937
938 // Generate a corresponding virtual getter / setter. 938 // Generate a corresponding virtual getter / setter.
939 var name = _elementMemberName(methodElement, 939 var name = _elementMemberName(methodElement,
940 allowExtensions: _extensionTypes.contains(type.element)); 940 allowExtensions: _extensionTypes.isNativeClass(type.element));
941 if (method.isGetter) { 941 if (method.isGetter) {
942 // Generate a setter 942 // Generate a setter
943 if (field.setter != null || !propertyOverrideResult.foundSetter) 943 if (field.setter != null || !propertyOverrideResult.foundSetter)
944 return null; 944 return null;
945 var fn = js.call('function(value) { super[#] = value; }', [name]); 945 var fn = js.call('function(value) { super[#] = value; }', [name]);
946 return new JS.Method(name, fn, isSetter: true); 946 return new JS.Method(name, fn, isSetter: true);
947 } else { 947 } else {
948 // Generate a getter 948 // Generate a getter
949 if (field.getter != null || !propertyOverrideResult.foundGetter) 949 if (field.getter != null || !propertyOverrideResult.foundGetter)
950 return null; 950 return null;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 993
994 /// Gets the JS peer for this Dart type if any, otherwise null. 994 /// Gets the JS peer for this Dart type if any, otherwise null.
995 /// 995 ///
996 /// For example for dart:_interceptors `JSArray` this will return "Array", 996 /// For example for dart:_interceptors `JSArray` this will return "Array",
997 /// referring to the JavaScript built-in `Array` type. 997 /// referring to the JavaScript built-in `Array` type.
998 String _getJSPeerName(ClassElement classElem) { 998 String _getJSPeerName(ClassElement classElem) {
999 var jsPeerName = getAnnotationName( 999 var jsPeerName = getAnnotationName(
1000 classElem, 1000 classElem,
1001 (a) => 1001 (a) =>
1002 isJsPeerInterface(a) || 1002 isJsPeerInterface(a) ||
1003 isNativeAnnotation(a) && _extensionTypes.contains(classElem)); 1003 isNativeAnnotation(a) && _extensionTypes.isNativeClass(classElem));
1004 if (jsPeerName != null && jsPeerName.contains(',')) { 1004 if (jsPeerName != null && jsPeerName.contains(',')) {
1005 jsPeerName = jsPeerName.split(',')[0]; 1005 jsPeerName = jsPeerName.split(',')[0];
1006 } 1006 }
1007 return jsPeerName; 1007 return jsPeerName;
1008 } 1008 }
1009 1009
1010 void _registerExtensionType(ClassElement classElem, List<JS.Statement> body) { 1010 void _registerExtensionType(ClassElement classElem, List<JS.Statement> body) {
1011 var jsPeerName = _getJSPeerName(classElem); 1011 var jsPeerName = _getJSPeerName(classElem);
1012 if (jsPeerName != null) { 1012 if (jsPeerName != null) {
1013 // TODO(jmesserly): this copies the dynamic members. 1013 // TODO(jmesserly): this copies the dynamic members.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 1084
1085 /// If a concrete class implements one of our extensions, we might need to 1085 /// If a concrete class implements one of our extensions, we might need to
1086 /// add forwarders. 1086 /// add forwarders.
1087 void _defineExtensionMembers(List<ExecutableElement> extensions, 1087 void _defineExtensionMembers(List<ExecutableElement> extensions,
1088 JS.Expression className, List<JS.Statement> body) { 1088 JS.Expression className, List<JS.Statement> body) {
1089 // If a concrete class implements one of our extensions, we might need to 1089 // If a concrete class implements one of our extensions, we might need to
1090 // add forwarders. 1090 // add forwarders.
1091 if (extensions.isNotEmpty) { 1091 if (extensions.isNotEmpty) {
1092 var methodNames = <JS.Expression>[]; 1092 var methodNames = <JS.Expression>[];
1093 for (var e in extensions) { 1093 for (var e in extensions) {
1094 methodNames.add(_elementMemberName(e)); 1094 methodNames.add(_elementMemberName(e, allowExtensions: false));
1095 } 1095 }
1096 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ 1096 body.add(js.statement('dart.defineExtensionMembers(#, #);', [
1097 className, 1097 className,
1098 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) 1098 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4)
1099 ])); 1099 ]));
1100 } 1100 }
1101 } 1101 }
1102 1102
1103 /// Emit the signature on the class recording the runtime type information 1103 /// Emit the signature on the class recording the runtime type information
1104 void _emitClassSignature( 1104 void _emitClassSignature(
(...skipping 16 matching lines...) Expand all
1121 var sNames = <JS.Expression>[]; 1121 var sNames = <JS.Expression>[];
1122 for (MethodDeclaration node in methods) { 1122 for (MethodDeclaration node in methods) {
1123 if (!(node.isSetter || node.isGetter || node.isAbstract)) { 1123 if (!(node.isSetter || node.isGetter || node.isAbstract)) {
1124 var name = node.name.name; 1124 var name = node.name.name;
1125 var element = node.element; 1125 var element = node.element;
1126 var inheritedElement = 1126 var inheritedElement =
1127 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); 1127 classElem.lookUpInheritedConcreteMethod(name, currentLibrary);
1128 if (inheritedElement != null && inheritedElement.type == element.type) { 1128 if (inheritedElement != null && inheritedElement.type == element.type) {
1129 continue; 1129 continue;
1130 } 1130 }
1131 var memberName = _elementMemberName(element); 1131 var memberName = _elementMemberName(element,
1132 allowExtensions: _extensionTypes.isNativeClass(classElem));
1132 var parts = _emitFunctionTypeParts(element.type); 1133 var parts = _emitFunctionTypeParts(element.type);
1133 var property = 1134 var property =
1134 new JS.Property(memberName, new JS.ArrayInitializer(parts)); 1135 new JS.Property(memberName, new JS.ArrayInitializer(parts));
1135 if (node.isStatic) { 1136 if (node.isStatic) {
1136 tStatics.add(property); 1137 tStatics.add(property);
1137 sNames.add(memberName); 1138 sNames.add(memberName);
1138 } else { 1139 } else {
1139 tMethods.add(property); 1140 tMethods.add(property);
1140 } 1141 }
1141 } 1142 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); 1174 body.add(js.statement('dart.setSignature(#, #);', [className, sig]));
1174 } 1175 }
1175 } 1176 }
1176 1177
1177 /// Ensure `dartx.` symbols we will use are present. 1178 /// Ensure `dartx.` symbols we will use are present.
1178 void _initExtensionSymbols( 1179 void _initExtensionSymbols(
1179 ClassElement classElem, 1180 ClassElement classElem,
1180 List<MethodDeclaration> methods, 1181 List<MethodDeclaration> methods,
1181 List<FieldDeclaration> fields, 1182 List<FieldDeclaration> fields,
1182 List<JS.Statement> body) { 1183 List<JS.Statement> body) {
1183 if (_extensionTypes.contains(classElem)) { 1184 if (_extensionTypes.hasNativeSubtype(classElem.type)) {
1184 var dartxNames = <JS.Expression>[]; 1185 var dartxNames = <JS.Expression>[];
1185 for (var m in methods) { 1186 for (var m in methods) {
1186 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 1187 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
1187 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); 1188 dartxNames.add(_elementMemberName(m.element, allowExtensions: false));
1188 } 1189 }
1189 } 1190 }
1190 for (var f in fields) { 1191 for (var f in fields) {
1191 if (!f.isStatic) { 1192 if (!f.isStatic) {
1192 for (var d in f.fields.variables) { 1193 for (var d in f.fields.variables) {
1193 if (d.element.isPublic) { 1194 if (d.element.isPublic) {
1194 dartxNames.add( 1195 dartxNames.add(
1195 _elementMemberName(d.element.getter, allowExtensions: false)); 1196 _elementMemberName(d.element.getter, allowExtensions: false));
1196 } 1197 }
1197 } 1198 }
1198 } 1199 }
1199 } 1200 }
1200 if (dartxNames.isNotEmpty) { 1201 if (dartxNames.isNotEmpty) {
1201 body.add(js.statement('dart.defineExtensionNames(#)', 1202 body.add(js.statement('dart.defineExtensionNames(#)',
1202 [new JS.ArrayInitializer(dartxNames, multiline: true)])); 1203 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
1203 } 1204 }
1204 } 1205 }
1205 } 1206 }
1206 1207
1207 List<ExecutableElement> _extensionsToImplement(ClassElement element) { 1208 List<ExecutableElement> _extensionsToImplement(ClassElement element) {
1208 var members = <ExecutableElement>[]; 1209 var members = <ExecutableElement>[];
1209 if (_extensionTypes.contains(element)) return members; 1210 if (_extensionTypes.isNativeClass(element)) return members;
1210 1211
1211 // Collect all extension types we implement. 1212 // Collect all extension types we implement.
1212 var type = element.type; 1213 var type = element.type;
1213 var types = new Set<ClassElement>(); 1214 var types = _extensionTypes.collectNativeInterfaces(element);
1214 _collectExtensions(type, types);
1215 if (types.isEmpty) return members; 1215 if (types.isEmpty) return members;
1216 1216
1217 // Collect all possible extension method names. 1217 // Collect all possible extension method names.
1218 var extensionMembers = new HashSet<String>(); 1218 var extensionMembers = new HashSet<String>();
1219 for (var t in types) { 1219 for (var t in types) {
1220 for (var m in [t.methods, t.accessors].expand((e) => e)) { 1220 for (var m in [t.methods, t.accessors].expand((e) => e)) {
1221 if (!m.isStatic) extensionMembers.add(m.name); 1221 if (!m.isStatic) extensionMembers.add(m.name);
1222 } 1222 }
1223 } 1223 }
1224 1224
1225 // Collect all of extension methods this type implements. 1225 // Collect all of extension methods this type implements.
1226 for (var m in [type.methods, type.accessors].expand((e) => e)) { 1226 for (var m in [type.methods, type.accessors].expand((e) => e)) {
1227 if (!m.isStatic && !m.isAbstract && extensionMembers.contains(m.name)) { 1227 if (!m.isStatic && !m.isAbstract && extensionMembers.contains(m.name)) {
1228 members.add(m); 1228 members.add(m);
1229 } 1229 }
1230 } 1230 }
1231 return members; 1231 return members;
1232 } 1232 }
1233 1233
1234 /// Collections the type and all supertypes, including interfaces, but
1235 /// excluding [Object].
1236 void _collectExtensions(InterfaceType type, Set<ClassElement> types) {
1237 if (type.isObject) return;
1238 var element = type.element;
1239 if (_extensionTypes.contains(element)) types.add(element);
1240 for (var m in type.mixins.reversed) {
1241 _collectExtensions(m, types);
1242 }
1243 for (var i in type.interfaces) {
1244 _collectExtensions(i, types);
1245 }
1246 _collectExtensions(type.superclass, types);
1247 }
1248
1249 /// Generates the implicit default constructor for class C of the form 1234 /// Generates the implicit default constructor for class C of the form
1250 /// `C() : super() {}`. 1235 /// `C() : super() {}`.
1251 JS.Method _emitImplicitConstructor( 1236 JS.Method _emitImplicitConstructor(
1252 ClassDeclaration node, 1237 ClassDeclaration node,
1253 List<FieldDeclaration> fields, 1238 List<FieldDeclaration> fields,
1254 Map<FieldElement, JS.TemporaryId> virtualFields) { 1239 Map<FieldElement, JS.TemporaryId> virtualFields) {
1255 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); 1240 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty);
1256 1241
1257 // If we don't have a method body, skip this. 1242 // If we don't have a method body, skip this.
1258 var superCall = _superConstructorCall(node.element); 1243 var superCall = _superConstructorCall(node.element);
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 fn.params.isNotEmpty) { 1643 fn.params.isNotEmpty) {
1659 // []= methods need to return the value. We could also address this at 1644 // []= methods need to return the value. We could also address this at
1660 // call sites, but it's cleaner to instead transform the operator method . 1645 // call sites, but it's cleaner to instead transform the operator method .
1661 fn = _alwaysReturnLastParameter(fn); 1646 fn = _alwaysReturnLastParameter(fn);
1662 } 1647 }
1663 1648
1664 fn = _makeGenericFunction(fn); 1649 fn = _makeGenericFunction(fn);
1665 } 1650 }
1666 1651
1667 return annotate( 1652 return annotate(
1668 new JS.Method(_elementMemberName(node.element), fn, 1653 new JS.Method(
1654 _elementMemberName(node.element,
1655 allowExtensions: _extensionTypes.isNativeClass(type.element)),
1656 fn,
1669 isGetter: node.isGetter, 1657 isGetter: node.isGetter,
1670 isSetter: node.isSetter, 1658 isSetter: node.isSetter,
1671 isStatic: node.isStatic), 1659 isStatic: node.isStatic),
1672 node, 1660 node,
1673 node.element); 1661 node.element);
1674 } 1662 }
1675 1663
1676 /// Transform the function so the last parameter is always returned. 1664 /// Transform the function so the last parameter is always returned.
1677 /// 1665 ///
1678 /// This is useful for indexed set methods, which otherwise would not have 1666 /// This is useful for indexed set methods, which otherwise would not have
(...skipping 1855 matching lines...) Expand 10 before | Expand all | Expand 10 after
3534 // Is this a member on `Object`? 3522 // Is this a member on `Object`?
3535 if (!isObjectProperty(memberName)) { 3523 if (!isObjectProperty(memberName)) {
3536 return false; 3524 return false;
3537 } 3525 }
3538 3526
3539 // Check if the target could be `null`, is dynamic, or may be an extension 3527 // Check if the target could be `null`, is dynamic, or may be an extension
3540 // native type. In all of those cases we need defensive code generation. 3528 // native type. In all of those cases we need defensive code generation.
3541 var type = getStaticType(target); 3529 var type = getStaticType(target);
3542 return isNullable(target) || 3530 return isNullable(target) ||
3543 type.isDynamic || 3531 type.isDynamic ||
3544 (_extensionTypes.contains(type.element) && target is! SuperExpression); 3532 (_extensionTypes.hasNativeSubtype(type) && target is! SuperExpression);
3545 } 3533 }
3546 3534
3547 /// Shared code for [PrefixedIdentifier] and [PropertyAccess]. 3535 /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
3548 JS.Expression _emitAccess( 3536 JS.Expression _emitAccess(
3549 Expression target, SimpleIdentifier memberId, DartType resultType) { 3537 Expression target, SimpleIdentifier memberId, DartType resultType) {
3550 Element member = memberId.staticElement; 3538 Element member = memberId.staticElement;
3551 if (member is PropertyAccessorElement) { 3539 if (member is PropertyAccessorElement) {
3552 member = (member as PropertyAccessorElement).variable; 3540 member = (member as PropertyAccessorElement).variable;
3553 } 3541 }
3554 bool isStatic = member is ClassMemberElement && member.isStatic; 3542 bool isStatic = member is ClassMemberElement && member.isStatic;
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
4137 name = '+$name'; 4125 name = '+$name';
4138 } 4126 }
4139 4127
4140 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 4128 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
4141 var baseType = type; 4129 var baseType = type;
4142 while (baseType is TypeParameterType) { 4130 while (baseType is TypeParameterType) {
4143 baseType = baseType.element.bound; 4131 baseType = baseType.element.bound;
4144 } 4132 }
4145 if (allowExtensions && 4133 if (allowExtensions &&
4146 baseType != null && 4134 baseType != null &&
4147 _extensionTypes.contains(baseType.element) && 4135 _extensionTypes.hasNativeSubtype(baseType) &&
4148 !isObjectProperty(name)) { 4136 !isObjectProperty(name)) {
4149 return js.call('dartx.#', _propertyName(name)); 4137 return js.call('dartx.#', _propertyName(name));
4150 } 4138 }
4151 4139
4152 return _propertyName(name); 4140 return _propertyName(name);
4153 } 4141 }
4154 4142
4155 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) { 4143 JS.TemporaryId _emitPrivateNameSymbol(LibraryElement library, String name) {
4156 return _privateNames 4144 return _privateNames
4157 .putIfAbsent(library, () => new HashMap()) 4145 .putIfAbsent(library, () => new HashMap())
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
4299 } 4287 }
4300 4288
4301 bool isLibraryPrefix(Expression node) => 4289 bool isLibraryPrefix(Expression node) =>
4302 node is SimpleIdentifier && node.staticElement is PrefixElement; 4290 node is SimpleIdentifier && node.staticElement is PrefixElement;
4303 4291
4304 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4292 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4305 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4293 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4306 4294
4307 bool _isDartRuntime(LibraryElement l) => 4295 bool _isDartRuntime(LibraryElement l) =>
4308 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4296 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | lib/src/compiler/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698