Chromium Code Reviews| 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 | 2 |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
| 7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 1256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1267 {List<FieldDeclaration> fields}) { | 1267 {List<FieldDeclaration> fields}) { |
| 1268 String name = element.name; | 1268 String name = element.name; |
| 1269 var heritage = _emitClassHeritage(element); | 1269 var heritage = _emitClassHeritage(element); |
| 1270 var typeParams = _emitTypeFormals(element.typeParameters); | 1270 var typeParams = _emitTypeFormals(element.typeParameters); |
| 1271 var jsFields = fields?.map(_emitTypeScriptField)?.toList(); | 1271 var jsFields = fields?.map(_emitTypeScriptField)?.toList(); |
| 1272 | 1272 |
| 1273 return new JS.ClassExpression(new JS.Identifier(name), heritage, methods, | 1273 return new JS.ClassExpression(new JS.Identifier(name), heritage, methods, |
| 1274 typeParams: typeParams, fields: jsFields); | 1274 typeParams: typeParams, fields: jsFields); |
| 1275 } | 1275 } |
| 1276 | 1276 |
| 1277 /// In some corner cases, a mixin may have its own mixins. | |
| 1278 /// E.g., M2 is a valid mixin: | |
| 1279 /// | |
| 1280 /// class M1 { int foo() => 42; } | |
| 1281 /// class M2 = Object with M1; | |
| 1282 /// class M3 = Object with M2; | |
| 1283 /// | |
| 1284 /// We expand out the list of mixins to treat M1 and M2 as separate | |
| 1285 /// applications. | |
| 1286 List<InterfaceType> _flattenMixins(List<InterfaceType> mixins) { | |
|
Jennifer Messerly
2017/03/27 22:15:15
I don't think this is correct in general?
it will
| |
| 1287 if (mixins.any((m) => m.mixins.isNotEmpty)) { | |
| 1288 // Clone, so we do not overwrite. | |
| 1289 mixins = new List<InterfaceType>.from(mixins); | |
| 1290 for (int i = 0; i < mixins.length; ++i) { | |
| 1291 var mixin = mixins[i]; | |
| 1292 if (mixin.mixins.isNotEmpty) { | |
| 1293 var indirectMixins = _flattenMixins(mixin.mixins); | |
| 1294 mixins.insertAll(i, indirectMixins); | |
| 1295 i += indirectMixins.length; | |
| 1296 } | |
| 1297 } | |
| 1298 } | |
| 1299 return mixins; | |
| 1300 } | |
| 1301 | |
| 1277 JS.Expression _emitClassHeritage(ClassElement element) { | 1302 JS.Expression _emitClassHeritage(ClassElement element) { |
| 1278 var type = element.type; | 1303 var type = element.type; |
| 1279 if (type.isObject) return null; | 1304 if (type.isObject) return null; |
| 1280 | 1305 |
| 1281 _loader.startTopLevel(element); | 1306 _loader.startTopLevel(element); |
| 1282 | 1307 |
| 1283 // List of "direct" supertypes (supertype + mixins) | 1308 // List of "direct" supertypes (supertype + mixins) |
| 1284 var basetypes = [type.superclass]..addAll(type.mixins); | 1309 var basetypes = [type.superclass]..addAll(_flattenMixins(type.mixins)); |
| 1285 | 1310 |
| 1286 // If any of these are recursive (via type parameter), defer setting | 1311 // If any of these are recursive (via type parameter), defer setting |
| 1287 // the real superclass. | 1312 // the real superclass. |
| 1288 if (basetypes.any((t) => _deferIfNeeded(t, element))) { | 1313 if (basetypes.any((t) => _deferIfNeeded(t, element))) { |
| 1289 // Fall back to raw type | 1314 // Fall back to raw type |
| 1290 basetypes = | 1315 basetypes = |
| 1291 basetypes.map((t) => fillDynamicTypeArgs(t.element.type)).toList(); | 1316 basetypes.map((t) => fillDynamicTypeArgs(t.element.type)).toList(); |
| 1292 _hasDeferredSupertype.add(element); | 1317 _hasDeferredSupertype.add(element); |
| 1293 } | 1318 } |
| 1294 | 1319 |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1714 var newBaseClass = _callHelper('global.#', [peer]); | 1739 var newBaseClass = _callHelper('global.#', [peer]); |
| 1715 body.add(_callHelperStatement( | 1740 body.add(_callHelperStatement( |
| 1716 'setExtensionBaseClass(#, #);', [className, newBaseClass])); | 1741 'setExtensionBaseClass(#, #);', [className, newBaseClass])); |
| 1717 } | 1742 } |
| 1718 } else if (_hasDeferredSupertype.contains(classElem)) { | 1743 } else if (_hasDeferredSupertype.contains(classElem)) { |
| 1719 // TODO(vsm): consider just threading the deferred supertype through | 1744 // TODO(vsm): consider just threading the deferred supertype through |
| 1720 // instead of recording classElem in a set on the class and recomputing | 1745 // instead of recording classElem in a set on the class and recomputing |
| 1721 var newBaseClass = _emitType(classElem.type.superclass, | 1746 var newBaseClass = _emitType(classElem.type.superclass, |
| 1722 nameType: false, subClass: classElem, className: className); | 1747 nameType: false, subClass: classElem, className: className); |
| 1723 if (classElem.type.mixins.isNotEmpty) { | 1748 if (classElem.type.mixins.isNotEmpty) { |
| 1724 var mixins = classElem.type.mixins | 1749 var mixins = _flattenMixins(classElem.type.mixins) |
| 1725 .map((t) => _emitType(t, nameType: false)) | 1750 .map((t) => _emitType(t, nameType: false)) |
| 1726 .toList(); | 1751 .toList(); |
| 1727 mixins.insert(0, newBaseClass); | 1752 mixins.insert(0, newBaseClass); |
| 1728 newBaseClass = _callHelper('mixin(#)', [mixins]); | 1753 newBaseClass = _callHelper('mixin(#)', [mixins]); |
| 1729 } | 1754 } |
| 1730 var deferredBaseClass = _callHelperStatement( | 1755 var deferredBaseClass = _callHelperStatement( |
| 1731 'setBaseClass(#, #);', [className, newBaseClass]); | 1756 'setBaseClass(#, #);', [className, newBaseClass]); |
| 1732 if (typeFormals.isNotEmpty) return deferredBaseClass; | 1757 if (typeFormals.isNotEmpty) return deferredBaseClass; |
| 1733 body.add(deferredBaseClass); | 1758 body.add(deferredBaseClass); |
| 1734 } | 1759 } |
| (...skipping 4302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6037 if (targetIdentifier.staticElement is! PrefixElement) return false; | 6062 if (targetIdentifier.staticElement is! PrefixElement) return false; |
| 6038 var prefix = targetIdentifier.staticElement as PrefixElement; | 6063 var prefix = targetIdentifier.staticElement as PrefixElement; |
| 6039 | 6064 |
| 6040 // The library the prefix is referring to must come from a deferred import. | 6065 // The library the prefix is referring to must come from a deferred import. |
| 6041 var containingLibrary = resolutionMap | 6066 var containingLibrary = resolutionMap |
| 6042 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 6067 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
| 6043 .library; | 6068 .library; |
| 6044 var imports = containingLibrary.getImportsWithPrefix(prefix); | 6069 var imports = containingLibrary.getImportsWithPrefix(prefix); |
| 6045 return imports.length == 1 && imports[0].isDeferred; | 6070 return imports.length == 1 && imports[0].isDeferred; |
| 6046 } | 6071 } |
| OLD | NEW |