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

Unified Diff: lib/src/compiler/code_generator.dart

Issue 1899373002: Emit forwarding getter/setter when overriding just a getter or setter. (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 8 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | lib/src/compiler/js_field_storage.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/compiler/code_generator.dart
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart
index 199a629e74a9a4fbdc601c56b03680ae25dd8ca9..a45ce215ce5ed0313a5f76def2feb2a1f76eeba1 100644
--- a/lib/src/compiler/code_generator.dart
+++ b/lib/src/compiler/code_generator.dart
@@ -5,11 +5,11 @@
import 'dart:collection' show HashMap, HashSet;
import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
+import 'package:analyzer/dart/ast/ast.dart' hide ConstantEvaluator;
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/ast/ast.dart' hide ConstantEvaluator;
-
+import 'package:analyzer/src/dart/ast/token.dart' show StringToken;
//TODO(leafp): Remove deprecated dependency
//ignore: DEPRECATED_MEMBER_USE
import 'package:analyzer/src/generated/element.dart'
@@ -17,27 +17,26 @@ import 'package:analyzer/src/generated/element.dart'
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart'
show TypeProvider, NamespaceBuilder;
-import 'package:analyzer/src/dart/ast/token.dart' show StringToken;
import 'package:analyzer/src/generated/type_system.dart'
show StrongTypeSystemImpl;
import 'package:analyzer/src/summary/summarize_elements.dart'
show PackageBundleAssembler;
import 'package:analyzer/src/task/strong/info.dart' show DynamicInvoke;
+import 'package:source_maps/source_maps.dart';
+import '../closure/closure_annotator.dart' show ClosureAnnotator;
import '../js_ast/js_ast.dart' as JS;
import '../js_ast/js_ast.dart' show js;
-import '../closure/closure_annotator.dart' show ClosureAnnotator;
-
import 'ast_builder.dart' show AstBuilder;
import 'compiler.dart'
show BuildUnit, CompilerOptions, JSModuleFile, ModuleFormat;
import 'element_helpers.dart';
import 'element_loader.dart' show ElementLoader;
import 'extension_types.dart' show ExtensionTypeSet;
-import 'js_field_storage.dart' show findFieldsNeedingStorage;
+import 'js_field_storage.dart' show checkForPropertyOverride, getSuperclasses;
import 'js_interop.dart';
-import 'js_names.dart' as JS;
import 'js_metalet.dart' as JS;
+import 'js_names.dart' as JS;
import 'js_typeref_codegen.dart' show JsTypeRefCodegen;
import 'module_builder.dart'
show LegacyModuleBuilder, NodeModuleBuilder, pathToJSIdentifier;
@@ -45,7 +44,6 @@ import 'nullable_type_inference.dart' show NullableTypeInference;
import 'reify_coercions.dart' show CoercionReifier;
import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless;
import 'source_map_printer.dart' show SourceMapPrintingContext;
-import 'package:source_maps/source_maps.dart';
class CodeGenerator extends GeneralizingAstVisitor
with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference {
@@ -69,10 +67,6 @@ class CodeGenerator extends GeneralizingAstVisitor
/// The global extension type table.
final ExtensionTypeSet _extensionTypes;
- /// Information that is precomputed for this library, indicates which fields
- /// need storage slots.
- HashSet<FieldElement> _fieldsNeedingStorage;
-
/// The variable for the target of the current `..` cascade expression.
///
/// Usually a [SimpleIdentifier], but it can also be other expressions
@@ -184,9 +178,6 @@ class CodeGenerator extends GeneralizingAstVisitor
throw new StateError('Can only call emitModule once.');
}
- _fieldsNeedingStorage = findFieldsNeedingStorage(
- compilationUnits.map((u) => u.element), _extensionTypes);
-
// Transform the AST to make coercions explicit.
compilationUnits = CoercionReifier.reify(compilationUnits);
@@ -554,7 +545,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// Emit things that come after the ES6 `class ... { ... }`.
_setBaseClass(classElem, className, body);
_defineNamedConstructors(ctors, body, className);
- _emitVirtualFields(fields, className, body);
+ _emitVirtualFields(classElem, fields, className, body);
_emitClassSignature(methods, classElem, ctors, extensions, className, body);
_defineExtensionMembers(extensions, className, body);
_emitClassMetadata(node.metadata, className, body);
@@ -774,6 +765,7 @@ class CodeGenerator extends GeneralizingAstVisitor
}
bool hasJsPeer = findAnnotation(element, isJsPeerInterface) != null;
+ var superclasses = getSuperclasses(element);
bool hasIterator = false;
for (var m in node.members) {
@@ -782,6 +774,10 @@ class CodeGenerator extends GeneralizingAstVisitor
} else if (m is MethodDeclaration) {
jsMethods.add(_emitMethodDeclaration(type, m));
+ if (m.element is PropertyAccessorElement) {
+ jsMethods.add(_emitSuperAccessorWrapper(m, type, superclasses));
+ }
+
if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') {
hasIterator = true;
jsMethods.add(_emitIterable(type));
@@ -806,6 +802,32 @@ class CodeGenerator extends GeneralizingAstVisitor
return jsMethods.where((m) => m != null).toList(growable: false);
}
+ JS.Method _emitSuperAccessorWrapper(MethodDeclaration method,
+ InterfaceType type, List<ClassElement> superclasses) {
+ var methodElement = method.element as PropertyAccessorElement;
+ var field = methodElement.variable;
+ if (!field.isSynthetic) return null;
+ var propertyOverrideResult = checkForPropertyOverride(
+ methodElement.variable, superclasses, _extensionTypes);
+
+ // Generate a corresponding virtual getter / setter.
+ var name = _elementMemberName(methodElement,
+ allowExtensions: _extensionTypes.contains(type.element));
+ if (method.isGetter) {
+ // Generate a setter
+ if (field.setter != null || !propertyOverrideResult.foundSetter)
+ return null;
+ var fn = js.call('function(value) { super[#] = value; }', [name]);
+ return new JS.Method(name, fn, isSetter: true);
+ } else {
+ // Generate a getter
+ if (field.getter != null || !propertyOverrideResult.foundGetter)
+ return null;
+ var fn = js.call('function() { return super[#]; }', [name]);
+ return new JS.Method(name, fn, isGetter: true);
+ }
+ }
+
bool _implementsIterable(InterfaceType t) =>
t.interfaces.any((i) => i.element.type == types.iterableType);
@@ -890,11 +912,18 @@ class CodeGenerator extends GeneralizingAstVisitor
/// Emits instance fields, if they are virtual
/// (in other words, they override a getter/setter pair).
- void _emitVirtualFields(List<FieldDeclaration> fields,
- JS.Expression className, List<JS.Statement> body) {
+ void _emitVirtualFields(
+ ClassElement classElement,
+ List<FieldDeclaration> fields,
+ JS.Expression className,
+ List<JS.Statement> body) {
+ List<ClassElement> superclasses = getSuperclasses(classElement);
for (FieldDeclaration member in fields) {
for (VariableDeclaration field in member.fields.variables) {
- if (_fieldsNeedingStorage.contains(field.element)) {
+ var propertyOverrideResult = checkForPropertyOverride(
+ field.element, superclasses, _extensionTypes);
+ if (propertyOverrideResult.foundGetter ||
+ propertyOverrideResult.foundSetter) {
body.add(_overrideField(className, field.element));
}
}
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | lib/src/compiler/js_field_storage.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698