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 |