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 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 _defineClass(classElem, className, classExpr, isCallable, body); | 726 _defineClass(classElem, className, classExpr, isCallable, body); |
727 | 727 |
728 // Emit things that come after the ES6 `class ... { ... }`. | 728 // Emit things that come after the ES6 `class ... { ... }`. |
729 var jsPeerName = _getJSPeerName(classElem); | 729 var jsPeerName = _getJSPeerName(classElem); |
730 _setBaseClass(classElem, className, jsPeerName, body); | 730 _setBaseClass(classElem, className, jsPeerName, body); |
731 | 731 |
732 _emitClassTypeTests(classElem, className, body); | 732 _emitClassTypeTests(classElem, className, body); |
733 | 733 |
734 _defineNamedConstructors(ctors, body, className, isCallable); | 734 _defineNamedConstructors(ctors, body, className, isCallable); |
735 _emitVirtualFieldSymbols(virtualFieldSymbols, body); | 735 _emitVirtualFieldSymbols(virtualFieldSymbols, body); |
736 _emitClassSignature(methods, classElem, ctors, extensions, className, body); | 736 _emitClassSignature( |
| 737 methods, allFields, classElem, ctors, extensions, className, body); |
737 _defineExtensionMembers(extensions, className, body); | 738 _defineExtensionMembers(extensions, className, body); |
738 _emitClassMetadata(node.metadata, className, body); | 739 _emitClassMetadata(node.metadata, className, body); |
739 | 740 |
740 JS.Statement classDef = _statement(body); | 741 JS.Statement classDef = _statement(body); |
741 var typeFormals = classElem.typeParameters; | 742 var typeFormals = classElem.typeParameters; |
742 if (typeFormals.isNotEmpty) { | 743 if (typeFormals.isNotEmpty) { |
743 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); | 744 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); |
744 } | 745 } |
745 | 746 |
746 body = <JS.Statement>[classDef]; | 747 body = <JS.Statement>[classDef]; |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1643 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ | 1644 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ |
1644 className, | 1645 className, |
1645 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) | 1646 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) |
1646 ])); | 1647 ])); |
1647 } | 1648 } |
1648 } | 1649 } |
1649 | 1650 |
1650 /// Emit the signature on the class recording the runtime type information | 1651 /// Emit the signature on the class recording the runtime type information |
1651 void _emitClassSignature( | 1652 void _emitClassSignature( |
1652 List<MethodDeclaration> methods, | 1653 List<MethodDeclaration> methods, |
| 1654 List<FieldDeclaration> fields, |
1653 ClassElement classElem, | 1655 ClassElement classElem, |
1654 List<ConstructorDeclaration> ctors, | 1656 List<ConstructorDeclaration> ctors, |
1655 List<ExecutableElement> extensions, | 1657 List<ExecutableElement> extensions, |
1656 JS.Expression className, | 1658 JS.Expression className, |
1657 List<JS.Statement> body) { | 1659 List<JS.Statement> body) { |
1658 if (classElem.interfaces.isNotEmpty) { | 1660 if (classElem.interfaces.isNotEmpty) { |
1659 body.add(js.statement('#[dart.implements] = () => #;', [ | 1661 body.add(js.statement('#[dart.implements] = () => #;', [ |
1660 className, | 1662 className, |
1661 new JS.ArrayInitializer( | 1663 new JS.ArrayInitializer( |
1662 new List<JS.Expression>.from(classElem.interfaces.map(_emitType))) | 1664 new List<JS.Expression>.from(classElem.interfaces.map(_emitType))) |
1663 ])); | 1665 ])); |
1664 } | 1666 } |
1665 | 1667 |
1666 var tStatics = <JS.Property>[]; | 1668 var tStaticMethods = <JS.Property>[]; |
1667 var tMethods = <JS.Property>[]; | 1669 var tInstanceMethods = <JS.Property>[]; |
| 1670 var tStaticGetters = <JS.Property>[]; |
| 1671 var tInstanceGetters = <JS.Property>[]; |
| 1672 var tStaticSetters = <JS.Property>[]; |
| 1673 var tInstanceSetters = <JS.Property>[]; |
1668 var sNames = <JS.Expression>[]; | 1674 var sNames = <JS.Expression>[]; |
1669 for (MethodDeclaration node in methods) { | 1675 for (MethodDeclaration node in methods) { |
1670 if (!(node.isSetter || node.isGetter || node.isAbstract)) { | 1676 var name = node.name.name; |
1671 var name = node.name.name; | 1677 var element = node.element; |
1672 var element = node.element; | 1678 // TODO(vsm): Clean up all the nasty duplication. |
1673 var inheritedElement = | 1679 if (node.isAbstract) { |
1674 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); | 1680 continue; |
1675 if (inheritedElement != null && inheritedElement.type == element.type) { | 1681 } |
1676 continue; | 1682 |
1677 } | 1683 Function lookup; |
1678 var memberName = _elementMemberName(element, | 1684 List<JS.Property> tMember; |
1679 useExtension: _extensionTypes.isNativeClass(classElem)); | 1685 JS.Expression type; |
1680 var type = _emitFunctionType(element.type, | 1686 if (node.isGetter) { |
1681 nameType: options.hoistSignatureTypes, | 1687 lookup = classElem.lookUpInheritedConcreteGetter; |
1682 hoistType: options.hoistSignatureTypes, | 1688 tMember = node.isStatic ? tStaticGetters : tInstanceGetters; |
1683 definite: true); | 1689 } else if (node.isSetter) { |
1684 var property = new JS.Property(memberName, type); | 1690 lookup = classElem.lookUpInheritedConcreteSetter; |
1685 if (node.isStatic) { | 1691 tMember = node.isStatic ? tStaticSetters : tInstanceSetters; |
1686 tStatics.add(property); | 1692 } else { |
1687 sNames.add(memberName); | 1693 // Method |
1688 } else { | 1694 lookup = classElem.lookUpInheritedConcreteMethod; |
1689 tMethods.add(property); | 1695 tMember = node.isStatic ? tStaticMethods : tInstanceMethods; |
1690 } | 1696 } |
| 1697 |
| 1698 type = _emitAnnotatedFunctionType(element.type, node.metadata, |
| 1699 parameters: node.parameters?.parameters, |
| 1700 nameType: options.hoistSignatureTypes, |
| 1701 hoistType: options.hoistSignatureTypes, |
| 1702 definite: true); |
| 1703 |
| 1704 var inheritedElement = lookup(name, currentLibrary); |
| 1705 if (inheritedElement != null && inheritedElement.type == element.type) { |
| 1706 continue; |
| 1707 } |
| 1708 var memberName = _elementMemberName(element, |
| 1709 useExtension: _extensionTypes.isNativeClass(classElem)); |
| 1710 var property = new JS.Property(memberName, type); |
| 1711 tMember.add(property); |
| 1712 // TODO(vsm): Why do we need this? |
| 1713 if (node.isStatic && !node.isGetter && !node.isSetter) { |
| 1714 sNames.add(memberName); |
1691 } | 1715 } |
1692 } | 1716 } |
1693 | 1717 |
| 1718 var tInstanceFields = <JS.Property>[]; |
| 1719 var tStaticFields = <JS.Property>[]; |
| 1720 for (FieldDeclaration node in fields) { |
| 1721 for (VariableDeclaration field in node.fields.variables) { |
| 1722 var element = field.element as FieldElement; |
| 1723 var memberName = _elementMemberName(element.getter, |
| 1724 useExtension: _extensionTypes.isNativeClass(classElem)); |
| 1725 var type = _emitAnnotatedType(element.type, node.metadata); |
| 1726 var property = new JS.Property(memberName, type); |
| 1727 (node.isStatic ? tStaticFields : tInstanceFields).add(property); |
| 1728 } |
| 1729 } |
| 1730 |
1694 var tCtors = <JS.Property>[]; | 1731 var tCtors = <JS.Property>[]; |
1695 for (ConstructorDeclaration node in ctors) { | 1732 for (ConstructorDeclaration node in ctors) { |
1696 var memberName = _constructorName(node.element); | 1733 var memberName = _constructorName(node.element); |
1697 var element = node.element; | 1734 var element = node.element; |
1698 var type = _emitFunctionType(element.type, | 1735 var type = _emitAnnotatedFunctionType(element.type, node.metadata, |
1699 parameters: node.parameters.parameters, | 1736 parameters: node.parameters.parameters, |
1700 nameType: options.hoistSignatureTypes, | 1737 nameType: options.hoistSignatureTypes, |
1701 hoistType: options.hoistSignatureTypes, | 1738 hoistType: options.hoistSignatureTypes, |
1702 definite: true); | 1739 definite: true); |
1703 var property = new JS.Property(memberName, type); | 1740 var property = new JS.Property(memberName, type); |
1704 tCtors.add(property); | 1741 tCtors.add(property); |
1705 } | 1742 } |
1706 | 1743 |
1707 JS.Property build(String name, List<JS.Property> elements) { | 1744 JS.Property build(String name, List<JS.Property> elements) { |
1708 var o = | 1745 var o = |
1709 new JS.ObjectInitializer(elements, multiline: elements.length > 1); | 1746 new JS.ObjectInitializer(elements, multiline: elements.length > 1); |
| 1747 // TODO(vsm): Remove |
1710 var e = js.call('() => #', o); | 1748 var e = js.call('() => #', o); |
1711 return new JS.Property(_propertyName(name), e); | 1749 return new JS.Property(_propertyName(name), e); |
1712 } | 1750 } |
1713 | 1751 |
1714 var sigFields = <JS.Property>[]; | 1752 var sigFields = <JS.Property>[]; |
1715 if (!tCtors.isEmpty) sigFields.add(build('constructors', tCtors)); | 1753 if (!tCtors.isEmpty) { |
1716 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods)); | 1754 sigFields.add(build('constructors', tCtors)); |
1717 if (!tStatics.isEmpty) { | 1755 } |
| 1756 if (!tInstanceFields.isEmpty) { |
| 1757 sigFields.add(build('fields', tInstanceFields)); |
| 1758 } |
| 1759 if (!tInstanceGetters.isEmpty) { |
| 1760 sigFields.add(build('getters', tInstanceGetters)); |
| 1761 } |
| 1762 if (!tInstanceSetters.isEmpty) { |
| 1763 sigFields.add(build('setters', tInstanceSetters)); |
| 1764 } |
| 1765 if (!tInstanceMethods.isEmpty) { |
| 1766 sigFields.add(build('methods', tInstanceMethods)); |
| 1767 } |
| 1768 if (!tStaticFields.isEmpty) { |
| 1769 sigFields.add(build('sfields', tStaticFields)); |
| 1770 } |
| 1771 if (!tStaticGetters.isEmpty) { |
| 1772 sigFields.add(build('sgetters', tStaticGetters)); |
| 1773 } |
| 1774 if (!tStaticSetters.isEmpty) { |
| 1775 sigFields.add(build('ssetters', tStaticSetters)); |
| 1776 } |
| 1777 if (!tStaticMethods.isEmpty) { |
1718 assert(!sNames.isEmpty); | 1778 assert(!sNames.isEmpty); |
| 1779 // TODO(vsm): Why do we need this names field? |
1719 var aNames = new JS.Property( | 1780 var aNames = new JS.Property( |
1720 _propertyName('names'), new JS.ArrayInitializer(sNames)); | 1781 _propertyName('names'), new JS.ArrayInitializer(sNames)); |
1721 sigFields.add(build('statics', tStatics)); | 1782 sigFields.add(build('statics', tStaticMethods)); |
1722 sigFields.add(aNames); | 1783 sigFields.add(aNames); |
1723 } | 1784 } |
1724 if (!sigFields.isEmpty || extensions.isNotEmpty) { | 1785 if (!sigFields.isEmpty || extensions.isNotEmpty) { |
1725 var sig = new JS.ObjectInitializer(sigFields); | 1786 var sig = new JS.ObjectInitializer(sigFields); |
1726 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); | 1787 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); |
1727 } | 1788 } |
1728 // Add static property dart._runtimeType to Object. | 1789 // Add static property dart._runtimeType to Object. |
1729 // All other Dart classes will (statically) inherit this property. | 1790 // All other Dart classes will (statically) inherit this property. |
1730 if (classElem == objectClass) { | 1791 if (classElem == objectClass) { |
1731 body.add(js.statement('dart.tagComputed(#, () => #.#);', | 1792 body.add(js.statement('dart.tagComputed(#, () => #.#);', |
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2662 | 2723 |
2663 var type = declaration ? emitTypeRef(element.type) : null; | 2724 var type = declaration ? emitTypeRef(element.type) : null; |
2664 return new JS.Identifier(element.name, type: type); | 2725 return new JS.Identifier(element.name, type: type); |
2665 } | 2726 } |
2666 | 2727 |
2667 List<Annotation> _parameterMetadata(FormalParameter p) => | 2728 List<Annotation> _parameterMetadata(FormalParameter p) => |
2668 (p is NormalFormalParameter) | 2729 (p is NormalFormalParameter) |
2669 ? p.metadata | 2730 ? p.metadata |
2670 : (p as DefaultFormalParameter).parameter.metadata; | 2731 : (p as DefaultFormalParameter).parameter.metadata; |
2671 | 2732 |
| 2733 // Wrap a result - usually a type - with its metadata. The runtime is |
| 2734 // responsible for unpacking this. |
| 2735 JS.Expression _emitAnnotatedResult( |
| 2736 JS.Expression result, List<Annotation> metadata) { |
| 2737 if (options.emitMetadata && metadata != null && metadata.isNotEmpty) { |
| 2738 result = new JS.ArrayInitializer( |
| 2739 [result]..addAll(metadata.map(_instantiateAnnotation))); |
| 2740 } |
| 2741 return result; |
| 2742 } |
| 2743 |
| 2744 JS.Expression _emitAnnotatedType(DartType type, List<Annotation> metadata, |
| 2745 {bool nameType: true, bool hoistType: true}) { |
| 2746 metadata ??= []; |
| 2747 var typeName = _emitType(type, nameType: nameType, hoistType: hoistType); |
| 2748 return _emitAnnotatedResult(typeName, metadata); |
| 2749 } |
| 2750 |
2672 JS.ArrayInitializer _emitTypeNames( | 2751 JS.ArrayInitializer _emitTypeNames( |
2673 List<DartType> types, List<FormalParameter> parameters, | 2752 List<DartType> types, List<FormalParameter> parameters, |
2674 {bool nameType: true, bool hoistType: true}) { | 2753 {bool nameType: true, bool hoistType: true}) { |
2675 var result = <JS.Expression>[]; | 2754 var result = <JS.Expression>[]; |
2676 for (int i = 0; i < types.length; ++i) { | 2755 for (int i = 0; i < types.length; ++i) { |
2677 var metadata = | 2756 var metadata = parameters != null |
2678 parameters != null ? _parameterMetadata(parameters[i]) : []; | 2757 ? _parameterMetadata(parameters[i]) |
2679 var typeName = | 2758 : <Annotation>[]; |
2680 _emitType(types[i], nameType: nameType, hoistType: hoistType); | 2759 result.add(_emitAnnotatedType(types[i], metadata)); |
2681 var value = typeName; | |
2682 if (options.emitMetadata && metadata.isNotEmpty) { | |
2683 value = new JS.ArrayInitializer( | |
2684 [typeName]..addAll(metadata.map(_instantiateAnnotation))); | |
2685 } | |
2686 result.add(value); | |
2687 } | 2760 } |
2688 return new JS.ArrayInitializer(result); | 2761 return new JS.ArrayInitializer(result); |
2689 } | 2762 } |
2690 | 2763 |
2691 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { | 2764 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { |
2692 var properties = <JS.Property>[]; | 2765 var properties = <JS.Property>[]; |
2693 types.forEach((name, type) { | 2766 types.forEach((name, type) { |
2694 var key = _propertyName(name); | 2767 var key = _propertyName(name); |
2695 var value = _emitType(type); | 2768 var value = _emitType(type); |
2696 properties.add(new JS.Property(key, value)); | 2769 properties.add(new JS.Property(key, value)); |
(...skipping 14 matching lines...) Expand all Loading... |
2711 lowerTypedef: lowerTypedef, | 2784 lowerTypedef: lowerTypedef, |
2712 nameType: nameType, | 2785 nameType: nameType, |
2713 hoistType: hoistType); | 2786 hoistType: hoistType); |
2714 var helper = (definite) ? 'definiteFunctionType' : 'functionType'; | 2787 var helper = (definite) ? 'definiteFunctionType' : 'functionType'; |
2715 var fullType = js.call('dart.${helper}(#)', [parts]); | 2788 var fullType = js.call('dart.${helper}(#)', [parts]); |
2716 if (!nameType) return fullType; | 2789 if (!nameType) return fullType; |
2717 return _typeTable.nameType(type, fullType, | 2790 return _typeTable.nameType(type, fullType, |
2718 hoistType: hoistType, definite: definite); | 2791 hoistType: hoistType, definite: definite); |
2719 } | 2792 } |
2720 | 2793 |
| 2794 JS.Expression _emitAnnotatedFunctionType( |
| 2795 FunctionType type, List<Annotation> metadata, |
| 2796 {List<FormalParameter> parameters, |
| 2797 bool lowerTypedef: false, |
| 2798 bool nameType: true, |
| 2799 bool hoistType: true, |
| 2800 bool definite: false}) { |
| 2801 var result = _emitFunctionType(type, |
| 2802 parameters: parameters, |
| 2803 lowerTypedef: lowerTypedef, |
| 2804 nameType: nameType, |
| 2805 hoistType: hoistType, |
| 2806 definite: definite); |
| 2807 return _emitAnnotatedResult(result, metadata); |
| 2808 } |
| 2809 |
2721 /// Emit the pieces of a function type, as an array of return type, | 2810 /// Emit the pieces of a function type, as an array of return type, |
2722 /// regular args, and optional/named args. | 2811 /// regular args, and optional/named args. |
2723 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, | 2812 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, |
2724 {List<FormalParameter> parameters, | 2813 {List<FormalParameter> parameters, |
2725 bool lowerTypedef: false, | 2814 bool lowerTypedef: false, |
2726 bool nameType: true, | 2815 bool nameType: true, |
2727 bool hoistType: true}) { | 2816 bool hoistType: true}) { |
2728 var parameterTypes = type.normalParameterTypes; | 2817 var parameterTypes = type.normalParameterTypes; |
2729 var optionalTypes = type.optionalParameterTypes; | 2818 var optionalTypes = type.optionalParameterTypes; |
2730 var namedTypes = type.namedParameterTypes; | 2819 var namedTypes = type.namedParameterTypes; |
(...skipping 2632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5363 } | 5452 } |
5364 | 5453 |
5365 bool isLibraryPrefix(Expression node) => | 5454 bool isLibraryPrefix(Expression node) => |
5366 node is SimpleIdentifier && node.staticElement is PrefixElement; | 5455 node is SimpleIdentifier && node.staticElement is PrefixElement; |
5367 | 5456 |
5368 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 5457 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
5369 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 5458 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
5370 | 5459 |
5371 bool _isDartRuntime(LibraryElement l) => | 5460 bool _isDartRuntime(LibraryElement l) => |
5372 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 5461 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |