Chromium Code Reviews| 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 |