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 |