| Index: lib/src/codegen/js_field_storage.dart
|
| diff --git a/lib/src/codegen/js_field_storage.dart b/lib/src/codegen/js_field_storage.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..eda02f0ebe7504fe7e89f94c6e19695e88a474cc
|
| --- /dev/null
|
| +++ b/lib/src/codegen/js_field_storage.dart
|
| @@ -0,0 +1,71 @@
|
| +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library dev_compiler.src.codegen.js_field_storage;
|
| +
|
| +import 'dart:collection' show HashMap, HashSet;
|
| +import 'package:analyzer/src/generated/ast.dart' show Identifier;
|
| +import 'package:analyzer/src/generated/element.dart';
|
| +
|
| +import 'package:dev_compiler/src/info.dart' show LibraryUnit;
|
| +
|
| +/// Finds fields in this library that are overridden, as well as any fields
|
| +/// from *other* libraries that were overridden by us.
|
| +HashSet<FieldElement> findFieldOverrides(LibraryUnit library) {
|
| + var propertyOverrides = new HashSet<PropertyInducingElement>();
|
| + for (var unit in library.partsThenLibrary) {
|
| + for (var cls in unit.element.types) {
|
| + var visited = new HashSet<PropertyInducingElement>();
|
| + for (var accessor in cls.accessors) {
|
| + var prop = accessor.variable;
|
| + if (visited.add(prop) && !propertyOverrides.contains(prop)) {
|
| + checkForPropertyOverride(prop, propertyOverrides);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Return only the field overrides.
|
| + return new HashSet<FieldElement>.from(
|
| + propertyOverrides.where((a) => a is FieldElement));
|
| +}
|
| +
|
| +void checkForPropertyOverride(PropertyInducingElement prop,
|
| + HashSet<PropertyInducingElement> propertyOverrides) {
|
| + var library = prop.library;
|
| + var type = (prop.enclosingElement as ClassElement).type;
|
| +
|
| + // Search for property overrides a particular "level" (mixins+superclass).
|
| + // Once we find them we don't need to keep searching superclasses, because
|
| + // Those properties will already be recorded as overridden in other libraries.
|
| + // Technically, we could make this analysis more precise: continue to search
|
| + // and explicitly mark that we don't need to emit.
|
| + bool found = false;
|
| + while (!found && !type.isObject) {
|
| + var superclass = type.superclass;
|
| + var supers = type.mixins.reversed.toList()..add(superclass);
|
| + for (var s in supers) {
|
| + var p = getProperty(s, library, prop.name);
|
| + if (p != null) {
|
| + if (!found) found = p.library != library;
|
| + propertyOverrides.add(p);
|
| + }
|
| + }
|
| +
|
| + type = superclass;
|
| + }
|
| +}
|
| +
|
| +PropertyInducingElement getProperty(
|
| + InterfaceType type, LibraryElement fromLibrary, String name) {
|
| + // Properties from a different library are not accessible.
|
| + if (Identifier.isPrivateName(name) && type.element.library != fromLibrary) {
|
| + return null;
|
| + }
|
| + for (var accessor in type.accessors) {
|
| + var prop = accessor.variable;
|
| + if (prop.name == name) return prop;
|
| + }
|
| + return null;
|
| +}
|
|
|