| 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 HashSet, HashMap, SplayTreeSet; | 5 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
| 6 | 6 |
| 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| 8 import 'package:analyzer/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.dart'; |
| 9 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
| 10 import 'package:analyzer/dart/element/visitor.dart'; | 10 import 'package:analyzer/dart/element/visitor.dart'; |
| 11 import 'package:analyzer/dart/element/type.dart'; | 11 import 'package:analyzer/dart/element/type.dart'; |
| 12 import 'package:analyzer/dart/ast/ast.dart' hide ConstantEvaluator; | 12 import 'package:analyzer/dart/ast/ast.dart' hide ConstantEvaluator; |
| 13 import 'package:analyzer/src/generated/constant.dart'; | 13 import 'package:analyzer/src/generated/constant.dart'; |
| 14 //TODO(leafp): Remove deprecated dependency | 14 //TODO(leafp): Remove deprecated dependency |
| 15 //ignore: DEPRECATED_MEMBER_USE | 15 //ignore: DEPRECATED_MEMBER_USE |
| 16 import 'package:analyzer/src/generated/element.dart' | 16 import 'package:analyzer/src/generated/element.dart' |
| 17 show DynamicElementImpl, DynamicTypeImpl, LocalVariableElementImpl; | 17 show DynamicElementImpl, DynamicTypeImpl, LocalVariableElementImpl; |
| 18 // TODO(jmesserly): we can remove this when ResolutionCopier is fixed. |
| 19 import 'package:analyzer/src/dart/ast/ast.dart' show FunctionBodyImpl; |
| 18 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; | 20 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
| 21 import 'package:analyzer/src/generated/parser.dart' show ResolutionCopier; |
| 19 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 22 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
| 20 import 'package:analyzer/src/dart/ast/token.dart' | 23 import 'package:analyzer/src/dart/ast/token.dart' |
| 21 show StringToken, Token, TokenType; | 24 show StringToken, Token, TokenType; |
| 22 import 'package:analyzer/src/generated/type_system.dart' | 25 import 'package:analyzer/src/generated/type_system.dart' |
| 23 show StrongTypeSystemImpl; | 26 show StrongTypeSystemImpl; |
| 27 import 'package:analyzer/src/task/strong/info.dart'; |
| 24 | 28 |
| 25 import 'ast_builder.dart' show AstBuilder; | 29 import 'ast_builder.dart' show AstBuilder; |
| 26 import 'reify_coercions.dart' show CoercionReifier, Tuple2; | 30 import 'reify_coercions.dart' show CoercionReifier, Tuple2; |
| 27 | 31 |
| 28 import '../js/js_ast.dart' as JS; | 32 import '../js/js_ast.dart' as JS; |
| 29 import '../js/js_ast.dart' show js; | 33 import '../js/js_ast.dart' show js; |
| 30 | 34 |
| 31 import '../closure/closure_annotator.dart' show ClosureAnnotator; | 35 import '../closure/closure_annotator.dart' show ClosureAnnotator; |
| 32 import '../compiler.dart' | 36 import '../compiler.dart' |
| 33 show AbstractCompiler, corelibOrder, getCorelibModuleName; | 37 show AbstractCompiler, corelibOrder, getCorelibModuleName; |
| 34 import '../info.dart'; | |
| 35 import '../options.dart' show CodegenOptions; | 38 import '../options.dart' show CodegenOptions; |
| 36 import '../utils.dart'; | 39 import '../utils.dart'; |
| 37 | 40 |
| 38 import 'code_generator.dart'; | |
| 39 import 'js_field_storage.dart'; | 41 import 'js_field_storage.dart'; |
| 40 import 'js_interop.dart'; | 42 import 'js_interop.dart'; |
| 41 import 'js_names.dart' as JS; | 43 import 'js_names.dart' as JS; |
| 42 import 'js_metalet.dart' as JS; | 44 import 'js_metalet.dart' as JS; |
| 43 import 'js_module_item_order.dart'; | 45 import 'js_module_item_order.dart'; |
| 44 import 'js_names.dart'; | 46 import 'js_names.dart'; |
| 45 import 'js_printer.dart' show writeJsLibrary; | 47 import 'js_printer.dart' show writeJsLibrary; |
| 46 import 'js_typeref_codegen.dart'; | 48 import 'js_typeref_codegen.dart'; |
| 47 import 'module_builder.dart'; | 49 import 'module_builder.dart'; |
| 48 import 'nullable_type_inference.dart'; | 50 import 'nullable_type_inference.dart'; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 | 130 |
| 129 var context = compiler.context; | 131 var context = compiler.context; |
| 130 var src = context.sourceFactory.forUri('dart:_interceptors'); | 132 var src = context.sourceFactory.forUri('dart:_interceptors'); |
| 131 var interceptors = context.computeLibraryElement(src); | 133 var interceptors = context.computeLibraryElement(src); |
| 132 _jsArray = interceptors.getType('JSArray'); | 134 _jsArray = interceptors.getType('JSArray'); |
| 133 _isDartRuntime = currentLibrary.source.uri.toString() == 'dart:_runtime'; | 135 _isDartRuntime = currentLibrary.source.uri.toString() == 'dart:_runtime'; |
| 134 } | 136 } |
| 135 | 137 |
| 136 TypeProvider get types => _types; | 138 TypeProvider get types => _types; |
| 137 | 139 |
| 138 JS.Program emitLibrary(LibraryUnit library) { | 140 JS.Program emitLibrary(List<CompilationUnit> units) { |
| 141 // Copy the AST before modifying it. |
| 142 units = units.map(_cloneCompilationUnit).toList(); |
| 143 |
| 139 // Modify the AST to make coercions explicit. | 144 // Modify the AST to make coercions explicit. |
| 140 new CoercionReifier(library, rules).reify(); | 145 new CoercionReifier(rules).reify(units); |
| 141 | 146 |
| 142 library.library.directives.forEach(_visit); | 147 units.last.directives.forEach(_visit); |
| 143 | |
| 144 var units = library.partsThenLibrary; | |
| 145 | 148 |
| 146 // Rather than directly visit declarations, we instead use [_loader] to | 149 // Rather than directly visit declarations, we instead use [_loader] to |
| 147 // visit them. It has the ability to sort elements on demand, so | 150 // visit them. It has the ability to sort elements on demand, so |
| 148 // dependencies between top level items are handled with a minimal | 151 // dependencies between top level items are handled with a minimal |
| 149 // reordering of the user's input code. The loader will call back into | 152 // reordering of the user's input code. The loader will call back into |
| 150 // this visitor via [_emitModuleItem] when it's ready to visit the item | 153 // this visitor via [_emitModuleItem] when it's ready to visit the item |
| 151 // for real. | 154 // for real. |
| 152 _loader.collectElements(currentLibrary, units); | 155 _loader.collectElements(currentLibrary, units); |
| 153 | 156 |
| 154 // TODO(jmesserly): ideally we could do this at a smaller granularity. | 157 // TODO(jmesserly): ideally we could do this at a smaller granularity. |
| 155 // We'll need to be consistent about when we're generating functions, and | 158 // We'll need to be consistent about when we're generating functions, and |
| 156 // only run this on the outermost function. | 159 // only run this on the outermost function. |
| 157 inferNullableTypesInLibrary(units); | 160 inferNullableTypesInLibrary(units); |
| 158 | 161 |
| 159 _constField = new ConstFieldVisitor(types, library.library.element.source); | 162 _constField = new ConstFieldVisitor(types, currentLibrary.source); |
| 160 | 163 |
| 161 for (var unit in units) { | 164 for (var unit in units) { |
| 162 for (var decl in unit.declarations) { | 165 for (var decl in unit.declarations) { |
| 163 if (decl is TopLevelVariableDeclaration) { | 166 if (decl is TopLevelVariableDeclaration) { |
| 164 visitTopLevelVariableDeclaration(decl); | 167 visitTopLevelVariableDeclaration(decl); |
| 165 } else { | 168 } else { |
| 166 _loader.loadDeclaration(decl, decl.element); | 169 _loader.loadDeclaration(decl, decl.element); |
| 167 } | 170 } |
| 168 } | 171 } |
| 169 } | 172 } |
| (...skipping 3583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3753 _addExtensionTypes(libraryUri); | 3756 _addExtensionTypes(libraryUri); |
| 3754 } | 3757 } |
| 3755 _pendingLibraries.clear(); | 3758 _pendingLibraries.clear(); |
| 3756 return _extensionTypes.contains(element); | 3759 return _extensionTypes.contains(element); |
| 3757 } | 3760 } |
| 3758 } | 3761 } |
| 3759 return false; | 3762 return false; |
| 3760 } | 3763 } |
| 3761 } | 3764 } |
| 3762 | 3765 |
| 3763 class JSGenerator extends CodeGenerator { | 3766 class JSGenerator { |
| 3767 final AbstractCompiler compiler; |
| 3764 final ExtensionTypeSet _extensionTypes; | 3768 final ExtensionTypeSet _extensionTypes; |
| 3765 final TypeProvider _types; | 3769 final TypeProvider _types; |
| 3766 | 3770 |
| 3767 JSGenerator(AbstractCompiler compiler) | 3771 JSGenerator(AbstractCompiler compiler) |
| 3768 : _types = compiler.context.typeProvider, | 3772 : compiler = compiler, |
| 3769 _extensionTypes = new ExtensionTypeSet(compiler), | 3773 _types = compiler.context.typeProvider, |
| 3770 super(compiler) { | 3774 _extensionTypes = new ExtensionTypeSet(compiler) { |
| 3771 // TODO(vsm): Eventually, we want to make this extensible - i.e., find | 3775 // TODO(vsm): Eventually, we want to make this extensible - i.e., find |
| 3772 // annotations in user code as well. It would need to be summarized in | 3776 // annotations in user code as well. It would need to be summarized in |
| 3773 // the element model - not searched this way on every compile. To make this | 3777 // the element model - not searched this way on every compile. To make this |
| 3774 // a little more efficient now, we do this in two phases. | 3778 // a little more efficient now, we do this in two phases. |
| 3775 | 3779 |
| 3776 // First, core types: | 3780 // First, core types: |
| 3777 _extensionTypes._addExtensionTypes('dart:_interceptors'); | 3781 _extensionTypes._addExtensionTypes('dart:_interceptors'); |
| 3778 _extensionTypes._addExtensionTypes('dart:_native_typed_data'); | 3782 _extensionTypes._addExtensionTypes('dart:_native_typed_data'); |
| 3779 // TODO(vsm): If we're analyzing against the main SDK, those | 3783 // TODO(vsm): If we're analyzing against the main SDK, those |
| 3780 // types are not explicitly annotated. | 3784 // types are not explicitly annotated. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3791 | 3795 |
| 3792 // Second, html types - these are only searched if we use dart:html, etc.: | 3796 // Second, html types - these are only searched if we use dart:html, etc.: |
| 3793 _extensionTypes._addPendingExtensionTypes('dart:html'); | 3797 _extensionTypes._addPendingExtensionTypes('dart:html'); |
| 3794 _extensionTypes._addPendingExtensionTypes('dart:indexed_db'); | 3798 _extensionTypes._addPendingExtensionTypes('dart:indexed_db'); |
| 3795 _extensionTypes._addPendingExtensionTypes('dart:svg'); | 3799 _extensionTypes._addPendingExtensionTypes('dart:svg'); |
| 3796 _extensionTypes._addPendingExtensionTypes('dart:web_audio'); | 3800 _extensionTypes._addPendingExtensionTypes('dart:web_audio'); |
| 3797 _extensionTypes._addPendingExtensionTypes('dart:web_gl'); | 3801 _extensionTypes._addPendingExtensionTypes('dart:web_gl'); |
| 3798 _extensionTypes._addPendingExtensionTypes('dart:web_sql'); | 3802 _extensionTypes._addPendingExtensionTypes('dart:web_sql'); |
| 3799 } | 3803 } |
| 3800 | 3804 |
| 3801 String generateLibrary(LibraryUnit unit) { | 3805 void generateLibrary(List<CompilationUnit> units) { |
| 3802 // Clone the AST first, so we can mutate it. | 3806 var library = units.first.element.library; |
| 3803 unit = unit.clone(); | 3807 var fields = |
| 3804 var library = unit.library.element.library; | 3808 findFieldsNeedingStorage(units.map((c) => c.element), _extensionTypes); |
| 3805 var fields = findFieldsNeedingStorage(unit, _extensionTypes); | |
| 3806 var rules = new StrongTypeSystemImpl(); | 3809 var rules = new StrongTypeSystemImpl(); |
| 3807 var codegen = | 3810 var codegen = |
| 3808 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields); | 3811 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields); |
| 3809 var module = codegen.emitLibrary(unit); | 3812 var module = codegen.emitLibrary(units); |
| 3810 var out = compiler.getOutputPath(library.source.uri); | 3813 var out = compiler.getOutputPath(library.source.uri); |
| 3811 var flags = compiler.options; | 3814 var options = compiler.options.codegenOptions; |
| 3812 var serverUri = flags.serverMode | 3815 writeJsLibrary(module, out, compiler.inputBaseDir, |
| 3813 ? Uri.parse('http://${flags.host}:${flags.port}/') | |
| 3814 : null; | |
| 3815 return writeJsLibrary(module, out, compiler.inputBaseDir, serverUri, | |
| 3816 emitTypes: options.closure, | 3816 emitTypes: options.closure, |
| 3817 emitSourceMaps: options.emitSourceMaps, | 3817 emitSourceMaps: options.emitSourceMaps, |
| 3818 fileSystem: compiler.fileSystem); | 3818 fileSystem: compiler.fileSystem); |
| 3819 } | 3819 } |
| 3820 } | 3820 } |
| 3821 | 3821 |
| 3822 /// Choose a canonical name from the library element. | 3822 /// Choose a canonical name from the library element. |
| 3823 /// This never uses the library's name (the identifier in the `library` | 3823 /// This never uses the library's name (the identifier in the `library` |
| 3824 /// declaration) as it doesn't have any meaningful rules enforced. | 3824 /// declaration) as it doesn't have any meaningful rules enforced. |
| 3825 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); | 3825 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3837 | 3837 |
| 3838 /// A special kind of element created by the compiler, signifying a temporary | 3838 /// A special kind of element created by the compiler, signifying a temporary |
| 3839 /// variable. These objects use instance equality, and should be shared | 3839 /// variable. These objects use instance equality, and should be shared |
| 3840 /// everywhere in the tree where they are treated as the same variable. | 3840 /// everywhere in the tree where they are treated as the same variable. |
| 3841 class TemporaryVariableElement extends LocalVariableElementImpl { | 3841 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3842 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3842 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3843 | 3843 |
| 3844 int get hashCode => identityHashCode(this); | 3844 int get hashCode => identityHashCode(this); |
| 3845 bool operator ==(Object other) => identical(this, other); | 3845 bool operator ==(Object other) => identical(this, other); |
| 3846 } | 3846 } |
| 3847 |
| 3848 CompilationUnit _cloneCompilationUnit(CompilationUnit unit) { |
| 3849 var result = new _TreeCloner().visitCompilationUnit(unit); |
| 3850 ResolutionCopier.copyResolutionData(unit, result); |
| 3851 return result; |
| 3852 } |
| 3853 |
| 3854 class _TreeCloner extends AstCloner { |
| 3855 void _cloneProperties(AstNode clone, AstNode node) { |
| 3856 if (clone != null) { |
| 3857 CoercionInfo.set(clone, CoercionInfo.get(node)); |
| 3858 DynamicInvoke.set(clone, DynamicInvoke.get(node)); |
| 3859 } |
| 3860 } |
| 3861 |
| 3862 @override |
| 3863 AstNode cloneNode(AstNode node) { |
| 3864 var clone = super.cloneNode(node); |
| 3865 _cloneProperties(clone, node); |
| 3866 return clone; |
| 3867 } |
| 3868 |
| 3869 @override |
| 3870 List cloneNodeList(List list) { |
| 3871 var clone = super.cloneNodeList(list); |
| 3872 for (int i = 0, len = list.length; i < len; i++) { |
| 3873 _cloneProperties(clone[i], list[i]); |
| 3874 } |
| 3875 return clone; |
| 3876 } |
| 3877 |
| 3878 // TODO(jmesserly): ResolutionCopier is not copying this yet. |
| 3879 @override |
| 3880 BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) { |
| 3881 var clone = super.visitBlockFunctionBody(node); |
| 3882 (clone as FunctionBodyImpl).localVariableInfo = |
| 3883 (node as FunctionBodyImpl).localVariableInfo; |
| 3884 return clone; |
| 3885 } |
| 3886 |
| 3887 @override |
| 3888 ExpressionFunctionBody visitExpressionFunctionBody( |
| 3889 ExpressionFunctionBody node) { |
| 3890 var clone = super.visitExpressionFunctionBody(node); |
| 3891 (clone as FunctionBodyImpl).localVariableInfo = |
| 3892 (node as FunctionBodyImpl).localVariableInfo; |
| 3893 return clone; |
| 3894 } |
| 3895 } |
| OLD | NEW |