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

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

Issue 2803673007: fix #29233, final fields can be settable in a mock (Closed)
Patch Set: fix Created 3 years, 8 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 | « no previous file | pkg/dev_compiler/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 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 892 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 903
904 JS.Expression className; 904 JS.Expression className;
905 if (classElem.typeParameters.isNotEmpty) { 905 if (classElem.typeParameters.isNotEmpty) {
906 // Generic classes will be defined inside a function that closes over the 906 // Generic classes will be defined inside a function that closes over the
907 // type parameter. So we can use their local variable name directly. 907 // type parameter. So we can use their local variable name directly.
908 className = new JS.Identifier(classElem.name); 908 className = new JS.Identifier(classElem.name);
909 } else { 909 } else {
910 className = _emitTopLevelName(classElem); 910 className = _emitTopLevelName(classElem);
911 } 911 }
912 912
913 var extensions = _extensionsToImplement(classElem);
914 var savedClassProperties = _classProperties; 913 var savedClassProperties = _classProperties;
915 _classProperties = 914 _classProperties =
916 new ClassPropertyModel.build(virtualFields, classElem, extensions); 915 new ClassPropertyModel.build(_extensionTypes, virtualFields, classElem);
917 916
918 var classExpr = _emitClassExpression( 917 var classExpr = _emitClassExpression(
919 classElem, _emitClassMethods(node, ctors, fields), 918 classElem, _emitClassMethods(node, ctors, fields),
920 fields: allFields); 919 fields: allFields);
921 920
922 var body = <JS.Statement>[]; 921 var body = <JS.Statement>[];
923 _initExtensionSymbols(classElem, methods, fields, body); 922 _initExtensionSymbols(classElem, methods, fields, body);
924 _emitSuperHelperSymbols(_superHelperSymbols, body); 923 _emitSuperHelperSymbols(_superHelperSymbols, body);
925 924
926 // Emit the class, e.g. `core.Object = class Object { ... }` 925 // Emit the class, e.g. `core.Object = class Object { ... }`
927 _defineClass(classElem, className, classExpr, isCallable, body); 926 _defineClass(classElem, className, classExpr, isCallable, body);
928 927
929 // Emit things that come after the ES6 `class ... { ... }`. 928 // Emit things that come after the ES6 `class ... { ... }`.
930 var jsPeerNames = _getJSPeerNames(classElem); 929 var jsPeerNames = _getJSPeerNames(classElem);
931 JS.Statement deferredBaseClass = 930 JS.Statement deferredBaseClass =
932 _setBaseClass(classElem, className, jsPeerNames, body); 931 _setBaseClass(classElem, className, jsPeerNames, body);
933 932
934 _emitClassTypeTests(classElem, className, body); 933 _emitClassTypeTests(classElem, className, body);
935 934
936 _defineNamedConstructors(ctors, body, className, isCallableTransitive); 935 _defineNamedConstructors(ctors, body, className, isCallableTransitive);
937 _emitVirtualFieldSymbols(classElem, body); 936 _emitVirtualFieldSymbols(classElem, body);
938 _emitClassSignature( 937 _emitClassSignature(methods, allFields, classElem, ctors, className, body);
939 methods, allFields, classElem, ctors, extensions, className, body); 938 _defineExtensionMembers(className, body);
940 _defineExtensionMembers(extensions, className, body);
941 _emitClassMetadata(node.metadata, className, body); 939 _emitClassMetadata(node.metadata, className, body);
942 940
943 JS.Statement classDef = _statement(body); 941 JS.Statement classDef = _statement(body);
944 942
945 var typeFormals = classElem.typeParameters; 943 var typeFormals = classElem.typeParameters;
946 if (typeFormals.isNotEmpty) { 944 if (typeFormals.isNotEmpty) {
947 classDef = _defineClassTypeArguments( 945 classDef = _defineClassTypeArguments(
948 classElem, typeFormals, classDef, className, deferredBaseClass); 946 classElem, typeFormals, classDef, className, deferredBaseClass);
949 } 947 }
950 948
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 jsMethods.add(_emitIterable(type)); 1475 jsMethods.add(_emitIterable(type));
1478 } 1476 }
1479 } else if (m is FieldDeclaration) { 1477 } else if (m is FieldDeclaration) {
1480 if (_extensionTypes.isNativeClass(element)) { 1478 if (_extensionTypes.isNativeClass(element)) {
1481 jsMethods.addAll(_emitNativeFieldAccessors(m)); 1479 jsMethods.addAll(_emitNativeFieldAccessors(m));
1482 continue; 1480 continue;
1483 } 1481 }
1484 if (m.isStatic) continue; 1482 if (m.isStatic) continue;
1485 for (VariableDeclaration field in m.fields.variables) { 1483 for (VariableDeclaration field in m.fields.variables) {
1486 if (virtualFields.containsKey(field.element)) { 1484 if (virtualFields.containsKey(field.element)) {
1487 jsMethods.addAll(_emitVirtualFieldAccessor(field, virtualFields)); 1485 jsMethods.addAll(_emitVirtualFieldAccessor(field));
1488 } 1486 }
1489 } 1487 }
1490 } 1488 }
1491 } 1489 }
1492 1490
1493 jsMethods.addAll(_implementMockInterfaces(type)); 1491 jsMethods.addAll(_classProperties.mockMembers.values
1492 .map((e) => _implementMockMember(e, type)));
1494 1493
1495 // If the type doesn't have an `iterator`, but claims to implement Iterable, 1494 // If the type doesn't have an `iterator`, but claims to implement Iterable,
1496 // we inject the adaptor method here, as it's less code size to put the 1495 // we inject the adaptor method here, as it's less code size to put the
1497 // helper on a parent class. This pattern is common in the core libraries 1496 // helper on a parent class. This pattern is common in the core libraries
1498 // (e.g. IterableMixin<E> and IterableBase<E>). 1497 // (e.g. IterableMixin<E> and IterableBase<E>).
1499 // 1498 //
1500 // (We could do this same optimization for any interface with an `iterator` 1499 // (We could do this same optimization for any interface with an `iterator`
1501 // method, but that's more expensive to check for, so it doesn't seem worth 1500 // method, but that's more expensive to check for, so it doesn't seem worth
1502 // it. The above case for an explicit `iterator` method will catch those.) 1501 // it. The above case for an explicit `iterator` method will catch those.)
1503 if (!hasJsPeer && !hasIterator && _implementsIterable(type)) { 1502 if (!hasJsPeer && !hasIterator && _implementsIterable(type)) {
1504 jsMethods.add(_emitIterable(type)); 1503 jsMethods.add(_emitIterable(type));
1505 } 1504 }
1506 1505
1507 // Add all of the super helper methods 1506 // Add all of the super helper methods
1508 jsMethods.addAll(_superHelpers); 1507 jsMethods.addAll(_superHelpers);
1509 _superHelpers.clear(); 1508 _superHelpers.clear();
1510 1509
1511 return jsMethods.where((m) => m != null).toList(growable: false); 1510 return jsMethods.where((m) => m != null).toList(growable: false);
1512 } 1511 }
1513 1512
1514 Iterable<ExecutableElement> _collectMockMethods(InterfaceType type) {
1515 var element = type.element;
1516 if (!_hasNoSuchMethod(element)) {
1517 return [];
1518 }
1519
1520 // Collect all unimplemented members.
1521 //
1522 // Initially, we track abstract and concrete members separately, then
1523 // remove concrete from the abstract set. This is done because abstract
1524 // members are allowed to "override" concrete ones in Dart.
1525 // (In that case, it will still be treated as a concrete member and can be
1526 // called at run time.)
1527 var abstractMembers = new Map<String, ExecutableElement>();
1528 var concreteMembers = new HashSet<String>();
1529
1530 void visit(InterfaceType type, bool isAbstract) {
1531 if (type == null) return;
1532 visit(type.superclass, isAbstract);
1533 for (var m in type.mixins) visit(m, isAbstract);
1534 for (var i in type.interfaces) visit(i, true);
1535
1536 var members = <ExecutableElement>[]
1537 ..addAll(type.methods)
1538 ..addAll(type.accessors);
1539 for (var m in members) {
1540 if (isAbstract || m.isAbstract) {
1541 // Inconsistent signatures are disallowed, even with nSM, so we don't
1542 // need to worry too much about which abstract member we save.
1543 abstractMembers[m.name] = m;
1544 } else {
1545 concreteMembers.add(m.name);
1546 }
1547 }
1548 }
1549
1550 visit(type, false);
1551
1552 concreteMembers.forEach(abstractMembers.remove);
1553 return abstractMembers.values;
1554 }
1555
1556 Iterable<JS.Method> _implementMockInterfaces(InterfaceType type) {
1557 // TODO(jmesserly): every type with nSM will generate new stubs for all
1558 // abstract members. For example:
1559 //
1560 // class C { m(); noSuchMethod(...) { ... } }
1561 // class D extends C { m(); noSuchMethod(...) { ... } }
1562 //
1563 // We'll generate D.m even though it is not necessary.
1564 //
1565 // Doing better is a bit tricky, as our current codegen strategy for the
1566 // mock methods encodes information about the number of arguments (and type
1567 // arguments) that D expects.
1568 return _collectMockMethods(type)
1569 .map((method) => _implementMockMethod(method, type));
1570 }
1571
1572 /// Given a class C that implements method M from interface I, but does not 1513 /// Given a class C that implements method M from interface I, but does not
1573 /// declare M, this will generate an implementation that forwards to 1514 /// declare M, this will generate an implementation that forwards to
1574 /// noSuchMethod. 1515 /// noSuchMethod.
1575 /// 1516 ///
1576 /// For example: 1517 /// For example:
1577 /// 1518 ///
1578 /// class Cat { 1519 /// class Cat {
1579 /// bool eatFood(String food) => true; 1520 /// bool eatFood(String food) => true;
1580 /// } 1521 /// }
1581 /// class MockCat implements Cat { 1522 /// class MockCat implements Cat {
1582 /// noSuchMethod(Invocation invocation) => 3; 1523 /// noSuchMethod(Invocation invocation) => 3;
1583 /// } 1524 /// }
1584 /// 1525 ///
1585 /// It will generate an `eatFood` that looks like: 1526 /// It will generate an `eatFood` that looks like:
1586 /// 1527 ///
1587 /// eatFood(...args) { 1528 /// eatFood(...args) {
1588 /// return core.bool.as(this.noSuchMethod( 1529 /// return core.bool.as(this.noSuchMethod(
1589 /// new dart.InvocationImpl('eatFood', args))); 1530 /// new dart.InvocationImpl('eatFood', args)));
1590 /// } 1531 /// }
1591 JS.Method _implementMockMethod(ExecutableElement method, InterfaceType type) { 1532 JS.Method _implementMockMember(ExecutableElement method, InterfaceType type) {
1592 var invocationProps = <JS.Property>[]; 1533 var invocationProps = <JS.Property>[];
1593 addProperty(String name, JS.Expression value) { 1534 addProperty(String name, JS.Expression value) {
1594 invocationProps.add(new JS.Property(js.string(name), value)); 1535 invocationProps.add(new JS.Property(js.string(name), value));
1595 } 1536 }
1596 1537
1597 var args = new JS.TemporaryId('args'); 1538 var args = new JS.TemporaryId('args');
1598 var fnArgs = <JS.Parameter>[]; 1539 var fnArgs = <JS.Parameter>[];
1599 JS.Expression positionalArgs; 1540 JS.Expression positionalArgs;
1600 1541
1601 if (method.type.namedParameterTypes.isNotEmpty) { 1542 if (method.type.namedParameterTypes.isNotEmpty) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1639 // We have a similar issue with `dgsend` helpers. 1580 // We have a similar issue with `dgsend` helpers.
1640 return new JS.Method( 1581 return new JS.Method(
1641 _declareMemberName(method, 1582 _declareMemberName(method,
1642 useExtension: _extensionTypes.isNativeClass(type.element)), 1583 useExtension: _extensionTypes.isNativeClass(type.element)),
1643 _makeGenericFunction(fn), 1584 _makeGenericFunction(fn),
1644 isGetter: method is PropertyAccessorElement && method.isGetter, 1585 isGetter: method is PropertyAccessorElement && method.isGetter,
1645 isSetter: method is PropertyAccessorElement && method.isSetter, 1586 isSetter: method is PropertyAccessorElement && method.isSetter,
1646 isStatic: false); 1587 isStatic: false);
1647 } 1588 }
1648 1589
1649 /// Return `true` if the given [classElement] has a noSuchMethod() method
1650 /// distinct from the one declared in class Object, as per the Dart Language
1651 /// Specification (section 10.4).
1652 // TODO(jmesserly): this was taken from error_verifier.dart
1653 bool _hasNoSuchMethod(ClassElement classElement) {
1654 // TODO(jmesserly): this is slow in Analyzer. It's a linear scan through all
1655 // methods, up through the class hierarchy.
1656 MethodElement method = classElement.lookUpMethod(
1657 FunctionElement.NO_SUCH_METHOD_METHOD_NAME, classElement.library);
1658 var definingClass = method?.enclosingElement;
1659 return definingClass != null && !definingClass.type.isObject;
1660 }
1661
1662 /// This is called whenever a derived class needs to introduce a new field, 1590 /// This is called whenever a derived class needs to introduce a new field,
1663 /// shadowing a field or getter/setter pair on its parent. 1591 /// shadowing a field or getter/setter pair on its parent.
1664 /// 1592 ///
1665 /// This is important because otherwise, trying to read or write the field 1593 /// This is important because otherwise, trying to read or write the field
1666 /// would end up calling the getter or setter, and one of those might not even 1594 /// would end up calling the getter or setter, and one of those might not even
1667 /// exist, resulting in a runtime error. Even if they did exist, that's the 1595 /// exist, resulting in a runtime error. Even if they did exist, that's the
1668 /// wrong behavior if a new field was declared. 1596 /// wrong behavior if a new field was declared.
1669 List<JS.Method> _emitVirtualFieldAccessor(VariableDeclaration field, 1597 List<JS.Method> _emitVirtualFieldAccessor(VariableDeclaration field) {
1670 Map<FieldElement, JS.TemporaryId> virtualFields) { 1598 var element = field.element as FieldElement;
1671 var virtualField = virtualFields[field.element]; 1599 var virtualField = _classProperties.virtualFields[element];
1672 var result = <JS.Method>[]; 1600 var result = <JS.Method>[];
1673 var name = _declareMemberName((field.element as FieldElement).getter); 1601 var name = _declareMemberName(element.getter);
1674 var getter = js.call('function() { return this[#]; }', [virtualField]);
1675 result.add(new JS.Method(name, getter, isGetter: true));
1676 1602
1677 if (field.isFinal) { 1603 var mocks = _classProperties.mockMembers;
1678 var setter = js.call('function(value) { super[#] = value; }', [name]); 1604 if (!mocks.containsKey(element.name)) {
1679 result.add(new JS.Method(name, setter, isSetter: true)); 1605 var getter = js.call('function() { return this[#]; }', [virtualField]);
1680 } else { 1606 result.add(new JS.Method(name, getter, isGetter: true));
1681 var setter = 1607 }
1682 js.call('function(value) { this[#] = value; }', [virtualField]); 1608
1683 result.add(new JS.Method(name, setter, isSetter: true)); 1609 if (!mocks.containsKey(element.name + '=')) {
1610 var args = field.isFinal
1611 ? [new JS.Super(), name]
1612 : [new JS.This(), virtualField];
1613
1614 result.add(new JS.Method(
1615 name, js.call('function(value) { #[#] = value; }', args),
1616 isSetter: true));
1684 } 1617 }
1685 1618
1686 return result; 1619 return result;
1687 } 1620 }
1688 1621
1689 /// Emit a getter or setter that simply forwards to the superclass getter or 1622 /// Emit a getter or setter that simply forwards to the superclass getter or
1690 /// setter. This is needed because in ES6, if you only override a getter 1623 /// setter. This is needed because in ES6, if you only override a getter
1691 /// (alternatively, a setter), then there is an implicit override of the 1624 /// (alternatively, a setter), then there is an implicit override of the
1692 /// setter (alternatively, the getter) that does nothing. 1625 /// setter (alternatively, the getter) that does nothing.
1693 JS.Method _emitSuperAccessorWrapper( 1626 JS.Method _emitSuperAccessorWrapper(
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 className, 1787 className,
1855 _runtimeModule, 1788 _runtimeModule,
1856 new JS.ArrayInitializer( 1789 new JS.ArrayInitializer(
1857 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation))) 1790 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation)))
1858 ])); 1791 ]));
1859 } 1792 }
1860 } 1793 }
1861 1794
1862 /// If a concrete class implements one of our extensions, we might need to 1795 /// If a concrete class implements one of our extensions, we might need to
1863 /// add forwarders. 1796 /// add forwarders.
1864 void _defineExtensionMembers(List<ExecutableElement> extensions, 1797 void _defineExtensionMembers(
1865 JS.Expression className, List<JS.Statement> body) { 1798 JS.Expression className, List<JS.Statement> body) {
1866 // If a concrete class implements one of our extensions, we might need to 1799 void emitExtenstions(
vsm 2017/04/07 20:57:35 nit: emitExtenstions -> emitExtensions
1867 // add forwarders. 1800 JS.Expression target, Iterable<ExecutableElement> extensions) {
1868 if (extensions.isNotEmpty) { 1801 if (extensions.isEmpty) return;
1869 var methodNames = <JS.Expression>[]; 1802
1870 for (var e in extensions) { 1803 var names = extensions
1871 methodNames.add(_declareMemberName(e, useExtension: false)); 1804 .map((e) => _declareMemberName(e, useExtension: false))
1872 } 1805 .toList();
1873 body.add(_callHelperStatement('defineExtensionMembers(#, #);', [ 1806 body.add(_callHelperStatement('defineExtensionMembers(#, #);', [
1874 className, 1807 target,
1875 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) 1808 new JS.ArrayInitializer(names, multiline: names.length > 4)
1876 ])); 1809 ]));
1877 } 1810 }
1811
1812 // Define mixin members (if any) on the mixin class.
1813 var mixinClass = js.call('#.__proto__', [className]);
1814 emitExtenstions(mixinClass, _classProperties.mixinExtensionMembers);
1815 emitExtenstions(className, _classProperties.extensionMembers);
1878 } 1816 }
1879 1817
1880 JS.Property _buildSignatureField(String name, List<JS.Property> elements) { 1818 JS.Property _buildSignatureField(String name, List<JS.Property> elements) {
1881 var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1); 1819 var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1);
1882 // TODO(vsm): Remove 1820 // TODO(vsm): Remove
1883 var e = js.call('() => #', o); 1821 var e = js.call('() => #', o);
1884 return new JS.Property(_propertyName(name), e); 1822 return new JS.Property(_propertyName(name), e);
1885 } 1823 }
1886 1824
1887 /// Emit the signature on the class recording the runtime type information 1825 /// Emit the signature on the class recording the runtime type information
1888 void _emitClassSignature( 1826 void _emitClassSignature(
1889 List<MethodDeclaration> methods, 1827 List<MethodDeclaration> methods,
1890 List<FieldDeclaration> fields, 1828 List<FieldDeclaration> fields,
1891 ClassElement classElem, 1829 ClassElement classElem,
1892 List<ConstructorDeclaration> ctors, 1830 List<ConstructorDeclaration> ctors,
1893 List<ExecutableElement> extensions,
1894 JS.Expression className, 1831 JS.Expression className,
1895 List<JS.Statement> body) { 1832 List<JS.Statement> body) {
1896 if (classElem.interfaces.isNotEmpty) { 1833 if (classElem.interfaces.isNotEmpty) {
1897 body.add(js.statement('#[#.implements] = () => #;', [ 1834 body.add(js.statement('#[#.implements] = () => #;', [
1898 className, 1835 className,
1899 _runtimeModule, 1836 _runtimeModule,
1900 new JS.ArrayInitializer( 1837 new JS.ArrayInitializer(
1901 new List<JS.Expression>.from(classElem.interfaces.map(_emitType))) 1838 new List<JS.Expression>.from(classElem.interfaces.map(_emitType)))
1902 ])); 1839 ]));
1903 } 1840 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2032 } 1969 }
2033 if (!tStaticMethods.isEmpty) { 1970 if (!tStaticMethods.isEmpty) {
2034 assert(!sNames.isEmpty); 1971 assert(!sNames.isEmpty);
2035 // Emit names so that we can lazily attach metadata to statics 1972 // Emit names so that we can lazily attach metadata to statics
2036 // TODO(leafp): revisit this strategy 1973 // TODO(leafp): revisit this strategy
2037 var aNames = new JS.Property( 1974 var aNames = new JS.Property(
2038 _propertyName('names'), new JS.ArrayInitializer(sNames)); 1975 _propertyName('names'), new JS.ArrayInitializer(sNames));
2039 sigFields.add(_buildSignatureField('statics', tStaticMethods)); 1976 sigFields.add(_buildSignatureField('statics', tStaticMethods));
2040 sigFields.add(aNames); 1977 sigFields.add(aNames);
2041 } 1978 }
2042 if (!sigFields.isEmpty || extensions.isNotEmpty) { 1979 // We set signature here, even if empty, to simplify the work of
1980 // defineExtensionMembers at runtime. See _defineExtensionMembers.
1981 if (!sigFields.isEmpty ||
1982 _classProperties.extensionMembers.isNotEmpty ||
1983 _classProperties.mixinExtensionMembers.isNotEmpty) {
2043 var sig = new JS.ObjectInitializer(sigFields); 1984 var sig = new JS.ObjectInitializer(sigFields);
2044 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); 1985 body.add(_callHelperStatement('setSignature(#, #);', [className, sig]));
2045 } 1986 }
2046 // Add static property dart._runtimeType to Object. 1987 // Add static property dart._runtimeType to Object.
2047 // All other Dart classes will (statically) inherit this property. 1988 // All other Dart classes will (statically) inherit this property.
2048 if (classElem == objectClass) { 1989 if (classElem == objectClass) {
2049 body.add(_callHelperStatement('tagComputed(#, () => #.#);', 1990 body.add(_callHelperStatement('tagComputed(#, () => #.#);',
2050 [className, emitLibraryName(dartCoreLibrary), 'Type'])); 1991 [className, emitLibraryName(dartCoreLibrary), 'Type']));
2051 } 1992 }
2052 } 1993 }
(...skipping 23 matching lines...) Expand all
2076 } 2017 }
2077 } 2018 }
2078 } 2019 }
2079 if (dartxNames.isNotEmpty) { 2020 if (dartxNames.isNotEmpty) {
2080 body.add(_callHelperStatement('defineExtensionNames(#)', 2021 body.add(_callHelperStatement('defineExtensionNames(#)',
2081 [new JS.ArrayInitializer(dartxNames, multiline: true)])); 2022 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
2082 } 2023 }
2083 } 2024 }
2084 } 2025 }
2085 2026
2086 List<ExecutableElement> _extensionsToImplement(ClassElement element) {
2087 if (_extensionTypes.isNativeClass(element)) return [];
2088
2089 // Collect all extension types we implement.
2090 var type = element.type;
2091 var types = _extensionTypes.collectNativeInterfaces(element);
2092 if (types.isEmpty) return [];
2093
2094 var members = new Set<ExecutableElement>();
2095 // Collect all possible extension method names.
2096 var extensionMembers = new HashSet<String>();
2097 for (var t in types) {
2098 for (var m in [t.methods, t.accessors].expand((e) => e)) {
2099 if (!m.isStatic && m.isPublic) extensionMembers.add(m.name);
2100 }
2101 }
2102
2103 // Collect all of extension methods this type implements.
2104 for (var m in [type.methods, type.accessors].expand((e) => e)) {
2105 if (!m.isStatic && !m.isAbstract && extensionMembers.contains(m.name)) {
2106 members.add(m);
2107 }
2108 }
2109 members.addAll(_collectMockMethods(type)
2110 .where((m) => extensionMembers.contains(m.name)));
2111 return members.toList();
2112 }
2113
2114 /// Generates the implicit default constructor for class C of the form 2027 /// Generates the implicit default constructor for class C of the form
2115 /// `C() : super() {}`. 2028 /// `C() : super() {}`.
2116 JS.Method _emitImplicitConstructor( 2029 JS.Method _emitImplicitConstructor(
2117 ClassDeclaration node, 2030 ClassDeclaration node,
2118 List<FieldDeclaration> fields, 2031 List<FieldDeclaration> fields,
2119 Map<FieldElement, JS.TemporaryId> virtualFields) { 2032 Map<FieldElement, JS.TemporaryId> virtualFields) {
2120 // If we don't have a method body, skip this. 2033 // If we don't have a method body, skip this.
2121 var superCall = _superConstructorCall(node.element); 2034 var superCall = _superConstructorCall(node.element);
2122 if (fields.isEmpty && superCall == null) return null; 2035 if (fields.isEmpty && superCall == null) return null;
2123 2036
(...skipping 3911 matching lines...) Expand 10 before | Expand all | Expand 10 after
6035 if (targetIdentifier.staticElement is! PrefixElement) return false; 5948 if (targetIdentifier.staticElement is! PrefixElement) return false;
6036 var prefix = targetIdentifier.staticElement as PrefixElement; 5949 var prefix = targetIdentifier.staticElement as PrefixElement;
6037 5950
6038 // The library the prefix is referring to must come from a deferred import. 5951 // The library the prefix is referring to must come from a deferred import.
6039 var containingLibrary = resolutionMap 5952 var containingLibrary = resolutionMap
6040 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 5953 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
6041 .library; 5954 .library;
6042 var imports = containingLibrary.getImportsWithPrefix(prefix); 5955 var imports = containingLibrary.getImportsWithPrefix(prefix);
6043 return imports.length == 1 && imports[0].isDeferred; 5956 return imports.length == 1 && imports[0].isDeferred;
6044 } 5957 }
OLDNEW
« no previous file with comments | « no previous file | pkg/dev_compiler/lib/src/compiler/element_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698