| 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/src/generated/ast.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/src/generated/constant.dart'; | 10 import 'package:analyzer/src/generated/constant.dart'; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 const DSEND = 'dsend'; | 56 const DSEND = 'dsend'; |
| 57 | 57 |
| 58 class JSCodegenVisitor extends GeneralizingAstVisitor | 58 class JSCodegenVisitor extends GeneralizingAstVisitor |
| 59 with ClosureAnnotator, JsTypeRefCodegen { | 59 with ClosureAnnotator, JsTypeRefCodegen { |
| 60 final AbstractCompiler compiler; | 60 final AbstractCompiler compiler; |
| 61 final CodegenOptions options; | 61 final CodegenOptions options; |
| 62 final LibraryElement currentLibrary; | 62 final LibraryElement currentLibrary; |
| 63 final StrongTypeSystemImpl rules; | 63 final StrongTypeSystemImpl rules; |
| 64 | 64 |
| 65 /// The global extension type table. | 65 /// The global extension type table. |
| 66 final HashSet<ClassElement> _extensionTypes; | 66 final ExtensionTypeSet _extensionTypes; |
| 67 | 67 |
| 68 /// Information that is precomputed for this library, indicates which fields | 68 /// Information that is precomputed for this library, indicates which fields |
| 69 /// need storage slots. | 69 /// need storage slots. |
| 70 final HashSet<FieldElement> _fieldsNeedingStorage; | 70 final HashSet<FieldElement> _fieldsNeedingStorage; |
| 71 | 71 |
| 72 /// The variable for the target of the current `..` cascade expression. | 72 /// The variable for the target of the current `..` cascade expression. |
| 73 /// | 73 /// |
| 74 /// Usually a [SimpleIdentifier], but it can also be other expressions | 74 /// Usually a [SimpleIdentifier], but it can also be other expressions |
| 75 /// that are safe to evaluate multiple times, such as `this`. | 75 /// that are safe to evaluate multiple times, such as `this`. |
| 76 Expression _cascadeTarget; | 76 Expression _cascadeTarget; |
| (...skipping 3632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3709 } else if (type is InterfaceType && type.element == expectedType.element) { | 3709 } else if (type is InterfaceType && type.element == expectedType.element) { |
| 3710 return type.typeArguments[0]; | 3710 return type.typeArguments[0]; |
| 3711 } else { | 3711 } else { |
| 3712 // TODO(leafp): The above only handles the case where the return type | 3712 // TODO(leafp): The above only handles the case where the return type |
| 3713 // is exactly Future/Stream/Iterable. Handle the subtype case. | 3713 // is exactly Future/Stream/Iterable. Handle the subtype case. |
| 3714 return DynamicTypeImpl.instance; | 3714 return DynamicTypeImpl.instance; |
| 3715 } | 3715 } |
| 3716 } | 3716 } |
| 3717 } | 3717 } |
| 3718 | 3718 |
| 3719 class _ExtensionFinder extends GeneralizingElementVisitor { | 3719 class ExtensionTypeSet extends GeneralizingElementVisitor { |
| 3720 final AnalysisContext _context; | 3720 final AnalysisContext _context; |
| 3721 final HashSet<ClassElement> _extensionTypes; | |
| 3722 final TypeProvider _types; | 3721 final TypeProvider _types; |
| 3723 | 3722 |
| 3724 _ExtensionFinder(this._context, this._extensionTypes, this._types); | 3723 final _extensionTypes = new HashSet<ClassElement>(); |
| 3724 final _pendingLibraries = new HashSet<String>(); |
| 3725 |
| 3726 ExtensionTypeSet(AbstractCompiler compiler) |
| 3727 : _context = compiler.context, |
| 3728 _types = compiler.context.typeProvider; |
| 3725 | 3729 |
| 3726 visitClassElement(ClassElement element) { | 3730 visitClassElement(ClassElement element) { |
| 3727 if (findAnnotation(element, isJsPeerInterface) != null || | 3731 if (findAnnotation(element, isJsPeerInterface) != null || |
| 3728 findAnnotation(element, isNativeAnnotation) != null) { | 3732 findAnnotation(element, isNativeAnnotation) != null) { |
| 3729 _addExtensionType(element.type); | 3733 _addExtensionType(element.type); |
| 3730 } | 3734 } |
| 3731 } | 3735 } |
| 3732 | 3736 |
| 3733 void _addExtensionType(InterfaceType t) { | 3737 void _addExtensionType(InterfaceType t) { |
| 3734 if (t.isObject || !_extensionTypes.add(t.element)) return; | 3738 if (t.isObject || !_extensionTypes.add(t.element)) return; |
| 3735 t = fillDynamicTypeArgs(t, _types) as InterfaceType; | 3739 t = fillDynamicTypeArgs(t, _types) as InterfaceType; |
| 3736 t.interfaces.forEach(_addExtensionType); | 3740 t.interfaces.forEach(_addExtensionType); |
| 3737 t.mixins.forEach(_addExtensionType); | 3741 t.mixins.forEach(_addExtensionType); |
| 3738 _addExtensionType(t.superclass); | 3742 _addExtensionType(t.superclass); |
| 3739 } | 3743 } |
| 3740 | 3744 |
| 3745 void _addExtensionTypesForLibrary(String libraryUri, List<String> typeNames) { |
| 3746 var sourceFactory = _context.sourceFactory.forUri(libraryUri); |
| 3747 var library = _context.computeLibraryElement(sourceFactory); |
| 3748 for (var typeName in typeNames) { |
| 3749 var element = library.getType(typeName); |
| 3750 _addExtensionType(element.type); |
| 3751 } |
| 3752 } |
| 3753 |
| 3741 void _addExtensionTypes(String libraryUri) { | 3754 void _addExtensionTypes(String libraryUri) { |
| 3742 var sourceFactory = _context.sourceFactory.forUri(libraryUri); | 3755 var sourceFactory = _context.sourceFactory.forUri(libraryUri); |
| 3743 var library = _context.computeLibraryElement(sourceFactory); | 3756 var library = _context.computeLibraryElement(sourceFactory); |
| 3744 visitLibraryElement(library); | 3757 visitLibraryElement(library); |
| 3745 } | 3758 } |
| 3759 |
| 3760 void _addPendingExtensionTypes(String libraryUri) { |
| 3761 _pendingLibraries.add(libraryUri); |
| 3762 } |
| 3763 |
| 3764 bool contains(Element element) { |
| 3765 if (_extensionTypes.contains(element)) return true; |
| 3766 if (_pendingLibraries.isEmpty) return false; |
| 3767 if (element is ClassElement) { |
| 3768 var uri = element.library.source.uri.toString(); |
| 3769 if (_pendingLibraries.contains(uri)) { |
| 3770 // Load all pending libraries |
| 3771 for (var libraryUri in _pendingLibraries) { |
| 3772 _addExtensionTypes(libraryUri); |
| 3773 } |
| 3774 _pendingLibraries.clear(); |
| 3775 return _extensionTypes.contains(element); |
| 3776 } |
| 3777 } |
| 3778 return false; |
| 3779 } |
| 3746 } | 3780 } |
| 3747 | 3781 |
| 3748 class JSGenerator extends CodeGenerator { | 3782 class JSGenerator extends CodeGenerator { |
| 3749 final _extensionTypes = new HashSet<ClassElement>(); | 3783 final ExtensionTypeSet _extensionTypes; |
| 3750 final TypeProvider _types; | 3784 final TypeProvider _types; |
| 3751 | 3785 |
| 3752 JSGenerator(AbstractCompiler compiler) | 3786 JSGenerator(AbstractCompiler compiler) |
| 3753 : _types = compiler.context.typeProvider, | 3787 : _types = compiler.context.typeProvider, |
| 3788 _extensionTypes = new ExtensionTypeSet(compiler), |
| 3754 super(compiler) { | 3789 super(compiler) { |
| 3755 // TODO(vsm): Eventually, we want to make this extensible - i.e., find | 3790 // TODO(vsm): Eventually, we want to make this extensible - i.e., find |
| 3756 // annotations in user code as well. It would need to be summarized in | 3791 // annotations in user code as well. It would need to be summarized in |
| 3757 // the element model - not searched this way on every compile. | 3792 // the element model - not searched this way on every compile. To make this |
| 3758 var finder = new _ExtensionFinder(context, _extensionTypes, _types); | 3793 // a little more efficient now, we do this in two phases. |
| 3759 finder._addExtensionTypes('dart:_interceptors'); | |
| 3760 finder._addExtensionTypes('dart:_native_typed_data'); | |
| 3761 finder._addExtensionTypes('dart:html'); | |
| 3762 finder._addExtensionTypes('dart:indexed_db'); | |
| 3763 finder._addExtensionTypes('dart:svg'); | |
| 3764 finder._addExtensionTypes('dart:web_audio'); | |
| 3765 finder._addExtensionTypes('dart:web_gl'); | |
| 3766 finder._addExtensionTypes('dart:web_sql'); | |
| 3767 | 3794 |
| 3795 // First, core types: |
| 3796 _extensionTypes._addExtensionTypes('dart:_interceptors'); |
| 3797 _extensionTypes._addExtensionTypes('dart:_native_typed_data'); |
| 3768 // TODO(vsm): If we're analyzing against the main SDK, those | 3798 // TODO(vsm): If we're analyzing against the main SDK, those |
| 3769 // types are not explicitly annotated. | 3799 // types are not explicitly annotated. |
| 3770 finder._addExtensionType(_types.intType); | 3800 _extensionTypes._addExtensionType(_types.intType); |
| 3771 finder._addExtensionType(_types.doubleType); | 3801 _extensionTypes._addExtensionType(_types.doubleType); |
| 3772 finder._addExtensionType(_types.boolType); | 3802 _extensionTypes._addExtensionType(_types.boolType); |
| 3773 finder._addExtensionType(_types.stringType); | 3803 _extensionTypes._addExtensionType(_types.stringType); |
| 3804 // These are used natively by dart:html but also not annotated. |
| 3805 _extensionTypes |
| 3806 ._addExtensionTypesForLibrary('dart:core', ['Comparable', 'Map']); |
| 3807 _extensionTypes |
| 3808 ._addExtensionTypesForLibrary('dart:collection', ['ListMixin']); |
| 3809 _extensionTypes._addExtensionTypesForLibrary('dart:math', ['Rectangle']); |
| 3810 |
| 3811 // Second, html types - these are only searched if we use dart:html, etc.: |
| 3812 _extensionTypes._addPendingExtensionTypes('dart:html'); |
| 3813 _extensionTypes._addPendingExtensionTypes('dart:indexed_db'); |
| 3814 _extensionTypes._addPendingExtensionTypes('dart:svg'); |
| 3815 _extensionTypes._addPendingExtensionTypes('dart:web_audio'); |
| 3816 _extensionTypes._addPendingExtensionTypes('dart:web_gl'); |
| 3817 _extensionTypes._addPendingExtensionTypes('dart:web_sql'); |
| 3774 } | 3818 } |
| 3775 | 3819 |
| 3776 String generateLibrary(LibraryUnit unit) { | 3820 String generateLibrary(LibraryUnit unit) { |
| 3777 // Clone the AST first, so we can mutate it. | 3821 // Clone the AST first, so we can mutate it. |
| 3778 unit = unit.clone(); | 3822 unit = unit.clone(); |
| 3779 var library = unit.library.element.library; | 3823 var library = unit.library.element.library; |
| 3780 var fields = findFieldsNeedingStorage(unit, _extensionTypes); | 3824 var fields = findFieldsNeedingStorage(unit, _extensionTypes); |
| 3781 var rules = new StrongTypeSystemImpl(); | 3825 var rules = new StrongTypeSystemImpl(); |
| 3782 var codegen = | 3826 var codegen = |
| 3783 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields); | 3827 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3811 | 3855 |
| 3812 /// A special kind of element created by the compiler, signifying a temporary | 3856 /// A special kind of element created by the compiler, signifying a temporary |
| 3813 /// variable. These objects use instance equality, and should be shared | 3857 /// variable. These objects use instance equality, and should be shared |
| 3814 /// everywhere in the tree where they are treated as the same variable. | 3858 /// everywhere in the tree where they are treated as the same variable. |
| 3815 class TemporaryVariableElement extends LocalVariableElementImpl { | 3859 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 3816 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3860 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 3817 | 3861 |
| 3818 int get hashCode => identityHashCode(this); | 3862 int get hashCode => identityHashCode(this); |
| 3819 bool operator ==(Object other) => identical(this, other); | 3863 bool operator ==(Object other) => identical(this, other); |
| 3820 } | 3864 } |
| OLD | NEW |