Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/code_generator.dart

Issue 2551023005: Prepare for decoupling analyzer ASTs from element model. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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';
11 import 'package:analyzer/dart/ast/standard_ast_factory.dart'; 11 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
12 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; 12 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
13 import 'package:analyzer/dart/ast/resolution_accessors.dart';
13 import 'package:analyzer/dart/element/element.dart'; 14 import 'package:analyzer/dart/element/element.dart';
14 import 'package:analyzer/dart/element/type.dart'; 15 import 'package:analyzer/dart/element/type.dart';
15 import 'package:analyzer/src/dart/ast/token.dart' show StringToken; 16 import 'package:analyzer/src/dart/ast/token.dart' show StringToken;
16 import 'package:analyzer/src/dart/element/element.dart' 17 import 'package:analyzer/src/dart/element/element.dart'
17 show LocalVariableElementImpl; 18 show LocalVariableElementImpl;
18 import 'package:analyzer/src/dart/element/type.dart' show DynamicTypeImpl; 19 import 'package:analyzer/src/dart/element/type.dart' show DynamicTypeImpl;
19 import 'package:analyzer/src/dart/sdk/sdk.dart'; 20 import 'package:analyzer/src/dart/sdk/sdk.dart';
20 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; 21 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
21 import 'package:analyzer/src/generated/resolver.dart' 22 import 'package:analyzer/src/generated/resolver.dart'
22 show TypeProvider, NamespaceBuilder; 23 show TypeProvider, NamespaceBuilder;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 186
186 var module = _emitModule(compilationUnits); 187 var module = _emitModule(compilationUnits);
187 var dartApiSummary = _summarizeModule(compilationUnits); 188 var dartApiSummary = _summarizeModule(compilationUnits);
188 189
189 return new JSModuleFile(unit.name, errors, options, module, dartApiSummary); 190 return new JSModuleFile(unit.name, errors, options, module, dartApiSummary);
190 } 191 }
191 192
192 List<int> _summarizeModule(List<CompilationUnit> units) { 193 List<int> _summarizeModule(List<CompilationUnit> units) {
193 if (!options.summarizeApi) return null; 194 if (!options.summarizeApi) return null;
194 195
195 if (!units.any((u) => u.element.librarySource.isInSystemLibrary)) { 196 if (!units.any((u) => elementForCompilationUnit(u).librarySource.isInSystemL ibrary)) {
196 var sdk = context.sourceFactory.dartSdk; 197 var sdk = context.sourceFactory.dartSdk;
197 summaryData.addBundle( 198 summaryData.addBundle(
198 null, 199 null,
199 sdk is SummaryBasedDartSdk 200 sdk is SummaryBasedDartSdk
200 ? sdk.bundle 201 ? sdk.bundle
201 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true)); 202 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true));
202 } 203 }
203 204
204 var assembler = new PackageBundleAssembler(); 205 var assembler = new PackageBundleAssembler();
205 assembler.recordDependencies(summaryData); 206 assembler.recordDependencies(summaryData);
(...skipping 21 matching lines...) Expand all
227 } 228 }
228 229
229 JS.Program _emitModule(List<CompilationUnit> compilationUnits) { 230 JS.Program _emitModule(List<CompilationUnit> compilationUnits) {
230 if (_moduleItems.isNotEmpty) { 231 if (_moduleItems.isNotEmpty) {
231 throw new StateError('Can only call emitModule once.'); 232 throw new StateError('Can only call emitModule once.');
232 } 233 }
233 234
234 // Transform the AST to make coercions explicit. 235 // Transform the AST to make coercions explicit.
235 compilationUnits = CoercionReifier.reify(compilationUnits); 236 compilationUnits = CoercionReifier.reify(compilationUnits);
236 237
237 if (compilationUnits.any((u) => _isDartRuntime(u.element.library))) { 238 if (compilationUnits.any((u) => _isDartRuntime(elementForCompilationUnit(u). library))) {
238 // Don't allow these to be renamed when we're building the SDK. 239 // Don't allow these to be renamed when we're building the SDK.
239 // There is JS code in dart:* that depends on their names. 240 // There is JS code in dart:* that depends on their names.
240 _runtimeModule = new JS.Identifier('dart'); 241 _runtimeModule = new JS.Identifier('dart');
241 _extensionSymbolsModule = new JS.Identifier('dartx'); 242 _extensionSymbolsModule = new JS.Identifier('dartx');
242 } else { 243 } else {
243 // Otherwise allow these to be renamed so users can write them. 244 // Otherwise allow these to be renamed so users can write them.
244 _runtimeModule = new JS.TemporaryId('dart'); 245 _runtimeModule = new JS.TemporaryId('dart');
245 _extensionSymbolsModule = new JS.TemporaryId('dartx'); 246 _extensionSymbolsModule = new JS.TemporaryId('dartx');
246 } 247 }
247 _typeTable = new TypeTable(_runtimeModule); 248 _typeTable = new TypeTable(_runtimeModule);
248 249
249 // Initialize our library variables. 250 // Initialize our library variables.
250 var items = <JS.ModuleItem>[]; 251 var items = <JS.ModuleItem>[];
251 for (var unit in compilationUnits) { 252 for (var unit in compilationUnits) {
252 var library = unit.element.library; 253 var library = elementForCompilationUnit(unit).library;
253 if (unit.element != library.definingCompilationUnit) continue; 254 if (unit.element != library.definingCompilationUnit) continue;
254 255
255 var libraryTemp = _isDartRuntime(library) 256 var libraryTemp = _isDartRuntime(library)
256 ? _runtimeModule 257 ? _runtimeModule
257 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library)); 258 : new JS.TemporaryId(jsLibraryName(_libraryRoot, library));
258 _libraries[library] = libraryTemp; 259 _libraries[library] = libraryTemp;
259 items.add(new JS.ExportDeclaration( 260 items.add(new JS.ExportDeclaration(
260 js.call('const # = Object.create(null)', [libraryTemp]))); 261 js.call('const # = Object.create(null)', [libraryTemp])));
261 262
262 // dart:_runtime has a magic module that holds extension method symbols. 263 // dart:_runtime has a magic module that holds extension method symbols.
263 // TODO(jmesserly): find a cleaner design for this. 264 // TODO(jmesserly): find a cleaner design for this.
264 if (_isDartRuntime(library)) { 265 if (_isDartRuntime(library)) {
265 items.add(new JS.ExportDeclaration(js 266 items.add(new JS.ExportDeclaration(js
266 .call('const # = Object.create(null)', [_extensionSymbolsModule]))); 267 .call('const # = Object.create(null)', [_extensionSymbolsModule])));
267 } 268 }
268 } 269 }
269 270
270 // Collect all Element -> Node mappings, in case we need to forward declare 271 // Collect all Element -> Node mappings, in case we need to forward declare
271 // any nodes. 272 // any nodes.
272 var nodes = new HashMap<Element, AstNode>.identity(); 273 var nodes = new HashMap<Element, AstNode>.identity();
273 var sdkBootstrappingFns = new List<FunctionElement>(); 274 var sdkBootstrappingFns = new List<FunctionElement>();
274 for (var unit in compilationUnits) { 275 for (var unit in compilationUnits) {
275 if (_isDartRuntime(unit.element.library)) { 276 if (_isDartRuntime(elementForCompilationUnit(unit).library)) {
276 sdkBootstrappingFns.addAll(unit.element.functions); 277 sdkBootstrappingFns.addAll(elementForCompilationUnit(unit).functions);
277 } 278 }
278 _collectElements(unit, nodes); 279 _collectElements(unit, nodes);
279 } 280 }
280 _loader = new ElementLoader(nodes); 281 _loader = new ElementLoader(nodes);
281 if (compilationUnits.isNotEmpty) { 282 if (compilationUnits.isNotEmpty) {
282 _constants = new ConstFieldVisitor(context, 283 _constants = new ConstFieldVisitor(context,
283 dummySource: compilationUnits.first.element.source); 284 dummySource: elementForCompilationUnit(compilationUnits.first).source) ;
284 } 285 }
285 286
286 // Add implicit dart:core dependency so it is first. 287 // Add implicit dart:core dependency so it is first.
287 emitLibraryName(dartCoreLibrary); 288 emitLibraryName(dartCoreLibrary);
288 289
289 // Emit SDK bootstrapping functions first, if any. 290 // Emit SDK bootstrapping functions first, if any.
290 sdkBootstrappingFns.forEach(_emitDeclaration); 291 sdkBootstrappingFns.forEach(_emitDeclaration);
291 292
292 // Visit each compilation unit and emit its code. 293 // Visit each compilation unit and emit its code.
293 // 294 //
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 722
722 // We export the JS type as if it was a Dart type. For example this allows 723 // We export the JS type as if it was a Dart type. For example this allows
723 // `dom.InputElement` to actually be HTMLInputElement. 724 // `dom.InputElement` to actually be HTMLInputElement.
724 // TODO(jmesserly): if we had the JS name on the Element, we could just 725 // TODO(jmesserly): if we had the JS name on the Element, we could just
725 // generate it correctly when we refer to it. 726 // generate it correctly when we refer to it.
726 return js.statement('# = #;', [_emitTopLevelName(e), jsTypeName]); 727 return js.statement('# = #;', [_emitTopLevelName(e), jsTypeName]);
727 } 728 }
728 729
729 @override 730 @override
730 JS.Statement visitClassDeclaration(ClassDeclaration node) { 731 JS.Statement visitClassDeclaration(ClassDeclaration node) {
731 var classElem = node.element; 732 var classElem = elementForClassDeclaration(node);
732 733
733 // If this class is annotated with `@JS`, then there is nothing to emit. 734 // If this class is annotated with `@JS`, then there is nothing to emit.
734 if (findAnnotation(classElem, isPublicJSAnnotation) != null) return null; 735 if (findAnnotation(classElem, isPublicJSAnnotation) != null) return null;
735 736
736 // If this is a JavaScript type, emit it now and then exit. 737 // If this is a JavaScript type, emit it now and then exit.
737 var jsTypeDef = _emitJsType(classElem); 738 var jsTypeDef = _emitJsType(classElem);
738 if (jsTypeDef != null) return jsTypeDef; 739 if (jsTypeDef != null) return jsTypeDef;
739 740
740 var ctors = <ConstructorDeclaration>[]; 741 var ctors = <ConstructorDeclaration>[];
741 var fields = <FieldDeclaration>[]; 742 var fields = <FieldDeclaration>[];
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 /// Emits a field declaration for TypeScript & Closure's ES6_TYPED 1104 /// Emits a field declaration for TypeScript & Closure's ES6_TYPED
1104 /// (e.g. `class Foo { i: string; }`) 1105 /// (e.g. `class Foo { i: string; }`)
1105 JS.VariableDeclarationList _emitTypeScriptField(FieldDeclaration field) { 1106 JS.VariableDeclarationList _emitTypeScriptField(FieldDeclaration field) {
1106 return new JS.VariableDeclarationList( 1107 return new JS.VariableDeclarationList(
1107 field.isStatic ? 'static' : null, 1108 field.isStatic ? 'static' : null,
1108 field.fields.variables 1109 field.fields.variables
1109 .map((decl) => new JS.VariableInitialization( 1110 .map((decl) => new JS.VariableInitialization(
1110 new JS.Identifier( 1111 new JS.Identifier(
1111 // TODO(ochafik): use a refactored _emitMemberName instead. 1112 // TODO(ochafik): use a refactored _emitMemberName instead.
1112 decl.name.name, 1113 decl.name.name,
1113 type: emitTypeRef(decl.element.type)), 1114 type: emitTypeRef(elementForVariableDeclaration(decl).type)) ,
1114 null)) 1115 null))
1115 .toList(growable: false)); 1116 .toList(growable: false));
1116 } 1117 }
1117 1118
1118 @override 1119 @override
1119 JS.Statement visitEnumDeclaration(EnumDeclaration node) { 1120 JS.Statement visitEnumDeclaration(EnumDeclaration node) {
1120 var element = node.element; 1121 var element = elementForEnumDeclaration(node);
1121 var type = element.type; 1122 var type = element.type;
1122 1123
1123 // Generate a class per section 13 of the spec. 1124 // Generate a class per section 13 of the spec.
1124 // TODO(vsm): Generate any accompanying metadata 1125 // TODO(vsm): Generate any accompanying metadata
1125 1126
1126 // Create constructor and initialize index 1127 // Create constructor and initialize index
1127 var constructor = new JS.Method(_propertyName('new'), 1128 var constructor = new JS.Method(_propertyName('new'),
1128 js.call('function(index) { this.index = index; }') as JS.Fun); 1129 js.call('function(index) { this.index = index; }') as JS.Fun);
1129 var fields = new List<FieldElement>.from( 1130 var fields = new List<FieldElement>.from(
1130 element.fields.where((f) => f.type == type)); 1131 element.fields.where((f) => f.type == type));
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1281 } 1282 }
1282 return jsMethods; 1283 return jsMethods;
1283 } 1284 }
1284 1285
1285 List<JS.Method> _emitClassMethods( 1286 List<JS.Method> _emitClassMethods(
1286 ClassDeclaration node, 1287 ClassDeclaration node,
1287 List<ConstructorDeclaration> ctors, 1288 List<ConstructorDeclaration> ctors,
1288 List<FieldDeclaration> fields, 1289 List<FieldDeclaration> fields,
1289 List<ClassElement> superclasses, 1290 List<ClassElement> superclasses,
1290 Map<FieldElement, JS.TemporaryId> virtualFields) { 1291 Map<FieldElement, JS.TemporaryId> virtualFields) {
1291 var element = node.element; 1292 var element = elementForClassDeclaration(node);
1292 var type = element.type; 1293 var type = element.type;
1293 var isObject = type.isObject; 1294 var isObject = type.isObject;
1294 1295
1295 // Iff no constructor is specified for a class C, it implicitly has a 1296 // Iff no constructor is specified for a class C, it implicitly has a
1296 // default constructor `C() : super() {}`, unless C is class Object. 1297 // default constructor `C() : super() {}`, unless C is class Object.
1297 var jsMethods = <JS.Method>[]; 1298 var jsMethods = <JS.Method>[];
1298 if (isObject) { 1299 if (isObject) {
1299 // Implements Dart constructor behavior. 1300 // Implements Dart constructor behavior.
1300 // 1301 //
1301 // Because of ES6 constructor restrictions (`this` is not available until 1302 // Because of ES6 constructor restrictions (`this` is not available until
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1761 1762
1762 var tStaticMethods = <JS.Property>[]; 1763 var tStaticMethods = <JS.Property>[];
1763 var tInstanceMethods = <JS.Property>[]; 1764 var tInstanceMethods = <JS.Property>[];
1764 var tStaticGetters = <JS.Property>[]; 1765 var tStaticGetters = <JS.Property>[];
1765 var tInstanceGetters = <JS.Property>[]; 1766 var tInstanceGetters = <JS.Property>[];
1766 var tStaticSetters = <JS.Property>[]; 1767 var tStaticSetters = <JS.Property>[];
1767 var tInstanceSetters = <JS.Property>[]; 1768 var tInstanceSetters = <JS.Property>[];
1768 var sNames = <JS.Expression>[]; 1769 var sNames = <JS.Expression>[];
1769 for (MethodDeclaration node in methods) { 1770 for (MethodDeclaration node in methods) {
1770 var name = node.name.name; 1771 var name = node.name.name;
1771 var element = node.element; 1772 var element = elementForMethodDeclaration(node);
1772 // TODO(vsm): Clean up all the nasty duplication. 1773 // TODO(vsm): Clean up all the nasty duplication.
1773 if (node.isAbstract) { 1774 if (node.isAbstract) {
1774 continue; 1775 continue;
1775 } 1776 }
1776 1777
1777 Function lookup; 1778 Function lookup;
1778 List<JS.Property> tMember; 1779 List<JS.Property> tMember;
1779 JS.Expression type; 1780 JS.Expression type;
1780 if (node.isGetter) { 1781 if (node.isGetter) {
1781 lookup = classElem.lookUpInheritedConcreteGetter; 1782 lookup = classElem.lookUpInheritedConcreteGetter;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1816 var memberName = _declareMemberName(element.getter); 1817 var memberName = _declareMemberName(element.getter);
1817 var type = _emitAnnotatedType(element.type, node.metadata); 1818 var type = _emitAnnotatedType(element.type, node.metadata);
1818 var property = new JS.Property(memberName, type); 1819 var property = new JS.Property(memberName, type);
1819 (node.isStatic ? tStaticFields : tInstanceFields).add(property); 1820 (node.isStatic ? tStaticFields : tInstanceFields).add(property);
1820 } 1821 }
1821 } 1822 }
1822 1823
1823 var tCtors = <JS.Property>[]; 1824 var tCtors = <JS.Property>[];
1824 for (ConstructorDeclaration node in ctors) { 1825 for (ConstructorDeclaration node in ctors) {
1825 var memberName = _constructorName(node.element); 1826 var memberName = _constructorName(node.element);
1826 var element = node.element; 1827 var element = elementForConstructorDeclaration(node);
1827 var type = _emitAnnotatedFunctionType(element.type, node.metadata, 1828 var type = _emitAnnotatedFunctionType(element.type, node.metadata,
1828 parameters: node.parameters.parameters, 1829 parameters: node.parameters.parameters,
1829 nameType: options.hoistSignatureTypes, 1830 nameType: options.hoistSignatureTypes,
1830 hoistType: options.hoistSignatureTypes, 1831 hoistType: options.hoistSignatureTypes,
1831 definite: true); 1832 definite: true);
1832 var property = new JS.Property(memberName, type); 1833 var property = new JS.Property(memberName, type);
1833 tCtors.add(property); 1834 tCtors.add(property);
1834 } 1835 }
1835 1836
1836 JS.Property build(String name, List<JS.Property> elements) { 1837 JS.Property build(String name, List<JS.Property> elements) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 1889
1889 /// Ensure `dartx.` symbols we will use are present. 1890 /// Ensure `dartx.` symbols we will use are present.
1890 void _initExtensionSymbols( 1891 void _initExtensionSymbols(
1891 ClassElement classElem, 1892 ClassElement classElem,
1892 List<MethodDeclaration> methods, 1893 List<MethodDeclaration> methods,
1893 List<FieldDeclaration> fields, 1894 List<FieldDeclaration> fields,
1894 List<JS.Statement> body) { 1895 List<JS.Statement> body) {
1895 if (_extensionTypes.hasNativeSubtype(classElem.type)) { 1896 if (_extensionTypes.hasNativeSubtype(classElem.type)) {
1896 var dartxNames = <JS.Expression>[]; 1897 var dartxNames = <JS.Expression>[];
1897 for (var m in methods) { 1898 for (var m in methods) {
1898 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 1899 if (!m.isAbstract && !m.isStatic && elementForMethodDeclaration(m).isPub lic) {
1899 dartxNames.add(_declareMemberName(m.element, useExtension: false)); 1900 dartxNames.add(_declareMemberName(m.element, useExtension: false));
1900 } 1901 }
1901 } 1902 }
1902 for (var fieldDecl in fields) { 1903 for (var fieldDecl in fields) {
1903 if (!fieldDecl.isStatic) { 1904 if (!fieldDecl.isStatic) {
1904 for (var field in fieldDecl.fields.variables) { 1905 for (var field in fieldDecl.fields.variables) {
1905 var e = field.element as FieldElement; 1906 var e = field.element as FieldElement;
1906 if (e.isPublic) { 1907 if (e.isPublic) {
1907 dartxNames.add(_declareMemberName(e.getter, useExtension: false)); 1908 dartxNames.add(_declareMemberName(e.getter, useExtension: false));
1908 } 1909 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1950 Map<FieldElement, JS.TemporaryId> virtualFields) { 1951 Map<FieldElement, JS.TemporaryId> virtualFields) {
1951 // If we don't have a method body, skip this. 1952 // If we don't have a method body, skip this.
1952 var superCall = _superConstructorCall(node.element); 1953 var superCall = _superConstructorCall(node.element);
1953 if (fields.isEmpty && superCall == null) return null; 1954 if (fields.isEmpty && superCall == null) return null;
1954 1955
1955 var initFields = _initializeFields(node, fields, virtualFields); 1956 var initFields = _initializeFields(node, fields, virtualFields);
1956 List<JS.Statement> body = [initFields]; 1957 List<JS.Statement> body = [initFields];
1957 if (superCall != null) { 1958 if (superCall != null) {
1958 body.add(superCall); 1959 body.add(superCall);
1959 } 1960 }
1960 var name = _constructorName(node.element.unnamedConstructor); 1961 var name = _constructorName(elementForClassDeclaration(node).unnamedConstruc tor);
1961 return annotate( 1962 return annotate(
1962 new JS.Method(name, js.call('function() { #; }', [body]) as JS.Fun), 1963 new JS.Method(name, js.call('function() { #; }', [body]) as JS.Fun),
1963 node, 1964 node,
1964 node.element); 1965 node.element);
1965 } 1966 }
1966 1967
1967 JS.Method _emitConstructor( 1968 JS.Method _emitConstructor(
1968 ConstructorDeclaration node, 1969 ConstructorDeclaration node,
1969 InterfaceType type, 1970 InterfaceType type,
1970 List<FieldDeclaration> fields, 1971 List<FieldDeclaration> fields,
1971 Map<FieldElement, JS.TemporaryId> virtualFields, 1972 Map<FieldElement, JS.TemporaryId> virtualFields,
1972 bool isObject) { 1973 bool isObject) {
1973 if (_externalOrNative(node)) return null; 1974 if (_externalOrNative(node)) return null;
1974 1975
1975 var name = _constructorName(node.element); 1976 var name = _constructorName(node.element);
1976 var returnType = emitTypeRef(node.element.enclosingElement.type); 1977 var returnType = emitTypeRef(elementForConstructorDeclaration(node).enclosin gElement.type);
1977 1978
1978 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; 1979 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz;
1979 var redirect = node.redirectedConstructor; 1980 var redirect = node.redirectedConstructor;
1980 if (redirect != null) { 1981 if (redirect != null) {
1981 var newKeyword = redirect.staticElement.isFactory ? '' : 'new'; 1982 var newKeyword = staticElementForConstructorReference(redirect).isFactory ? '' : 'new';
1982 // Pass along all arguments verbatim, and let the callee handle them. 1983 // Pass along all arguments verbatim, and let the callee handle them.
1983 // TODO(jmesserly): we'll need something different once we have 1984 // TODO(jmesserly): we'll need something different once we have
1984 // rest/spread support, but this should work for now. 1985 // rest/spread support, but this should work for now.
1985 var params = 1986 var params =
1986 visitFormalParameterList(node.parameters, destructure: false); 1987 visitFormalParameterList(node.parameters, destructure: false);
1987 1988
1988 var fun = new JS.Fun( 1989 var fun = new JS.Fun(
1989 params, 1990 params,
1990 js.statement('{ return $newKeyword #(#); }', 1991 js.statement('{ return $newKeyword #(#); }',
1991 [_visit(redirect) as JS.Node, params]), 1992 [_visit(redirect) as JS.Node, params]),
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2080 var jsSuper = _superConstructorCall(cls.element, superCall); 2081 var jsSuper = _superConstructorCall(cls.element, superCall);
2081 if (jsSuper != null) body.add(jsSuper); 2082 if (jsSuper != null) body.add(jsSuper);
2082 2083
2083 body.add(_visit(node.body)); 2084 body.add(_visit(node.body));
2084 return new JS.Block(body)..sourceInformation = node; 2085 return new JS.Block(body)..sourceInformation = node;
2085 } 2086 }
2086 2087
2087 @override 2088 @override
2088 JS.Statement visitRedirectingConstructorInvocation( 2089 JS.Statement visitRedirectingConstructorInvocation(
2089 RedirectingConstructorInvocation node) { 2090 RedirectingConstructorInvocation node) {
2090 var ctor = node.staticElement; 2091 var ctor = staticElementForConstructorReference(node);
2091 var cls = ctor.enclosingElement; 2092 var cls = ctor.enclosingElement;
2092 // We can't dispatch to the constructor with `this.new` as that might hit a 2093 // We can't dispatch to the constructor with `this.new` as that might hit a
2093 // derived class constructor with the same name. 2094 // derived class constructor with the same name.
2094 return js.statement('#.prototype.#.call(this, #);', [ 2095 return js.statement('#.prototype.#.call(this, #);', [
2095 new JS.Identifier(cls.name), 2096 new JS.Identifier(cls.name),
2096 _constructorName(ctor), 2097 _constructorName(ctor),
2097 _visit(node.argumentList) 2098 _visit(node.argumentList)
2098 ]); 2099 ]);
2099 } 2100 }
2100 2101
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2257 _defaultParamValue(param), 2258 _defaultParamValue(param),
2258 ])); 2259 ]));
2259 } else if (param.kind == ParameterKind.POSITIONAL) { 2260 } else if (param.kind == ParameterKind.POSITIONAL) {
2260 body.add(js.statement('if (# === void 0) # = #;', 2261 body.add(js.statement('if (# === void 0) # = #;',
2261 [jsParam, jsParam, _defaultParamValue(param)])); 2262 [jsParam, jsParam, _defaultParamValue(param)]));
2262 } 2263 }
2263 } 2264 }
2264 2265
2265 // TODO(jmesserly): various problems here, see: 2266 // TODO(jmesserly): various problems here, see:
2266 // https://github.com/dart-lang/dev_compiler/issues/116 2267 // https://github.com/dart-lang/dev_compiler/issues/116
2267 var paramType = param.element.type; 2268 var paramType = elementForFormalParameter(param).type;
2268 if (node is MethodDeclaration && 2269 if (node is MethodDeclaration &&
2269 (param.element.isCovariant || _unsoundCovariant(paramType, true)) && 2270 (elementForFormalParameter(param).isCovariant || _unsoundCovariant(par amType, true)) &&
2270 !_inWhitelistCode(node)) { 2271 !_inWhitelistCode(node)) {
2271 var castType = _emitType(paramType, 2272 var castType = _emitType(paramType,
2272 nameType: options.nameTypeTests || options.hoistTypeTests, 2273 nameType: options.nameTypeTests || options.hoistTypeTests,
2273 hoistType: options.hoistTypeTests); 2274 hoistType: options.hoistTypeTests);
2274 body.add(js.statement('#._check(#);', [castType, jsParam])); 2275 body.add(js.statement('#._check(#);', [castType, jsParam]));
2275 } 2276 }
2276 } 2277 }
2277 return body.isEmpty ? null : _statement(body); 2278 return body.isEmpty ? null : _statement(body);
2278 } 2279 }
2279 2280
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2404 } 2405 }
2405 2406
2406 var body = <JS.Statement>[]; 2407 var body = <JS.Statement>[];
2407 var fn = _emitFunction(node.functionExpression); 2408 var fn = _emitFunction(node.functionExpression);
2408 2409
2409 if (currentLibrary.source.isInSystemLibrary && 2410 if (currentLibrary.source.isInSystemLibrary &&
2410 _isInlineJSFunction(node.functionExpression)) { 2411 _isInlineJSFunction(node.functionExpression)) {
2411 fn = _simplifyPassThroughArrowFunCallBody(fn); 2412 fn = _simplifyPassThroughArrowFunCallBody(fn);
2412 } 2413 }
2413 2414
2414 var element = node.element; 2415 var element = elementForFunctionDeclaration(node);
2415 var nameExpr = _emitTopLevelName(element); 2416 var nameExpr = _emitTopLevelName(element);
2416 body.add(annotate(js.statement('# = #', [nameExpr, fn]), node, element)); 2417 body.add(annotate(js.statement('# = #', [nameExpr, fn]), node, element));
2417 if (!_isDartRuntime(element.library)) { 2418 if (!_isDartRuntime(element.library)) {
2418 body.add(_emitFunctionTagged(nameExpr, element.type, topLevel: true) 2419 body.add(_emitFunctionTagged(nameExpr, element.type, topLevel: true)
2419 .toStatement()); 2420 .toStatement());
2420 } 2421 }
2421 2422
2422 return _statement(body); 2423 return _statement(body);
2423 } 2424 }
2424 2425
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
2672 JS.Statement declareFn; 2673 JS.Statement declareFn;
2673 if (JS.This.foundIn(fn)) { 2674 if (JS.This.foundIn(fn)) {
2674 declareFn = js.statement('const # = #.bind(this);', [name, fn]); 2675 declareFn = js.statement('const # = #.bind(this);', [name, fn]);
2675 } else { 2676 } else {
2676 declareFn = new JS.FunctionDeclaration(name, fn); 2677 declareFn = new JS.FunctionDeclaration(name, fn);
2677 } 2678 }
2678 declareFn = annotate(declareFn, node, node.functionDeclaration.element); 2679 declareFn = annotate(declareFn, node, node.functionDeclaration.element);
2679 2680
2680 return new JS.Block([ 2681 return new JS.Block([
2681 declareFn, 2682 declareFn,
2682 _emitFunctionTagged(name, func.element.type).toStatement() 2683 _emitFunctionTagged(name, elementForFunctionDeclaration(func).type).toStat ement()
2683 ]); 2684 ]);
2684 } 2685 }
2685 2686
2686 /// Emits a simple identifier, including handling an inferred generic 2687 /// Emits a simple identifier, including handling an inferred generic
2687 /// function instantiation. 2688 /// function instantiation.
2688 @override 2689 @override
2689 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { 2690 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) {
2690 var typeArgs = _getTypeArgs(node.staticElement, node.staticType); 2691 var typeArgs = _getTypeArgs(node.staticElement, node.staticType);
2691 var simpleId = _emitSimpleIdentifier(node); 2692 var simpleId = _emitSimpleIdentifier(node);
2692 if (typeArgs == null) { 2693 if (typeArgs == null) {
2693 return simpleId; 2694 return simpleId;
2694 } 2695 }
2695 return _callHelper('gbind(#, #)', [simpleId, typeArgs]); 2696 return _callHelper('gbind(#, #)', [simpleId, typeArgs]);
2696 } 2697 }
2697 2698
2698 /// Emits a simple identifier, handling implicit `this` as well as 2699 /// Emits a simple identifier, handling implicit `this` as well as
2699 /// going through the qualified library name if necessary, but *not* handling 2700 /// going through the qualified library name if necessary, but *not* handling
2700 /// inferred generic function instantiation. 2701 /// inferred generic function instantiation.
2701 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) { 2702 JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) {
2702 var accessor = node.staticElement; 2703 var accessor = staticElementForIdentifier(node);
2703 if (accessor == null) { 2704 if (accessor == null) {
2704 return js.commentExpression( 2705 return js.commentExpression(
2705 'Unimplemented unknown name', new JS.Identifier(node.name)); 2706 'Unimplemented unknown name', new JS.Identifier(node.name));
2706 } 2707 }
2707 2708
2708 // Get the original declaring element. If we had a property accessor, this 2709 // Get the original declaring element. If we had a property accessor, this
2709 // indirects back to a (possibly synthetic) field. 2710 // indirects back to a (possibly synthetic) field.
2710 var element = accessor; 2711 var element = accessor;
2711 if (accessor is PropertyAccessorElement) element = accessor.variable; 2712 if (accessor is PropertyAccessorElement) element = accessor.variable;
2712 2713
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
3223 3224
3224 /// Emits assignment to a simple identifier. Handles all legal simple 3225 /// Emits assignment to a simple identifier. Handles all legal simple
3225 /// identifier assignment targets (local, top level library member, implicit 3226 /// identifier assignment targets (local, top level library member, implicit
3226 /// `this` or class, etc.) 3227 /// `this` or class, etc.)
3227 JS.Expression _emitSetSimpleIdentifier( 3228 JS.Expression _emitSetSimpleIdentifier(
3228 SimpleIdentifier node, Expression rhs) { 3229 SimpleIdentifier node, Expression rhs) {
3229 JS.Expression unimplemented() { 3230 JS.Expression unimplemented() {
3230 return _badAssignment("Unimplemented: unknown name '$node'", node, rhs); 3231 return _badAssignment("Unimplemented: unknown name '$node'", node, rhs);
3231 } 3232 }
3232 3233
3233 var accessor = node.staticElement; 3234 var accessor = staticElementForIdentifier(node);
3234 if (accessor == null) return unimplemented(); 3235 if (accessor == null) return unimplemented();
3235 3236
3236 // Get the original declaring element. If we had a property accessor, this 3237 // Get the original declaring element. If we had a property accessor, this
3237 // indirects back to a (possibly synthetic) field. 3238 // indirects back to a (possibly synthetic) field.
3238 var element = accessor; 3239 var element = accessor;
3239 if (accessor is PropertyAccessorElement) element = accessor.variable; 3240 if (accessor is PropertyAccessorElement) element = accessor.variable;
3240 3241
3241 _declareBeforeUse(element); 3242 _declareBeforeUse(element);
3242 3243
3243 if (element is LocalVariableElement || element is ParameterElement) { 3244 if (element is LocalVariableElement || element is ParameterElement) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
3385 } 3386 }
3386 3387
3387 var result = _emitForeignJS(node); 3388 var result = _emitForeignJS(node);
3388 if (result != null) return result; 3389 if (result != null) return result;
3389 3390
3390 var target = _getTarget(node); 3391 var target = _getTarget(node);
3391 if (target == null || isLibraryPrefix(target)) { 3392 if (target == null || isLibraryPrefix(target)) {
3392 return _emitFunctionCall(node); 3393 return _emitFunctionCall(node);
3393 } 3394 }
3394 if (node.methodName.name == 'call') { 3395 if (node.methodName.name == 'call') {
3395 var targetType = target.staticType; 3396 var targetType = staticTypeForExpression(target);
3396 if (targetType is FunctionType) { 3397 if (targetType is FunctionType) {
3397 // Call methods on function types should be handled as regular function 3398 // Call methods on function types should be handled as regular function
3398 // invocations. 3399 // invocations.
3399 return _emitFunctionCall(node, node.target); 3400 return _emitFunctionCall(node, node.target);
3400 } 3401 }
3401 if (targetType.isDartCoreFunction || targetType.isDynamic) { 3402 if (targetType.isDartCoreFunction || targetType.isDynamic) {
3402 // TODO(vsm): Can a call method take generic type parameters? 3403 // TODO(vsm): Can a call method take generic type parameters?
3403 return _emitDynamicInvoke(node, _visit(target), 3404 return _emitDynamicInvoke(node, _visit(target),
3404 _visit(node.argumentList) as List<JS.Expression>); 3405 _visit(node.argumentList) as List<JS.Expression>);
3405 } 3406 }
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
3860 3861
3861 @override 3862 @override
3862 visitVariableDeclaration(VariableDeclaration node) { 3863 visitVariableDeclaration(VariableDeclaration node) {
3863 if (node.element is PropertyInducingElement) { 3864 if (node.element is PropertyInducingElement) {
3864 // Static and instance fields are handled elsewhere. 3865 // Static and instance fields are handled elsewhere.
3865 assert(node.element is TopLevelVariableElement); 3866 assert(node.element is TopLevelVariableElement);
3866 return _emitTopLevelField(node); 3867 return _emitTopLevelField(node);
3867 } 3868 }
3868 3869
3869 var name = 3870 var name =
3870 new JS.Identifier(node.name.name, type: emitTypeRef(node.element.type)); 3871 new JS.Identifier(node.name.name, type: emitTypeRef(elementForVariableDe claration(node).type));
3871 return new JS.VariableInitialization(name, _visitInitializer(node)); 3872 return new JS.VariableInitialization(name, _visitInitializer(node));
3872 } 3873 }
3873 3874
3874 /// Try to emit a constant static field. 3875 /// Try to emit a constant static field.
3875 /// 3876 ///
3876 /// If the field's initializer does not cause side effects, and if all of 3877 /// If the field's initializer does not cause side effects, and if all of
3877 /// dependencies are safe to refer to while we are initializing the class, 3878 /// dependencies are safe to refer to while we are initializing the class,
3878 /// then we can initialize it eagerly: 3879 /// then we can initialize it eagerly:
3879 /// 3880 ///
3880 /// // Baz must be const constructor, and the name "Baz" must be defined 3881 /// // Baz must be const constructor, and the name "Baz" must be defined
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
4077 var args = _visit(argumentList) as List<JS.Expression>; 4078 var args = _visit(argumentList) as List<JS.Expression>;
4078 if (args.isEmpty) { 4079 if (args.isEmpty) {
4079 return js.call('{}'); 4080 return js.call('{}');
4080 } 4081 }
4081 assert(args.single is JS.ObjectInitializer); 4082 assert(args.single is JS.ObjectInitializer);
4082 return args.single; 4083 return args.single;
4083 } 4084 }
4084 4085
4085 @override 4086 @override
4086 visitInstanceCreationExpression(InstanceCreationExpression node) { 4087 visitInstanceCreationExpression(InstanceCreationExpression node) {
4087 var element = node.staticElement; 4088 var element = staticElementForConstructorReference(node);
4088 var constructor = node.constructorName; 4089 var constructor = node.constructorName;
4089 var name = constructor.name; 4090 var name = constructor.name;
4090 var type = constructor.type.type; 4091 var type = constructor.type.type;
4091 if (node.isConst && 4092 if (node.isConst &&
4092 element?.name == 'fromEnvironment' && 4093 element?.name == 'fromEnvironment' &&
4093 element.library.isDartCore) { 4094 element.library.isDartCore) {
4094 var value = node.accept(_constants.constantVisitor); 4095 var value = node.accept(_constants.constantVisitor);
4095 4096
4096 if (value == null || value.isNull) { 4097 if (value == null || value.isNull) {
4097 return new JS.LiteralNull(); 4098 return new JS.LiteralNull();
(...skipping 1668 matching lines...) Expand 10 before | Expand all | Expand 10 after
5766 bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) { 5767 bool _isDeferredLoadLibrary(Expression target, SimpleIdentifier name) {
5767 if (name.name != "loadLibrary") return false; 5768 if (name.name != "loadLibrary") return false;
5768 5769
5769 if (target is! SimpleIdentifier) return false; 5770 if (target is! SimpleIdentifier) return false;
5770 var targetIdentifier = target as SimpleIdentifier; 5771 var targetIdentifier = target as SimpleIdentifier;
5771 5772
5772 if (targetIdentifier.staticElement is! PrefixElement) return false; 5773 if (targetIdentifier.staticElement is! PrefixElement) return false;
5773 var prefix = targetIdentifier.staticElement as PrefixElement; 5774 var prefix = targetIdentifier.staticElement as PrefixElement;
5774 5775
5775 // The library the prefix is referring to must come from a deferred import. 5776 // The library the prefix is referring to must come from a deferred import.
5776 var containingLibrary = (target.root as CompilationUnit).element.library; 5777 var containingLibrary = elementForCompilationUnit(target.root as CompilationUn it).library;
5777 var imports = containingLibrary.getImportsWithPrefix(prefix); 5778 var imports = containingLibrary.getImportsWithPrefix(prefix);
5778 return imports.length == 1 && imports[0].isDeferred; 5779 return imports.length == 1 && imports[0].isDeferred;
5779 } 5780 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698