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 | 6 |
7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
8 import 'package:analyzer/dart/ast/ast.dart'; | 8 import 'package:analyzer/dart/ast/ast.dart'; |
9 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 9 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
10 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 FunctionBody _currentFunction; | 108 FunctionBody _currentFunction; |
109 | 109 |
110 /// Helper class for emitting elements in the proper order to allow | 110 /// Helper class for emitting elements in the proper order to allow |
111 /// JS to load the module. | 111 /// JS to load the module. |
112 ElementLoader _loader; | 112 ElementLoader _loader; |
113 | 113 |
114 BuildUnit _buildUnit; | 114 BuildUnit _buildUnit; |
115 | 115 |
116 String _buildRoot; | 116 String _buildRoot; |
117 | 117 |
118 /// Whether the current compilation unit being compiled is within the Dart | |
119 /// SDK itself. | |
120 // TODO(rnystrom): Get rid of this if we can treat class literals inside | |
121 // the SDK the same way we do outside. | |
122 bool _compilingSdkLibrary = false; | |
Bob Nystrom
2016/05/02 22:19:09
This is kind of nasty, but it was the most expedie
Jennifer Messerly
2016/05/02 23:04:20
We already have another way to get this info, expl
| |
123 | |
118 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) | 124 CodeGenerator(AnalysisContext c, this.options, this._extensionTypes) |
119 : context = c, | 125 : context = c, |
120 types = c.typeProvider, | 126 types = c.typeProvider, |
121 _asyncStreamIterator = | 127 _asyncStreamIterator = |
122 _getLibrary(c, 'dart:async').getType('StreamIterator').type, | 128 _getLibrary(c, 'dart:async').getType('StreamIterator').type, |
123 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), | 129 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), |
124 dartCoreLibrary = _getLibrary(c, 'dart:core'), | 130 dartCoreLibrary = _getLibrary(c, 'dart:core'), |
125 dartJSLibrary = _getLibrary(c, 'dart:js'); | 131 dartJSLibrary = _getLibrary(c, 'dart:js'); |
126 | 132 |
127 LibraryElement get currentLibrary => _loader.currentElement.library; | 133 LibraryElement get currentLibrary => _loader.currentElement.library; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 | 217 |
212 // Collect all Element -> Node mappings, in case we need to forward declare | 218 // Collect all Element -> Node mappings, in case we need to forward declare |
213 // any nodes. | 219 // any nodes. |
214 var nodes = new HashMap<Element, AstNode>.identity(); | 220 var nodes = new HashMap<Element, AstNode>.identity(); |
215 compilationUnits.map(_collectElements).forEach(nodes.addAll); | 221 compilationUnits.map(_collectElements).forEach(nodes.addAll); |
216 _loader = new ElementLoader(_emitModuleItem, nodes); | 222 _loader = new ElementLoader(_emitModuleItem, nodes); |
217 | 223 |
218 // Add implicit dart:core dependency so it is first. | 224 // Add implicit dart:core dependency so it is first. |
219 emitLibraryName(dartCoreLibrary); | 225 emitLibraryName(dartCoreLibrary); |
220 | 226 |
221 // | |
222 // Visit each compilation unit and emit its code. | 227 // Visit each compilation unit and emit its code. |
223 // | 228 // |
224 // NOTE: declarations are not necessarily emitted in this order. | 229 // NOTE: declarations are not necessarily emitted in this order. |
225 // Order will be changed as needed so the resulting code can execute. | 230 // Order will be changed as needed so the resulting code can execute. |
226 // This is done by forward declaring items. | 231 // This is done by forward declaring items. |
227 compilationUnits.forEach(visitCompilationUnit); | 232 compilationUnits.forEach(visitCompilationUnit); |
228 | 233 |
229 // Declare imports | 234 // Declare imports |
230 _finishImports(items); | 235 _finishImports(items); |
231 | 236 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
329 inferNullableTypes(node); | 334 inferNullableTypes(node); |
330 | 335 |
331 var code = _visit(node); | 336 var code = _visit(node); |
332 if (code != null) _moduleItems.add(code); | 337 if (code != null) _moduleItems.add(code); |
333 } | 338 } |
334 | 339 |
335 @override | 340 @override |
336 void visitCompilationUnit(CompilationUnit unit) { | 341 void visitCompilationUnit(CompilationUnit unit) { |
337 _constField = new ConstFieldVisitor(types, unit.element.source); | 342 _constField = new ConstFieldVisitor(types, unit.element.source); |
338 | 343 |
344 _compilingSdkLibrary = unit.element.source.uri.scheme == "dart"; | |
Jennifer Messerly
2016/05/02 23:04:20
This won't work because we don't necessarily visit
Bob Nystrom
2016/05/03 20:50:47
Done.
| |
345 | |
339 for (var declaration in unit.declarations) { | 346 for (var declaration in unit.declarations) { |
340 var element = declaration.element; | 347 var element = declaration.element; |
341 if (element != null) { | 348 if (element != null) { |
342 _loader.emitDeclaration(element); | 349 _loader.emitDeclaration(element); |
343 } else { | 350 } else { |
344 declaration.accept(this); | 351 declaration.accept(this); |
345 } | 352 } |
346 } | 353 } |
347 for (var directive in unit.directives) { | 354 for (var directive in unit.directives) { |
348 directive.accept(this); | 355 directive.accept(this); |
(...skipping 1609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1958 | 1965 |
1959 // Get the original declaring element. If we had a property accessor, this | 1966 // Get the original declaring element. If we had a property accessor, this |
1960 // indirects back to a (possibly synthetic) field. | 1967 // indirects back to a (possibly synthetic) field. |
1961 var element = accessor; | 1968 var element = accessor; |
1962 if (accessor is PropertyAccessorElement) element = accessor.variable; | 1969 if (accessor is PropertyAccessorElement) element = accessor.variable; |
1963 | 1970 |
1964 _loader.declareBeforeUse(element); | 1971 _loader.declareBeforeUse(element); |
1965 | 1972 |
1966 // type literal | 1973 // type literal |
1967 if (element is TypeDefiningElement) { | 1974 if (element is TypeDefiningElement) { |
1968 return _emitTypeName(fillDynamicTypeArgs(element.type)); | 1975 // TODO(rnystrom): Treating core libraries specially is lame. The JS() |
1976 // code templates often refer to core lib classes and expect that to emit | |
1977 // a reference directly to the JS class (i.e. its constructor), not a | |
1978 // Type object. Figure out how to handle these better. | |
1979 if (_compilingSdkLibrary || | |
Jennifer Messerly
2016/05/02 23:04:20
Here's how this can be done better:
See where we
Bob Nystrom
2016/05/03 20:50:47
Took some doing, but done. Scoping it to just with
| |
1980 node.parent is MethodInvocation || | |
Jennifer Messerly
2016/05/02 23:04:20
FYI: at some point I'd love to ditch parent pointe
Bob Nystrom
2016/05/03 20:50:47
Yeah, this is gross. Doing something more explicit
| |
1981 node.parent is PrefixedIdentifier || | |
1982 node.parent is PropertyAccess) { | |
1983 // A static member call. Emit the class itself. | |
1984 return _emitTypeName(fillDynamicTypeArgs(element.type)); | |
1985 } else { | |
1986 // A type literal expression. Emit the "Type" object that corresponds | |
1987 // to that type. | |
1988 var dynType = fillDynamicTypeArgs(element.type); | |
1989 var isGeneric = dynType is ParameterizedType && | |
1990 dynType.typeArguments.isNotEmpty; | |
1991 var genericInst = _emitTypeName(dynType, lowerGeneric: isGeneric); | |
Jennifer Messerly
2016/05/02 23:04:20
you should never need to pass `lowerGeneric` expli
Bob Nystrom
2016/05/03 20:50:47
Done. I think at first I wasn't filling in the dyn
| |
1992 return js.call('dart.wrapType(#)', genericInst); | |
1993 } | |
1969 } | 1994 } |
1970 | 1995 |
1971 // library member | 1996 // library member |
1972 if (element.enclosingElement is CompilationUnitElement) { | 1997 if (element.enclosingElement is CompilationUnitElement) { |
1973 return _emitTopLevelName(element); | 1998 return _emitTopLevelName(element); |
1974 } | 1999 } |
1975 | 2000 |
1976 var name = element.name; | 2001 var name = element.name; |
1977 | 2002 |
1978 // Unqualified class member. This could mean implicit-this, or implicit | 2003 // Unqualified class member. This could mean implicit-this, or implicit |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2105 | 2130 |
2106 // TODO(jmesserly): like constants, should we hoist function types out of | 2131 // TODO(jmesserly): like constants, should we hoist function types out of |
2107 // methods? Similar issue with generic types. For all of these, we may want | 2132 // methods? Similar issue with generic types. For all of these, we may want |
2108 // to canonicalize them too, at least when inside the same library. | 2133 // to canonicalize them too, at least when inside the same library. |
2109 var name = type.name; | 2134 var name = type.name; |
2110 var element = type.element; | 2135 var element = type.element; |
2111 if (name == '' || name == null || lowerTypedef) { | 2136 if (name == '' || name == null || lowerTypedef) { |
2112 var parts = _emitFunctionTypeParts(type as FunctionType); | 2137 var parts = _emitFunctionTypeParts(type as FunctionType); |
2113 return js.call('dart.functionType(#)', [parts]); | 2138 return js.call('dart.functionType(#)', [parts]); |
2114 } | 2139 } |
2115 // For now, reify generic method parameters as dynamic | 2140 |
2141 // For now, reify generic method parameters as dynamic. | |
2116 bool _isGenericTypeParameter(DartType type) => | 2142 bool _isGenericTypeParameter(DartType type) => |
2117 type is TypeParameterType && | 2143 type is TypeParameterType && |
2118 type.element.enclosingElement is! TypeDefiningElement; | 2144 type.element.enclosingElement is! TypeDefiningElement; |
2119 | 2145 |
2120 if (_isGenericTypeParameter(type)) { | 2146 if (_isGenericTypeParameter(type)) { |
2121 return js.call('dart.dynamic'); | 2147 return js.call('dart.dynamic'); |
2122 } | 2148 } |
2123 | 2149 |
2124 if (type is TypeParameterType) { | 2150 if (type is TypeParameterType) { |
2125 return new JS.Identifier(name); | 2151 return new JS.Identifier(name); |
2126 } | 2152 } |
2127 | 2153 |
2128 if (type is ParameterizedType) { | 2154 if (type is ParameterizedType) { |
2129 var args = type.typeArguments; | 2155 var args = type.typeArguments; |
2130 Iterable jsArgs = null; | 2156 Iterable jsArgs; |
2131 if (args.any((a) => !a.isDynamic && !_isGenericTypeParameter(a))) { | 2157 if (args.any((a) => !a.isDynamic && !_isGenericTypeParameter(a))) { |
2132 jsArgs = args.map(_emitTypeName); | 2158 jsArgs = args.map(_emitTypeName); |
2133 } else if (lowerGeneric) { | 2159 } else if (lowerGeneric) { |
2134 jsArgs = []; | 2160 jsArgs = []; |
2135 } | 2161 } |
2136 if (jsArgs != null) { | 2162 if (jsArgs != null) { |
2137 var genericName = _emitTopLevelName(element, suffix: '\$'); | 2163 var genericName = _emitTopLevelName(element, suffix: '\$'); |
2138 return js.call('#(#)', [genericName, jsArgs]); | 2164 return js.call('#(#)', [genericName, jsArgs]); |
2139 } | 2165 } |
2140 } | 2166 } |
(...skipping 1808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3949 } | 3975 } |
3950 | 3976 |
3951 bool isLibraryPrefix(Expression node) => | 3977 bool isLibraryPrefix(Expression node) => |
3952 node is SimpleIdentifier && node.staticElement is PrefixElement; | 3978 node is SimpleIdentifier && node.staticElement is PrefixElement; |
3953 | 3979 |
3954 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 3980 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
3955 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 3981 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
3956 | 3982 |
3957 bool _isDartRuntime(LibraryElement l) => | 3983 bool _isDartRuntime(LibraryElement l) => |
3958 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 3984 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |