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) sigFields.add(build('constructors', tCtors)); |
1716 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods)); | 1754 if (!tInstanceFields.isEmpty) |
Jennifer Messerly
2016/09/01 16:42:43
style nit: add curly braces since it didn't fit on
| |
1717 if (!tStatics.isEmpty) { | 1755 sigFields.add(build('fields', tInstanceFields)); |
1756 if (!tInstanceGetters.isEmpty) | |
1757 sigFields.add(build('getters', tInstanceGetters)); | |
1758 if (!tInstanceSetters.isEmpty) | |
1759 sigFields.add(build('setters', tInstanceSetters)); | |
1760 if (!tInstanceMethods.isEmpty) | |
1761 sigFields.add(build('methods', tInstanceMethods)); | |
1762 if (!tStaticFields.isEmpty) sigFields.add(build('sfields', tStaticFields)); | |
1763 if (!tStaticGetters.isEmpty) | |
1764 sigFields.add(build('sgetters', tStaticGetters)); | |
1765 if (!tStaticSetters.isEmpty) | |
1766 sigFields.add(build('ssetters', tStaticSetters)); | |
1767 if (!tStaticMethods.isEmpty) { | |
1718 assert(!sNames.isEmpty); | 1768 assert(!sNames.isEmpty); |
1769 // TODO(vsm): Why do we need this names field? | |
1719 var aNames = new JS.Property( | 1770 var aNames = new JS.Property( |
1720 _propertyName('names'), new JS.ArrayInitializer(sNames)); | 1771 _propertyName('names'), new JS.ArrayInitializer(sNames)); |
1721 sigFields.add(build('statics', tStatics)); | 1772 sigFields.add(build('statics', tStaticMethods)); |
1722 sigFields.add(aNames); | 1773 sigFields.add(aNames); |
1723 } | 1774 } |
1724 if (!sigFields.isEmpty || extensions.isNotEmpty) { | 1775 if (!sigFields.isEmpty || extensions.isNotEmpty) { |
1725 var sig = new JS.ObjectInitializer(sigFields); | 1776 var sig = new JS.ObjectInitializer(sigFields); |
1726 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); | 1777 body.add(js.statement('dart.setSignature(#, #);', [className, sig])); |
1727 } | 1778 } |
1728 // Add static property dart._runtimeType to Object. | 1779 // Add static property dart._runtimeType to Object. |
1729 // All other Dart classes will (statically) inherit this property. | 1780 // All other Dart classes will (statically) inherit this property. |
1730 if (classElem == objectClass) { | 1781 if (classElem == objectClass) { |
1731 body.add(js.statement('dart.tagComputed(#, () => #.#);', | 1782 body.add(js.statement('dart.tagComputed(#, () => #.#);', |
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2662 | 2713 |
2663 var type = declaration ? emitTypeRef(element.type) : null; | 2714 var type = declaration ? emitTypeRef(element.type) : null; |
2664 return new JS.Identifier(element.name, type: type); | 2715 return new JS.Identifier(element.name, type: type); |
2665 } | 2716 } |
2666 | 2717 |
2667 List<Annotation> _parameterMetadata(FormalParameter p) => | 2718 List<Annotation> _parameterMetadata(FormalParameter p) => |
2668 (p is NormalFormalParameter) | 2719 (p is NormalFormalParameter) |
2669 ? p.metadata | 2720 ? p.metadata |
2670 : (p as DefaultFormalParameter).parameter.metadata; | 2721 : (p as DefaultFormalParameter).parameter.metadata; |
2671 | 2722 |
2723 // Wrap a result - usually a type - with its metadata. The runtime is | |
2724 // responsible for unpacking this. | |
2725 JS.Expression _emitAnnotatedResult( | |
2726 JS.Expression result, List<Annotation> metadata) { | |
2727 if (options.emitMetadata && metadata != null && metadata.isNotEmpty) { | |
2728 result = new JS.ArrayInitializer( | |
2729 [result]..addAll(metadata.map(_instantiateAnnotation))); | |
2730 } | |
2731 return result; | |
2732 } | |
2733 | |
2734 JS.Expression _emitAnnotatedType(DartType type, List<Annotation> metadata, | |
2735 {bool nameType: true, bool hoistType: true}) { | |
2736 metadata ??= []; | |
2737 var typeName = _emitType(type, nameType: nameType, hoistType: hoistType); | |
2738 return _emitAnnotatedResult(typeName, metadata); | |
2739 } | |
2740 | |
2672 JS.ArrayInitializer _emitTypeNames( | 2741 JS.ArrayInitializer _emitTypeNames( |
2673 List<DartType> types, List<FormalParameter> parameters, | 2742 List<DartType> types, List<FormalParameter> parameters, |
2674 {bool nameType: true, bool hoistType: true}) { | 2743 {bool nameType: true, bool hoistType: true}) { |
2675 var result = <JS.Expression>[]; | 2744 var result = <JS.Expression>[]; |
2676 for (int i = 0; i < types.length; ++i) { | 2745 for (int i = 0; i < types.length; ++i) { |
2677 var metadata = | 2746 var metadata = parameters != null |
2678 parameters != null ? _parameterMetadata(parameters[i]) : []; | 2747 ? _parameterMetadata(parameters[i]) |
2679 var typeName = | 2748 : <Annotation>[]; |
2680 _emitType(types[i], nameType: nameType, hoistType: hoistType); | 2749 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 } | 2750 } |
2688 return new JS.ArrayInitializer(result); | 2751 return new JS.ArrayInitializer(result); |
2689 } | 2752 } |
2690 | 2753 |
2691 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { | 2754 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { |
2692 var properties = <JS.Property>[]; | 2755 var properties = <JS.Property>[]; |
2693 types.forEach((name, type) { | 2756 types.forEach((name, type) { |
2694 var key = _propertyName(name); | 2757 var key = _propertyName(name); |
2695 var value = _emitType(type); | 2758 var value = _emitType(type); |
2696 properties.add(new JS.Property(key, value)); | 2759 properties.add(new JS.Property(key, value)); |
(...skipping 14 matching lines...) Expand all Loading... | |
2711 lowerTypedef: lowerTypedef, | 2774 lowerTypedef: lowerTypedef, |
2712 nameType: nameType, | 2775 nameType: nameType, |
2713 hoistType: hoistType); | 2776 hoistType: hoistType); |
2714 var helper = (definite) ? 'definiteFunctionType' : 'functionType'; | 2777 var helper = (definite) ? 'definiteFunctionType' : 'functionType'; |
2715 var fullType = js.call('dart.${helper}(#)', [parts]); | 2778 var fullType = js.call('dart.${helper}(#)', [parts]); |
2716 if (!nameType) return fullType; | 2779 if (!nameType) return fullType; |
2717 return _typeTable.nameType(type, fullType, | 2780 return _typeTable.nameType(type, fullType, |
2718 hoistType: hoistType, definite: definite); | 2781 hoistType: hoistType, definite: definite); |
2719 } | 2782 } |
2720 | 2783 |
2784 JS.Expression _emitAnnotatedFunctionType( | |
2785 FunctionType type, List<Annotation> metadata, | |
2786 {List<FormalParameter> parameters, | |
2787 bool lowerTypedef: false, | |
2788 bool nameType: true, | |
2789 bool hoistType: true, | |
2790 bool definite: false}) { | |
2791 var result = _emitFunctionType(type, | |
2792 parameters: parameters, | |
2793 lowerTypedef: lowerTypedef, | |
2794 nameType: nameType, | |
2795 hoistType: hoistType, | |
2796 definite: definite); | |
2797 return _emitAnnotatedResult(result, metadata); | |
2798 } | |
2799 | |
2721 /// Emit the pieces of a function type, as an array of return type, | 2800 /// Emit the pieces of a function type, as an array of return type, |
2722 /// regular args, and optional/named args. | 2801 /// regular args, and optional/named args. |
2723 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, | 2802 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, |
2724 {List<FormalParameter> parameters, | 2803 {List<FormalParameter> parameters, |
2725 bool lowerTypedef: false, | 2804 bool lowerTypedef: false, |
2726 bool nameType: true, | 2805 bool nameType: true, |
2727 bool hoistType: true}) { | 2806 bool hoistType: true}) { |
2728 var parameterTypes = type.normalParameterTypes; | 2807 var parameterTypes = type.normalParameterTypes; |
2729 var optionalTypes = type.optionalParameterTypes; | 2808 var optionalTypes = type.optionalParameterTypes; |
2730 var namedTypes = type.namedParameterTypes; | 2809 var namedTypes = type.namedParameterTypes; |
(...skipping 2632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5363 } | 5442 } |
5364 | 5443 |
5365 bool isLibraryPrefix(Expression node) => | 5444 bool isLibraryPrefix(Expression node) => |
5366 node is SimpleIdentifier && node.staticElement is PrefixElement; | 5445 node is SimpleIdentifier && node.staticElement is PrefixElement; |
5367 | 5446 |
5368 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 5447 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
5369 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 5448 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
5370 | 5449 |
5371 bool _isDartRuntime(LibraryElement l) => | 5450 bool _isDartRuntime(LibraryElement l) => |
5372 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 5451 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |