| Index: sdk/lib/_internal/compiler/implementation/resolution/class_members.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/resolution/class_members.dart b/sdk/lib/_internal/compiler/implementation/resolution/class_members.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8efc910fbf49dc253f2c3983548be9e6a0d673b8
|
| --- /dev/null
|
| +++ b/sdk/lib/_internal/compiler/implementation/resolution/class_members.dart
|
| @@ -0,0 +1,303 @@
|
| +// Copyright (c) 2012, 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 resolution.compute_members;
|
| +
|
| +import '../elements/elements.dart'
|
| + show Element,
|
| + Name,
|
| + PublicName,
|
| + Member,
|
| + MemberSignature,
|
| + LibraryElement,
|
| + ClassElement,
|
| + MixinApplicationElement;
|
| +import '../elements/modelx.dart'
|
| + show BaseClassElementX;
|
| +import '../dart_types.dart';
|
| +import '../dart2jslib.dart'
|
| + show Compiler,
|
| + MessageKind,
|
| + invariant;
|
| +import '../util/util.dart';
|
| +
|
| +part 'member_impl.dart';
|
| +
|
| +class MembersCreator {
|
| + final ClassElement cls;
|
| + final Compiler compiler;
|
| +
|
| + Map<Name, Member> classMembers = new Map<Name, Member>();
|
| + Map<Name, MemberSignature> interfaceMembers =
|
| + new Map<Name, MemberSignature>();
|
| +
|
| + MembersCreator(Compiler this.compiler, ClassElement this.cls);
|
| +
|
| + void computeMembers() {
|
| + Map<Name, Set<Member>> inheritedInterfaceMembers =
|
| + _computeSuperMembers();
|
| + Map<Name, Member> declaredMembers = _computeClassMembers();
|
| + _computeInterfaceMembers(inheritedInterfaceMembers, declaredMembers);
|
| + }
|
| +
|
| + Map<Name, Set<Member>> _computeSuperMembers() {
|
| + Map<Name, Set<Member>> inheritedInterfaceMembers =
|
| + new Map<Name, Set<Member>>();
|
| +
|
| + void inheritInterfaceMembers(InterfaceType supertype) {
|
| + supertype.element.forEachInterfaceMember((MemberSignature member) {
|
| + Set<Member> members =
|
| + inheritedInterfaceMembers.putIfAbsent(
|
| + member.name, () => new Set<Member>());
|
| + for (DeclaredMember declaredMember in member.declarations) {
|
| + members.add(declaredMember.inheritFrom(supertype));
|
| + }
|
| + });
|
| + }
|
| +
|
| + // Inherit class and interface members from superclass.
|
| + InterfaceType superclass = cls.supertype;
|
| + if (superclass != null) {
|
| + computeClassMembers(compiler, superclass.element);
|
| + superclass.element.forEachClassMember((DeclaredMember member) {
|
| + if (!member.isStatic) {
|
| + DeclaredMember inherited = member.inheritFrom(superclass);
|
| + classMembers[member.name] = inherited;
|
| + }
|
| + });
|
| + inheritInterfaceMembers(superclass);
|
| + }
|
| +
|
| + // Inherit interface members from superinterfaces.
|
| + for (Link<DartType> link = cls.interfaces;
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| + InterfaceType superinterface = link.head;
|
| + computeClassMembers(compiler, superinterface.element);
|
| + inheritInterfaceMembers(superinterface);
|
| + }
|
| +
|
| + return inheritedInterfaceMembers;
|
| + }
|
| +
|
| + Map<Name, Member> _computeClassMembers() {
|
| + Map<Name, Member> declaredMembers = new Map<Name, Member>();
|
| +
|
| + void overrideMember(DeclaredMember declared) {
|
| + classMembers[declared.name] = declared;
|
| + }
|
| +
|
| + if (cls.isMixinApplication) {
|
| + MixinApplicationElement mixinApplication = cls;
|
| + if (mixinApplication.mixin != null) {
|
| + // Only mix in class members when the mixin type is not malformed.
|
| + computeClassMembers(compiler, mixinApplication.mixin);
|
| +
|
| + mixinApplication.mixin.forEachClassMember((DeclaredMember member) {
|
| + if (!member.isStatic) {
|
| + // Abstract and static members are not mixed in.
|
| + DeclaredMember mixedInMember =
|
| + member.inheritFrom(mixinApplication.mixinType);
|
| + overrideMember(mixedInMember);
|
| + }
|
| + });
|
| + }
|
| + } else {
|
| + LibraryElement library = cls.getLibrary();
|
| + InterfaceType thisType = cls.thisType;
|
| +
|
| + cls.forEachLocalMember((Element element) {
|
| + if (element.isConstructor()) return;
|
| +
|
| + Name name = new Name(element.name, library);
|
| + if (element.isField()) {
|
| + DartType type = element.computeType(compiler);
|
| + declaredMembers[name] = new DeclaredMember(
|
| + name, element, thisType, type,
|
| + new FunctionType(compiler.functionClass, type));
|
| + if (!element.modifiers.isConst() &&
|
| + !element.modifiers.isFinal()) {
|
| + name = name.setter;
|
| + declaredMembers[name] = new DeclaredMember(
|
| + name, element, thisType, type,
|
| + new FunctionType(compiler.functionClass,
|
| + compiler.types.voidType,
|
| + const Link<DartType>().prepend(type)));
|
| + }
|
| + } else if (element.isGetter()) {
|
| + FunctionType functionType = element.computeType(compiler);
|
| + DartType type = functionType.returnType;
|
| + declaredMembers[name] =
|
| + new DeclaredMember(name, element, thisType, type, functionType);
|
| + } else if (element.isSetter()) {
|
| + FunctionType functionType = element.computeType(compiler);
|
| + DartType type;
|
| + if (!functionType.parameterTypes.isEmpty) {
|
| + type = functionType.parameterTypes.head;
|
| + } else {
|
| + type = compiler.types.dynamicType;
|
| + }
|
| + name = name.setter;
|
| + declaredMembers[name] = new DeclaredMember(
|
| + name, element, thisType, type, functionType);
|
| + } else {
|
| + assert(invariant(element, element.isFunction()));
|
| + FunctionType type = element.computeType(compiler);
|
| + declaredMembers[name] = new DeclaredMember(
|
| + name, element, thisType, type, type);
|
| + }
|
| + });
|
| + }
|
| +
|
| + declaredMembers.values.forEach((Member member) {
|
| + if (!member.element.isAbstract) {
|
| + overrideMember(member);
|
| + }
|
| + });
|
| +
|
| + return declaredMembers;
|
| + }
|
| +
|
| + void _computeInterfaceMembers(
|
| + Map<Name, Set<Member>> inheritedInterfaceMembers,
|
| + Map<Name, Member> declaredMembers) {
|
| + InterfaceType thisType = cls.thisType;
|
| + // Compute the interface members by overriding the inherited members with
|
| + // a declared member or by computing a single, possibly synthesized,
|
| + // inherited member.
|
| + inheritedInterfaceMembers.forEach(
|
| + (Name name, Set<Member> inheritedMembers) {
|
| + Member declared = declaredMembers[name];
|
| + if (declared != null) {
|
| + if (!declared.isStatic) {
|
| + interfaceMembers[name] = declared;
|
| + }
|
| + } else {
|
| + bool someAreGetters = false;
|
| + bool allAreGetters = true;
|
| + Map<DartType, Set<Member>> subtypesOfAllInherited =
|
| + new Map<DartType, Set<Member>>();
|
| + outer: for (Member inherited in inheritedMembers) {
|
| + if (inherited.isGetter) {
|
| + someAreGetters = true;
|
| + if (!allAreGetters) break outer;
|
| + } else {
|
| + allAreGetters = false;
|
| + if (someAreGetters) break outer;
|
| + }
|
| + for (MemberSignature other in inheritedMembers) {
|
| + if (!compiler.types.isSubtype(inherited.functionType,
|
| + other.functionType)) {
|
| + continue outer;
|
| + }
|
| + }
|
| + subtypesOfAllInherited.putIfAbsent(inherited.functionType,
|
| + () => new Set<Member>()).add(inherited);
|
| + }
|
| + if (someAreGetters && !allAreGetters) {
|
| + interfaceMembers[name] = new ErroneousMember(inheritedMembers);
|
| + } else if (subtypesOfAllInherited.length == 1) {
|
| + // All signatures have the same type.
|
| + Set<Member> members = subtypesOfAllInherited.values.first;
|
| + MemberSignature inherited = members.first;
|
| + if (members.length != 1) {
|
| + // Multiple signatures with the same type => return a
|
| + // synthesized signature.
|
| + inherited = new SyntheticMember(
|
| + members, inherited.type, inherited.functionType);
|
| + }
|
| + interfaceMembers[name] = inherited;
|
| + } else {
|
| + _inheritedSynthesizedMember(name, inheritedMembers);
|
| + }
|
| + }
|
| + });
|
| +
|
| + // Add the non-overriding instance methods to the interface members.
|
| + declaredMembers.forEach((Name name, Member member) {
|
| + if (!member.isStatic) {
|
| + interfaceMembers.putIfAbsent(name, () => member);
|
| + }
|
| + });
|
| + }
|
| +
|
| + /// Create and inherit a synthesized member for [inheritedMembers].
|
| + void _inheritedSynthesizedMember(Name name,
|
| + Set<Member> inheritedMembers) {
|
| + // Multiple signatures with different types => create the synthesized
|
| + // version.
|
| + int minRequiredParameters;
|
| + int maxPositionalParameters;
|
| + Set<String> names = new Set<String>();
|
| + for (MemberSignature member in inheritedMembers) {
|
| + int requiredParameters = 0;
|
| + int optionalParameters = 0;
|
| + if (member.isSetter) {
|
| + requiredParameters = 1;
|
| + }
|
| + if (member.type.kind == TypeKind.FUNCTION) {
|
| + FunctionType type = member.type;
|
| + type.namedParameters.forEach(
|
| + (String name) => names.add(name));
|
| + requiredParameters = type.parameterTypes.slowLength();
|
| + optionalParameters = type.optionalParameterTypes.slowLength();
|
| + }
|
| + int positionalParameters = requiredParameters + optionalParameters;
|
| + if (minRequiredParameters == null ||
|
| + minRequiredParameters > requiredParameters) {
|
| + minRequiredParameters = requiredParameters;
|
| + }
|
| + if (maxPositionalParameters == null ||
|
| + maxPositionalParameters < positionalParameters) {
|
| + maxPositionalParameters = positionalParameters;
|
| + }
|
| + }
|
| + int optionalParameters =
|
| + maxPositionalParameters - minRequiredParameters;
|
| + // TODO(johnniwinther): Support function types with both optional
|
| + // and named parameters?
|
| + if (optionalParameters == 0 || names.isEmpty) {
|
| + Link<DartType> requiredParameterTypes = const Link<DartType>();
|
| + while (--minRequiredParameters >= 0) {
|
| + requiredParameterTypes =
|
| + requiredParameterTypes.prepend(compiler.types.dynamicType);
|
| + }
|
| + Link<DartType> optionalParameterTypes = const Link<DartType>();
|
| + while (--optionalParameters >= 0) {
|
| + optionalParameterTypes =
|
| + optionalParameterTypes.prepend(compiler.types.dynamicType);
|
| + }
|
| + Link<String> namedParameters = const Link<String>();
|
| + Link<DartType> namedParameterTypes = const Link<DartType>();
|
| + List<String> namesReversed =
|
| + names.toList()..sort((a, b) => -a.compareTo(b));
|
| + for (String name in namesReversed) {
|
| + namedParameters = namedParameters.prepend(name);
|
| + namedParameterTypes =
|
| + namedParameterTypes.prepend(compiler.types.dynamicType);
|
| + }
|
| + FunctionType memberType = new FunctionType(
|
| + compiler.functionClass,
|
| + compiler.types.dynamicType,
|
| + requiredParameterTypes,
|
| + optionalParameterTypes,
|
| + namedParameters, namedParameterTypes);
|
| + DartType type = memberType;
|
| + if (inheritedMembers.first.isGetter ||
|
| + inheritedMembers.first.isSetter) {
|
| + type = compiler.types.dynamicType;
|
| + }
|
| + interfaceMembers[name] = new SyntheticMember(
|
| + inheritedMembers, type, memberType);
|
| + }
|
| + }
|
| +
|
| + static void computeClassMembers(Compiler compiler, BaseClassElementX cls) {
|
| + if (cls.classMembers != null) return;
|
| + MembersCreator creator = new MembersCreator(compiler, cls);
|
| + creator.computeMembers();
|
| + cls.classMembers = creator.classMembers;
|
| + cls.interfaceMembers = creator.interfaceMembers;
|
| + }
|
| +}
|
|
|