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 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 | 1296 |
1297 // Create enum class | 1297 // Create enum class |
1298 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), | 1298 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), |
1299 _emitClassHeritage(element), [constructor, toStringF]); | 1299 _emitClassHeritage(element), [constructor, toStringF]); |
1300 var id = _emitTopLevelName(element); | 1300 var id = _emitTopLevelName(element); |
1301 | 1301 |
1302 // Emit metadata for synthetic enum index member. | 1302 // Emit metadata for synthetic enum index member. |
1303 // TODO(jacobr): make field readonly when that is supported. | 1303 // TODO(jacobr): make field readonly when that is supported. |
1304 var tInstanceFields = <JS.Property>[ | 1304 var tInstanceFields = <JS.Property>[ |
1305 new JS.Property( | 1305 new JS.Property( |
1306 _emitMemberName('index'), _emitAnnotatedType(intClass.type, null)) | 1306 _emitMemberName('index'), _emitFieldSignature(types.intType)) |
1307 ]; | 1307 ]; |
1308 var sigFields = <JS.Property>[ | 1308 var sigFields = <JS.Property>[]; |
1309 _buildSignatureField('fields', tInstanceFields) | 1309 _buildSignatureField(sigFields, 'fields', tInstanceFields); |
1310 ]; | |
1311 var sig = new JS.ObjectInitializer(sigFields); | 1310 var sig = new JS.ObjectInitializer(sigFields); |
1312 | 1311 |
1313 var result = [ | 1312 var result = [ |
1314 js.statement('# = #', [id, classExpr]), | 1313 js.statement('# = #', [id, classExpr]), |
1315 _callHelperStatement('setSignature(#, #);', [id, sig]) | 1314 _callHelperStatement('setSignature(#, #);', [id, sig]) |
1316 ]; | 1315 ]; |
1317 | 1316 |
1318 // defineEnumValues internally depends on dart.constList which uses | 1317 // defineEnumValues internally depends on dart.constList which uses |
1319 // _interceptors.JSArray. | 1318 // _interceptors.JSArray. |
1320 _declareBeforeUse(_jsArray); | 1319 _declareBeforeUse(_jsArray); |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1839 new JS.ArrayInitializer(names, multiline: names.length > 4) | 1838 new JS.ArrayInitializer(names, multiline: names.length > 4) |
1840 ])); | 1839 ])); |
1841 } | 1840 } |
1842 | 1841 |
1843 // Define mixin members (if any) on the mixin class. | 1842 // Define mixin members (if any) on the mixin class. |
1844 var mixinClass = js.call('#.__proto__', [className]); | 1843 var mixinClass = js.call('#.__proto__', [className]); |
1845 emitExtensions(mixinClass, _classProperties.mixinExtensionMembers); | 1844 emitExtensions(mixinClass, _classProperties.mixinExtensionMembers); |
1846 emitExtensions(className, _classProperties.extensionMembers); | 1845 emitExtensions(className, _classProperties.extensionMembers); |
1847 } | 1846 } |
1848 | 1847 |
1849 JS.Property _buildSignatureField(String name, List<JS.Property> elements) { | 1848 void _buildSignatureField( |
| 1849 List<JS.Property> sigFields, String name, List<JS.Property> elements) { |
| 1850 if (elements.isEmpty) return; |
1850 var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1); | 1851 var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1); |
1851 // TODO(vsm): Remove | 1852 // TODO(vsm): Remove |
1852 var e = js.call('() => #', o); | 1853 var e = js.call('() => #', o); |
1853 return new JS.Property(_propertyName(name), e); | 1854 sigFields.add(new JS.Property(_propertyName(name), e)); |
1854 } | 1855 } |
1855 | 1856 |
1856 /// Emit the signature on the class recording the runtime type information | 1857 /// Emit the signature on the class recording the runtime type information |
1857 void _emitClassSignature( | 1858 void _emitClassSignature( |
1858 List<MethodDeclaration> methods, | 1859 List<MethodDeclaration> methods, |
1859 List<FieldDeclaration> fields, | 1860 List<FieldDeclaration> fields, |
1860 ClassElement classElem, | 1861 ClassElement classElem, |
1861 List<ConstructorDeclaration> ctors, | 1862 List<ConstructorDeclaration> ctors, |
1862 JS.Expression className, | 1863 JS.Expression className, |
1863 List<JS.Statement> body) { | 1864 List<JS.Statement> body) { |
(...skipping 13 matching lines...) Expand all Loading... |
1877 var tStaticSetters = <JS.Property>[]; | 1878 var tStaticSetters = <JS.Property>[]; |
1878 var tInstanceSetters = <JS.Property>[]; | 1879 var tInstanceSetters = <JS.Property>[]; |
1879 var sNames = <JS.Expression>[]; | 1880 var sNames = <JS.Expression>[]; |
1880 for (MethodDeclaration node in methods) { | 1881 for (MethodDeclaration node in methods) { |
1881 var name = node.name.name; | 1882 var name = node.name.name; |
1882 var element = resolutionMap.elementDeclaredByMethodDeclaration(node); | 1883 var element = resolutionMap.elementDeclaredByMethodDeclaration(node); |
1883 // TODO(vsm): Clean up all the nasty duplication. | 1884 // TODO(vsm): Clean up all the nasty duplication. |
1884 if (node.isAbstract) { | 1885 if (node.isAbstract) { |
1885 continue; | 1886 continue; |
1886 } | 1887 } |
1887 if (node.isStatic && | 1888 // Static getters/setters cannot be called with dynamic dispatch, nor |
1888 !options.emitMetadata && | 1889 // can they be torn off. |
| 1890 // TODO(jmesserly): can we attach static method type info at the tearoff |
| 1891 // point, and avoid saving the information otherwise? Same trick would |
| 1892 // work for top-level functions. |
| 1893 if (!options.emitMetadata && |
| 1894 node.isStatic && |
1889 (node.isGetter || node.isSetter)) { | 1895 (node.isGetter || node.isSetter)) { |
1890 continue; | 1896 continue; |
1891 } | 1897 } |
1892 List<JS.Property> tMember; | 1898 List<JS.Property> tMember; |
| 1899 // TODO(jmesserly): these 3 variables should be typed. |
1893 Function getOverride; | 1900 Function getOverride; |
1894 Function lookup; | 1901 Function lookup; |
1895 Function elementToType; | 1902 Function elementToType; |
| 1903 // TODO(jmesserly): we could reduce work by not saving a full function |
| 1904 // type for getters/setters. These only need 1 type to be saved. |
1896 if (node.isGetter) { | 1905 if (node.isGetter) { |
1897 elementToType = (ExecutableElement element) => element.type; | 1906 elementToType = (ExecutableElement element) => element.type; |
1898 getOverride = classElem.lookUpInheritedConcreteGetter; | 1907 getOverride = classElem.lookUpInheritedConcreteGetter; |
1899 lookup = classElem.type.lookUpInheritedGetter; | 1908 lookup = classElem.type.lookUpInheritedGetter; |
1900 tMember = node.isStatic ? tStaticGetters : tInstanceGetters; | 1909 tMember = node.isStatic ? tStaticGetters : tInstanceGetters; |
1901 } else if (node.isSetter) { | 1910 } else if (node.isSetter) { |
1902 elementToType = (ExecutableElement element) => element.type; | 1911 elementToType = (ExecutableElement element) => element.type; |
1903 getOverride = classElem.lookUpInheritedConcreteSetter; | 1912 getOverride = classElem.lookUpInheritedConcreteSetter; |
1904 lookup = classElem.type.lookUpInheritedSetter; | 1913 lookup = classElem.type.lookUpInheritedSetter; |
1905 tMember = node.isStatic ? tStaticSetters : tInstanceSetters; | 1914 tMember = node.isStatic ? tStaticSetters : tInstanceSetters; |
(...skipping 22 matching lines...) Expand all Loading... |
1928 var type = _emitAnnotatedFunctionType(reifiedType, node.metadata, | 1937 var type = _emitAnnotatedFunctionType(reifiedType, node.metadata, |
1929 parameters: node.parameters?.parameters, | 1938 parameters: node.parameters?.parameters, |
1930 nameType: options.hoistSignatureTypes, | 1939 nameType: options.hoistSignatureTypes, |
1931 hoistType: options.hoistSignatureTypes, | 1940 hoistType: options.hoistSignatureTypes, |
1932 definite: true); | 1941 definite: true); |
1933 | 1942 |
1934 if (needsSignature) { | 1943 if (needsSignature) { |
1935 var memberName = _declareMemberName(element); | 1944 var memberName = _declareMemberName(element); |
1936 var property = new JS.Property(memberName, type); | 1945 var property = new JS.Property(memberName, type); |
1937 tMember.add(property); | 1946 tMember.add(property); |
1938 // We record the names of static methods seperately so we can | 1947 // We record the names of static methods separately so we can |
1939 // attach metadata to them individually. | 1948 // attach metadata to them individually. |
1940 // TODO(leafp): Revisit this. | 1949 // TODO(leafp): Revisit this. |
1941 if (node.isStatic && !node.isGetter && !node.isSetter) { | 1950 if (node.isStatic && !node.isGetter && !node.isSetter) { |
1942 sNames.add(memberName); | 1951 sNames.add(memberName); |
1943 } | 1952 } |
1944 } | 1953 } |
1945 } | 1954 } |
1946 | 1955 |
1947 var tInstanceFields = <JS.Property>[]; | 1956 var tInstanceFields = <JS.Property>[]; |
1948 var tStaticFields = <JS.Property>[]; | 1957 var tStaticFields = <JS.Property>[]; |
1949 for (FieldDeclaration node in fields) { | 1958 for (FieldDeclaration node in fields) { |
1950 if (!node.isStatic || options.emitMetadata) { | 1959 // Only instance fields need to be saved for dynamic dispatch. |
| 1960 var isStatic = node.isStatic; |
| 1961 if (options.emitMetadata || !isStatic) { |
1951 for (VariableDeclaration field in node.fields.variables) { | 1962 for (VariableDeclaration field in node.fields.variables) { |
1952 var element = field.element as FieldElement; | 1963 var element = field.element as FieldElement; |
| 1964 var fieldList = isStatic ? tStaticFields : tInstanceFields; |
| 1965 |
1953 var memberName = _declareMemberName(element.getter); | 1966 var memberName = _declareMemberName(element.getter); |
1954 var type = _emitAnnotatedType(element.type, node.metadata); | 1967 var fieldSig = _emitFieldSignature(element.type, |
1955 var property = new JS.Property(memberName, type); | 1968 metadata: node.metadata, isFinal: element.isFinal); |
1956 (node.isStatic ? tStaticFields : tInstanceFields).add(property); | 1969 fieldList.add(new JS.Property(memberName, fieldSig)); |
1957 } | 1970 } |
1958 } | 1971 } |
1959 } | 1972 } |
1960 | 1973 |
1961 var tCtors = <JS.Property>[]; | 1974 var tCtors = <JS.Property>[]; |
1962 if (options.emitMetadata) { | 1975 if (options.emitMetadata) { |
1963 for (ConstructorDeclaration node in ctors) { | 1976 for (ConstructorDeclaration node in ctors) { |
1964 var memberName = _constructorName(node.element); | 1977 var memberName = _constructorName(node.element); |
1965 var element = | 1978 var element = |
1966 resolutionMap.elementDeclaredByConstructorDeclaration(node); | 1979 resolutionMap.elementDeclaredByConstructorDeclaration(node); |
1967 var type = _emitAnnotatedFunctionType(element.type, node.metadata, | 1980 var type = _emitAnnotatedFunctionType(element.type, node.metadata, |
1968 parameters: node.parameters.parameters, | 1981 parameters: node.parameters.parameters, |
1969 nameType: options.hoistSignatureTypes, | 1982 nameType: options.hoistSignatureTypes, |
1970 hoistType: options.hoistSignatureTypes, | 1983 hoistType: options.hoistSignatureTypes, |
1971 definite: true); | 1984 definite: true); |
1972 var property = new JS.Property(memberName, type); | 1985 var property = new JS.Property(memberName, type); |
1973 tCtors.add(property); | 1986 tCtors.add(property); |
1974 } | 1987 } |
1975 } | 1988 } |
1976 var sigFields = <JS.Property>[]; | 1989 var sigFields = <JS.Property>[]; |
1977 if (!tCtors.isEmpty) { | 1990 _buildSignatureField(sigFields, 'constructors', tCtors); |
1978 sigFields.add(_buildSignatureField('constructors', tCtors)); | 1991 _buildSignatureField(sigFields, 'fields', tInstanceFields); |
1979 } | 1992 _buildSignatureField(sigFields, 'getters', tInstanceGetters); |
1980 if (!tInstanceFields.isEmpty) { | 1993 _buildSignatureField(sigFields, 'setters', tInstanceSetters); |
1981 sigFields.add(_buildSignatureField('fields', tInstanceFields)); | 1994 _buildSignatureField(sigFields, 'methods', tInstanceMethods); |
1982 } | 1995 _buildSignatureField(sigFields, 'sfields', tStaticFields); |
1983 if (!tInstanceGetters.isEmpty) { | 1996 _buildSignatureField(sigFields, 'sgetters', tStaticGetters); |
1984 sigFields.add(_buildSignatureField('getters', tInstanceGetters)); | 1997 _buildSignatureField(sigFields, 'ssetters', tStaticSetters); |
1985 } | 1998 _buildSignatureField(sigFields, 'statics', tStaticMethods); |
1986 if (!tInstanceSetters.isEmpty) { | |
1987 sigFields.add(_buildSignatureField('setters', tInstanceSetters)); | |
1988 } | |
1989 if (!tInstanceMethods.isEmpty) { | |
1990 sigFields.add(_buildSignatureField('methods', tInstanceMethods)); | |
1991 } | |
1992 if (!tStaticFields.isEmpty) { | |
1993 sigFields.add(_buildSignatureField('sfields', tStaticFields)); | |
1994 } | |
1995 if (!tStaticGetters.isEmpty) { | |
1996 sigFields.add(_buildSignatureField('sgetters', tStaticGetters)); | |
1997 } | |
1998 if (!tStaticSetters.isEmpty) { | |
1999 sigFields.add(_buildSignatureField('ssetters', tStaticSetters)); | |
2000 } | |
2001 if (!tStaticMethods.isEmpty) { | 1999 if (!tStaticMethods.isEmpty) { |
2002 assert(!sNames.isEmpty); | 2000 assert(!sNames.isEmpty); |
2003 // Emit names so that we can lazily attach metadata to statics | 2001 // Emit names so that we can lazily attach metadata to statics |
2004 // TODO(leafp): revisit this strategy | 2002 // TODO(leafp): revisit this strategy |
2005 var aNames = new JS.Property( | 2003 sigFields.add(new JS.Property( |
2006 _propertyName('names'), new JS.ArrayInitializer(sNames)); | 2004 _propertyName('names'), new JS.ArrayInitializer(sNames))); |
2007 sigFields.add(_buildSignatureField('statics', tStaticMethods)); | |
2008 sigFields.add(aNames); | |
2009 } | 2005 } |
2010 // We set signature here, even if empty, to simplify the work of | 2006 // We set signature here, even if empty, to simplify the work of |
2011 // defineExtensionMembers at runtime. See _defineExtensionMembers. | 2007 // defineExtensionMembers at runtime. See _defineExtensionMembers. |
2012 if (!sigFields.isEmpty || | 2008 if (!sigFields.isEmpty || |
2013 _classProperties.extensionMembers.isNotEmpty || | 2009 _classProperties.extensionMembers.isNotEmpty || |
2014 _classProperties.mixinExtensionMembers.isNotEmpty) { | 2010 _classProperties.mixinExtensionMembers.isNotEmpty) { |
2015 var sig = new JS.ObjectInitializer(sigFields); | 2011 var sig = new JS.ObjectInitializer(sigFields); |
2016 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); | 2012 body.add(_callHelperStatement('setSignature(#, #);', [className, sig])); |
2017 } | 2013 } |
2018 // Add static property dart._runtimeType to Object. | 2014 // Add static property dart._runtimeType to Object. |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2948 return result; | 2944 return result; |
2949 } | 2945 } |
2950 | 2946 |
2951 JS.Expression _emitAnnotatedType(DartType type, List<Annotation> metadata, | 2947 JS.Expression _emitAnnotatedType(DartType type, List<Annotation> metadata, |
2952 {bool nameType: true, bool hoistType: true}) { | 2948 {bool nameType: true, bool hoistType: true}) { |
2953 metadata ??= []; | 2949 metadata ??= []; |
2954 var typeName = _emitType(type, nameType: nameType, hoistType: hoistType); | 2950 var typeName = _emitType(type, nameType: nameType, hoistType: hoistType); |
2955 return _emitAnnotatedResult(typeName, metadata); | 2951 return _emitAnnotatedResult(typeName, metadata); |
2956 } | 2952 } |
2957 | 2953 |
| 2954 JS.Expression _emitFieldSignature(DartType type, |
| 2955 {List<Annotation> metadata, bool isFinal: true}) { |
| 2956 var args = [_emitType(type)]; |
| 2957 if (options.emitMetadata && metadata != null && metadata.isNotEmpty) { |
| 2958 args.add(new JS.ArrayInitializer( |
| 2959 metadata.map(_instantiateAnnotation).toList())); |
| 2960 } |
| 2961 return _callHelper(isFinal ? 'finalFieldType(#)' : 'fieldType(#)', args); |
| 2962 } |
| 2963 |
2958 JS.ArrayInitializer _emitTypeNames( | 2964 JS.ArrayInitializer _emitTypeNames( |
2959 List<DartType> types, List<FormalParameter> parameters, | 2965 List<DartType> types, List<FormalParameter> parameters, |
2960 {bool nameType: true, bool hoistType: true}) { | 2966 {bool nameType: true, bool hoistType: true}) { |
2961 var result = <JS.Expression>[]; | 2967 var result = <JS.Expression>[]; |
2962 for (int i = 0; i < types.length; ++i) { | 2968 for (int i = 0; i < types.length; ++i) { |
2963 var metadata = parameters != null | 2969 var metadata = parameters != null |
2964 ? _parameterMetadata(parameters[i]) | 2970 ? _parameterMetadata(parameters[i]) |
2965 : <Annotation>[]; | 2971 : <Annotation>[]; |
2966 result.add(_emitAnnotatedType(types[i], metadata)); | 2972 result.add(_emitAnnotatedType(types[i], metadata)); |
2967 } | 2973 } |
(...skipping 3160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6128 if (targetIdentifier.staticElement is! PrefixElement) return false; | 6134 if (targetIdentifier.staticElement is! PrefixElement) return false; |
6129 var prefix = targetIdentifier.staticElement as PrefixElement; | 6135 var prefix = targetIdentifier.staticElement as PrefixElement; |
6130 | 6136 |
6131 // The library the prefix is referring to must come from a deferred import. | 6137 // The library the prefix is referring to must come from a deferred import. |
6132 var containingLibrary = resolutionMap | 6138 var containingLibrary = resolutionMap |
6133 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 6139 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
6134 .library; | 6140 .library; |
6135 var imports = containingLibrary.getImportsWithPrefix(prefix); | 6141 var imports = containingLibrary.getImportsWithPrefix(prefix); |
6136 return imports.length == 1 && imports[0].isDeferred; | 6142 return imports.length == 1 && imports[0].isDeferred; |
6137 } | 6143 } |
OLD | NEW |