| Index: tests/compiler/dart2js/members_test.dart
|
| diff --git a/tests/compiler/dart2js/members_test.dart b/tests/compiler/dart2js/members_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..155c5313eadc06ad051f78be6f905589633914a3
|
| --- /dev/null
|
| +++ b/tests/compiler/dart2js/members_test.dart
|
| @@ -0,0 +1,681 @@
|
| +// Copyright (c) 2014, 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 members_test;
|
| +
|
| +import 'package:expect/expect.dart';
|
| +import "package:async_helper/async_helper.dart";
|
| +import 'type_test_helper.dart';
|
| +import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
|
| +import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart"
|
| + show Element, ClassElement, MemberSignature, Name, PublicName;
|
| +import "../../../sdk/lib/_internal/compiler/implementation/resolution/class_members.dart"
|
| + show SyntheticMember, ErroneousMember;
|
| +
|
| +void main() {
|
| + testClassMembers();
|
| + testInterfaceMembers();
|
| + testClassVsInterfaceMembers();
|
| + testMixinMembers();
|
| +}
|
| +
|
| +MemberSignature getMember(InterfaceType cls, String name,
|
| + {bool isSetter: false,
|
| + int checkType: CHECK_INTERFACE}) {
|
| + Name memberName =
|
| + new Name(name, cls.element.getLibrary(), isSetter: isSetter);
|
| + MemberSignature member = checkType == CHECK_CLASS
|
| + ? cls.element.lookupClassMember(memberName)
|
| + : cls.element.lookupInterfaceMember(memberName);
|
| + if (member != null) {
|
| + Expect.equals(memberName, member.name);
|
| + }
|
| + return member;
|
| +}
|
| +
|
| +/// Check interface member only.
|
| +const int CHECK_INTERFACE = 0;
|
| +/// Check class member only.
|
| +const int CHECK_CLASS = 1;
|
| +/// Check that there is no class member for the interface member.
|
| +const int NO_CLASS_MEMBER = 2;
|
| +/// Check that the interface member is also a class member.
|
| +const int ALSO_CLASS_MEMBER = 3;
|
| +
|
| +/**
|
| + * Checks [member] or interface member [name] of the declaration of [cls].
|
| + *
|
| + * If [inheritFrom] is set, the member from [cls] must be identical to the
|
| + * member from [inheritedFrom].
|
| + *
|
| + * Otherwise, the properties of member are checked against the values of
|
| + * [isStatic], [isSetter], [isGetter], [declarer], [type] and
|
| + * [functionType].
|
| + *
|
| + * If [synthesizedFrom] or [erroneousFrom] is not `null`, the member is checked
|
| + * to be synthesized for the corresponding members found on the type is
|
| + * [synthesizedFrom] or or [erroneousFrom], respectively.
|
| + * Otherwise, if [declarer] is `null`, the declarer is checked to be [cls], and
|
| + * if [declarer] is not `null`, the declarer is checked to be [declarer].
|
| + * If [type] is `null` it is checked that the type of the member is also the
|
| + * member type, otherwise the type is checked to be [type].
|
| + *
|
| + * If [isClassMember] is `true` it is checked that the member is also a class
|
| + * member.
|
| + */
|
| +MemberSignature checkMember(InterfaceType cls,
|
| + String name,
|
| + {bool isStatic: false,
|
| + bool isSetter: false,
|
| + bool isGetter: false,
|
| + InterfaceType declarer,
|
| + DartType type,
|
| + FunctionType functionType,
|
| + InterfaceType inheritedFrom,
|
| + List<InterfaceType> synthesizedFrom,
|
| + List<InterfaceType> erroneousFrom,
|
| + int checkType: ALSO_CLASS_MEMBER}) {
|
| + String memberKind = checkType == CHECK_CLASS ? 'class' : 'interface';
|
| + MemberSignature member =
|
| + getMember(cls, name, isSetter: isSetter, checkType: checkType);
|
| + Expect.isNotNull(member, "No $memberKind member '$name' in $cls.");
|
| + Name memberName = member.name;
|
| + if (checkType == ALSO_CLASS_MEMBER) {
|
| + MemberSignature classMember = cls.element.lookupClassMember(memberName);
|
| + Expect.isNotNull(classMember, "No class member '$memberName' in $cls.");
|
| + Expect.equals(member, classMember);
|
| + } else if (checkType == NO_CLASS_MEMBER) {
|
| + Expect.isNull(cls.element.lookupClassMember(memberName));
|
| + }
|
| +
|
| + if (inheritedFrom != null) {
|
| + MemberSignature inherited = checkType == CHECK_CLASS
|
| + ? inheritedFrom.element.lookupClassMember(memberName)
|
| + : inheritedFrom.element.lookupInterfaceMember(memberName);
|
| + Expect.isNotNull(inherited,
|
| + "No $memberKind member '$memberName' in $inheritedFrom.");
|
| + Expect.equals(inherited.inheritFrom(inheritedFrom), member);
|
| + } else {
|
| + if (erroneousFrom != null || synthesizedFrom != null) {
|
| + Expect.notEquals(checkType, CHECK_CLASS,
|
| + "Arguments 'erroneousFrom' and 'synthesizedFrom' only apply "
|
| + "to interface members.");
|
| + if (synthesizedFrom != null) {
|
| + Expect.isTrue(member is SyntheticMember,
|
| + "Member '$member' is not synthesized.");
|
| + } else {
|
| + Expect.isTrue(member is ErroneousMember,
|
| + "Member '$member' is not erroneous.");
|
| + }
|
| + Set<MemberSignature> members = new Set<MemberSignature>();
|
| + List from = synthesizedFrom != null ? synthesizedFrom : erroneousFrom;
|
| + for (InterfaceType type in from) {
|
| + MemberSignature inheritedMember =
|
| + type.element.lookupInterfaceMember(memberName);
|
| + Expect.isNotNull(inheritedMember);
|
| + members.add(inheritedMember.inheritFrom(type));
|
| + }
|
| + Expect.setEquals(members, member.declarations);
|
| + } else if (declarer != null) {
|
| + Expect.equals(declarer, member.declarer,
|
| + "Unexpected declarer '${member.declarer}' of $memberKind member "
|
| + "'$member'. Expected '${declarer}'.");
|
| + } else {
|
| + Expect.equals(cls.element, member.element.getEnclosingClass());
|
| + Expect.equals(cls, member.declarer);
|
| + }
|
| + Expect.equals(isSetter, member.isSetter);
|
| + Expect.equals(isGetter, member.isGetter);
|
| + if (type != null) {
|
| + Expect.equals(type, member.type,
|
| + "Unexpected type of $memberKind member '$member'.");
|
| + }
|
| + if (functionType != null) {
|
| + if (type == null) {
|
| + Expect.equals(member.type, member.functionType,
|
| + "Unexpected type of $memberKind member '$member'.");
|
| + }
|
| + Expect.equals(functionType, member.functionType,
|
| + "Unexpected member type of $memberKind member '$member'.");
|
| + }
|
| + }
|
| + return member;
|
| +}
|
| +
|
| +void checkMemberCount(InterfaceType cls, int expectedCount,
|
| + {bool interfaceMembers: true}) {
|
| + int count = 0;
|
| + if (interfaceMembers) {
|
| + cls.element.forEachInterfaceMember((_) => count++);
|
| + } else {
|
| + cls.element.forEachClassMember((_) => count++);
|
| + }
|
| + Expect.equals(expectedCount, count);
|
| +}
|
| +
|
| +void testClassMembers() {
|
| + asyncTest(() => TypeEnvironment.create(r"""
|
| + abstract class A {
|
| + int field;
|
| + final finalField = 0;
|
| + static var staticField;
|
| +
|
| + int get getter => 0;
|
| + get abstractGetter;
|
| + void set setter(int _) {}
|
| + set abstractSetter(_);
|
| +
|
| + method() {}
|
| + abstractMethod();
|
| + static staticMethod() {}
|
| + }
|
| + class B<T> {
|
| + T field;
|
| + void method(T t) {}
|
| + static staticMethod() {}
|
| + toString([T t]) {}
|
| + }
|
| + class C<S> extends B<S> {}
|
| + class D extends C<int> {}
|
| + class E extends D {}
|
| + """, useMockCompiler: false).then((env) {
|
| +
|
| + InterfaceType bool_ = env['bool'];
|
| + InterfaceType String_ = env['String'];
|
| + InterfaceType num_ = env['num'];
|
| + InterfaceType int_ = env['int'];
|
| + InterfaceType dynamic_ = env['dynamic'];
|
| + VoidType void_ = env['void'];
|
| + InterfaceType Type_ = env['Type'];
|
| + InterfaceType Invocation_ = env['Invocation'];
|
| +
|
| + InterfaceType Object_ = env['Object'];
|
| + checkMemberCount(Object_, 5 /*declared*/, interfaceMembers: true);
|
| + checkMemberCount(Object_, 5 /*declared*/, interfaceMembers: false);
|
| +
|
| + checkMember(Object_, '==',
|
| + functionType: env.functionType(bool_, [dynamic_]));
|
| + checkMember(Object_, 'hashCode',
|
| + isGetter: true,
|
| + type: int_, functionType: env.functionType(int_, []));
|
| + checkMember(Object_, 'noSuchMethod',
|
| + functionType: env.functionType(dynamic_, [Invocation_]));
|
| + checkMember(Object_, 'runtimeType',
|
| + isGetter: true,
|
| + type: Type_, functionType: env.functionType(Type_, []));
|
| + checkMember(Object_, 'toString',
|
| + functionType: env.functionType(String_, []));
|
| +
|
| + InterfaceType A = env['A'];
|
| + checkMemberCount(A, 5 /*inherited*/ + 9 /*non-static declared*/,
|
| + interfaceMembers: true);
|
| + checkMemberCount(A, 5 /*inherited*/ + 9 /*non-abstract declared*/,
|
| + interfaceMembers: false);
|
| +
|
| + checkMember(A, '==', inheritedFrom: Object_);
|
| + checkMember(A, 'hashCode', inheritedFrom: Object_);
|
| + checkMember(A, 'noSuchMethod', inheritedFrom: Object_);
|
| + checkMember(A, 'runtimeType', inheritedFrom: Object_);
|
| + checkMember(A, 'toString', inheritedFrom: Object_);
|
| +
|
| + checkMember(A, 'field', isGetter: true,
|
| + type: int_, functionType: env.functionType(int_, []));
|
| + checkMember(A, 'field', isSetter: true,
|
| + type: int_, functionType: env.functionType(void_, [int_]));
|
| + checkMember(A, 'finalField', isGetter: true,
|
| + type: dynamic_, functionType: env.functionType(dynamic_, []));
|
| + checkMember(A, 'staticField', isGetter: true, isStatic: true,
|
| + checkType: CHECK_CLASS,
|
| + type: dynamic_, functionType: env.functionType(dynamic_, []));
|
| + checkMember(A, 'staticField', isSetter: true, isStatic: true,
|
| + checkType: CHECK_CLASS, type: dynamic_,
|
| + functionType: env.functionType(void_, [dynamic_]));
|
| +
|
| + checkMember(A, 'getter', isGetter: true,
|
| + type: int_, functionType: env.functionType(int_, []));
|
| + checkMember(A, 'abstractGetter', isGetter: true,
|
| + checkType: NO_CLASS_MEMBER,
|
| + type: dynamic_, functionType: env.functionType(dynamic_, []));
|
| + checkMember(A, 'setter', isSetter: true,
|
| + type: int_, functionType: env.functionType(void_, [int_]));
|
| + checkMember(A, 'abstractSetter', isSetter: true,
|
| + checkType: NO_CLASS_MEMBER, type: dynamic_,
|
| + functionType: env.functionType(dynamic_, [dynamic_]));
|
| +
|
| + checkMember(A, 'method', functionType: env.functionType(dynamic_, []));
|
| + checkMember(A, 'abstractMethod',
|
| + checkType: NO_CLASS_MEMBER,
|
| + functionType: env.functionType(dynamic_, []));
|
| + checkMember(A, 'staticMethod',
|
| + checkType: CHECK_CLASS,
|
| + isStatic: true, functionType: env.functionType(dynamic_, []));
|
| +
|
| + ClassElement B = env.getElement('B');
|
| + InterfaceType B_this = B.thisType;
|
| + TypeVariableType B_T = B_this.typeArguments.head;
|
| + checkMemberCount(B_this, 4 /*inherited*/ + 4 /*non-static declared*/,
|
| + interfaceMembers: true);
|
| + checkMemberCount(B_this, 4 /*inherited*/ + 5 /*declared*/,
|
| + interfaceMembers: false);
|
| +
|
| + checkMember(B_this, '==', inheritedFrom: Object_);
|
| + checkMember(B_this, 'hashCode', inheritedFrom: Object_);
|
| + checkMember(B_this, 'noSuchMethod', inheritedFrom: Object_);
|
| + checkMember(B_this, 'runtimeType', inheritedFrom: Object_);
|
| +
|
| + checkMember(B_this, 'field', isGetter: true,
|
| + type: B_T, functionType: env.functionType(B_T, []));
|
| + checkMember(B_this, 'field', isSetter: true,
|
| + type: B_T, functionType: env.functionType(void_, [B_T]));
|
| + checkMember(B_this, 'method', functionType: env.functionType(void_, [B_T]));
|
| + checkMember(B_this, 'staticMethod',
|
| + checkType: CHECK_CLASS,
|
| + isStatic: true, functionType: env.functionType(dynamic_, []));
|
| + checkMember(B_this, 'toString',
|
| + functionType: env.functionType(dynamic_, [],
|
| + optionalParameters: [B_T]));
|
| +
|
| + ClassElement C = env.getElement('C');
|
| + InterfaceType C_this = C.thisType;
|
| + TypeVariableType C_S = C_this.typeArguments.head;
|
| + checkMemberCount(C_this, 8 /*inherited*/, interfaceMembers: true);
|
| + checkMemberCount(C_this, 8 /*inherited*/, interfaceMembers: false);
|
| + InterfaceType B_S = instantiate(B, [C_S]);
|
| +
|
| + checkMember(C_this, '==', inheritedFrom: Object_);
|
| + checkMember(C_this, 'hashCode', inheritedFrom: Object_);
|
| + checkMember(C_this, 'noSuchMethod', inheritedFrom: Object_);
|
| + checkMember(C_this, 'runtimeType', inheritedFrom: Object_);
|
| +
|
| + checkMember(C_this, 'field', isGetter: true,
|
| + declarer: B_S,
|
| + type: C_S, functionType: env.functionType(C_S, []));
|
| + checkMember(C_this, 'field', isSetter: true,
|
| + declarer: B_S,
|
| + type: C_S, functionType: env.functionType(void_, [C_S]));
|
| + checkMember(C_this, 'method',
|
| + declarer: B_S,
|
| + functionType: env.functionType(void_, [C_S]));
|
| + checkMember(C_this, 'toString',
|
| + declarer: B_S,
|
| + functionType: env.functionType(dynamic_, [],
|
| + optionalParameters: [C_S]));
|
| +
|
| + InterfaceType D = env['D'];
|
| + checkMemberCount(D, 8 /*inherited*/, interfaceMembers: true);
|
| + checkMemberCount(D, 8 /*inherited*/, interfaceMembers: false);
|
| + InterfaceType B_int = instantiate(B, [int_]);
|
| +
|
| + checkMember(D, '==', inheritedFrom: Object_);
|
| + checkMember(D, 'hashCode', inheritedFrom: Object_);
|
| + checkMember(D, 'noSuchMethod', inheritedFrom: Object_);
|
| + checkMember(D, 'runtimeType', inheritedFrom: Object_);
|
| +
|
| + checkMember(D, 'field', isGetter: true,
|
| + declarer: B_int,
|
| + type: int_, functionType: env.functionType(int_, []));
|
| + checkMember(D, 'field', isSetter: true,
|
| + declarer: B_int,
|
| + type: int_, functionType: env.functionType(void_, [int_]));
|
| + checkMember(D, 'method',
|
| + declarer: B_int,
|
| + functionType: env.functionType(void_, [int_]));
|
| + checkMember(D, 'toString',
|
| + declarer: B_int,
|
| + functionType: env.functionType(dynamic_, [],
|
| + optionalParameters: [int_]));
|
| +
|
| + InterfaceType E = env['E'];
|
| + checkMemberCount(E, 8 /*inherited*/, interfaceMembers: true);
|
| + checkMemberCount(E, 8 /*inherited*/, interfaceMembers: false);
|
| +
|
| + checkMember(E, '==', inheritedFrom: Object_);
|
| + checkMember(E, 'hashCode', inheritedFrom: Object_);
|
| + checkMember(E, 'noSuchMethod', inheritedFrom: Object_);
|
| + checkMember(E, 'runtimeType', inheritedFrom: Object_);
|
| +
|
| + checkMember(E, 'field', isGetter: true,
|
| + declarer: B_int,
|
| + type: int_, functionType: env.functionType(int_, []));
|
| + checkMember(E, 'field', isSetter: true,
|
| + declarer: B_int,
|
| + type: int_, functionType: env.functionType(void_, [int_]));
|
| + checkMember(E, 'method',
|
| + declarer: B_int,
|
| + functionType: env.functionType(void_, [int_]));
|
| + checkMember(E, 'toString',
|
| + declarer: B_int,
|
| + functionType: env.functionType(dynamic_, [],
|
| + optionalParameters: [int_]));
|
| + }));
|
| +}
|
| +
|
| +void testInterfaceMembers() {
|
| + asyncTest(() => TypeEnvironment.create(r"""
|
| + abstract class A {
|
| + num method1();
|
| + void method2();
|
| + void method3();
|
| + void method4();
|
| + method5(a);
|
| + method6(a);
|
| + method7(a);
|
| + method8(a, b);
|
| + method9(a, b, c);
|
| + method10(a, {b, c});
|
| + method11(a, {b, c});
|
| + num get getter1;
|
| + num get getter2;
|
| + void set setter1(num _);
|
| + void set setter2(num _);
|
| + void set setter3(num _);
|
| + get getterAndMethod;
|
| + }
|
| + abstract class B {
|
| + int method1();
|
| + int method2();
|
| + num method3();
|
| + num method4();
|
| + method5([a]);
|
| + method6([a, b]);
|
| + method7(a, [b]);
|
| + method8([a]);
|
| + method9(a, [b]);
|
| + method10(a, {c, d});
|
| + method11(a, b, {c, d});
|
| + num get getter1;
|
| + int get getter2;
|
| + void set setter1(num _);
|
| + set setter2(num _);
|
| + void set setter3(int _);
|
| + getterAndMethod();
|
| + }
|
| + abstract class C {
|
| + int method3();
|
| + num method4();
|
| + }
|
| + abstract class D implements A, B, C {}
|
| + """).then((env) {
|
| +
|
| + InterfaceType dynamic_ = env['dynamic'];
|
| + VoidType void_ = env['void'];
|
| + InterfaceType num_ = env['num'];
|
| + InterfaceType int_ = env['int'];
|
| +
|
| + InterfaceType A = env['A'];
|
| + InterfaceType B = env['B'];
|
| + InterfaceType C = env['C'];
|
| + InterfaceType D = env['D'];
|
| +
|
| + // A: num method1()
|
| + // B: int method1()
|
| + // D: dynamic method1() -- synthesized from A and B.
|
| + checkMember(D, 'method1',
|
| + synthesizedFrom: [A, B],
|
| + functionType: env.functionType(dynamic_ , []),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: void method2()
|
| + // B: int method2()
|
| + // D: int method2() -- inherited from B
|
| + checkMember(D, 'method2', inheritedFrom: B, checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: void method3()
|
| + // B: num method3()
|
| + // C: int method3()
|
| + // D: dynamic method3() -- synthesized from A, B, and C.
|
| + checkMember(D, 'method3',
|
| + synthesizedFrom: [A, B, C],
|
| + functionType: env.functionType(dynamic_ , []),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: void method4()
|
| + // B: num method4()
|
| + // C: num method4()
|
| + // D: num method4() -- synthesized from B and C.
|
| + checkMember(D, 'method4',
|
| + synthesizedFrom: [B, C],
|
| + functionType: env.functionType(num_, []),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: method5(a)
|
| + // B: method5([a])
|
| + // D: method5([a]) -- inherited from B
|
| + checkMember(D, 'method5', inheritedFrom: B, checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: method6(a)
|
| + // B: method6([a, b])
|
| + // D: method6([a, b]) -- inherited from B
|
| + checkMember(D, 'method6', inheritedFrom: B, checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: method7(a)
|
| + // B: method7(a, [b])
|
| + // D: method7(a, [b]) -- inherited from B
|
| + checkMember(D, 'method7', inheritedFrom: B, checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: method8(a, b)
|
| + // B: method8([a])
|
| + // D: method8([a, b]) -- synthesized from A and B.
|
| + checkMember(D, 'method8',
|
| + synthesizedFrom: [A, B],
|
| + functionType: env.functionType(
|
| + dynamic_, [], optionalParameters: [dynamic_, dynamic_]),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: method9(a, b, c)
|
| + // B: method9(a, [b])
|
| + // D: method9(a, [b, c]) -- synthesized from A and B.
|
| + checkMember(D, 'method9',
|
| + synthesizedFrom: [A, B],
|
| + functionType: env.functionType(
|
| + dynamic_, [dynamic_], optionalParameters: [dynamic_, dynamic_]),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: method10(a, {b, c})
|
| + // B: method10(a, {c, d})
|
| + // D: method10(a, {b, c, d}) -- synthesized from A and B.
|
| + checkMember(D, 'method10',
|
| + synthesizedFrom: [A, B],
|
| + functionType: env.functionType(dynamic_, [dynamic_],
|
| + namedParameters: {'b': dynamic_,
|
| + 'c': dynamic_,
|
| + 'd': dynamic_}),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: method11(a, {b, c})
|
| + // B: method11(a, b, {c, d})
|
| + // D: method11(a, [b], {c, d}) -- synthesized from A and B.
|
| + // TODO(johnniwinther): Change to check synthesized member when function
|
| + // types with both optional and named parameters are supported.
|
| + Expect.isNull(getMember(D, 'method11'));
|
| + /*checkMember(D, 'method11',
|
| + synthesizedFrom: [A, B],
|
| + functionType: env.functionType(dynamic_, [dynamic_],
|
| + optionalParameters: [dynamic_],
|
| + namedParameters: {'c': dynamic_,
|
| + 'd': dynamic_,}),
|
| + checkType: NO_CLASS_MEMBER);*/
|
| +
|
| + // A: num get getter1
|
| + // B: num get getter1
|
| + // D: num get getter1 -- synthesized from A and B.
|
| + checkMember(D, 'getter1',
|
| + isGetter: true,
|
| + synthesizedFrom: [A, B], type: num_,
|
| + functionType: env.functionType(num_ , []),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: num get getter2
|
| + // B: int get getter2
|
| + // D: dynamic get getter2 -- synthesized from A and B.
|
| + checkMember(D, 'getter2',
|
| + isGetter: true,
|
| + synthesizedFrom: [A, B], type: dynamic_,
|
| + functionType: env.functionType(dynamic_ , []),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: void set setter1(num _)
|
| + // B: void set setter1(num _)
|
| + // D: void set setter1(num _) -- synthesized from A and B.
|
| + checkMember(D, 'setter1',
|
| + isSetter: true,
|
| + synthesizedFrom: [A, B], type: num_,
|
| + functionType: env.functionType(void_ , [num_]),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: void set setter2(num _)
|
| + // B: set setter2(num _)
|
| + // D: dynamic set setter2(dynamic _) -- synthesized from A and B.
|
| + checkMember(D, 'setter2',
|
| + isSetter: true,
|
| + synthesizedFrom: [A, B], type: dynamic_,
|
| + functionType: env.functionType(dynamic_ , [dynamic_]),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: void set setter3(num _)
|
| + // B: void set setter3(int _)
|
| + // D: dynamic set setter3(dynamic _) -- synthesized from A and B.
|
| + checkMember(D, 'setter3',
|
| + isSetter: true,
|
| + synthesizedFrom: [A, B], type: dynamic_,
|
| + functionType: env.functionType(dynamic_ , [dynamic_]),
|
| + checkType: NO_CLASS_MEMBER);
|
| +
|
| + // A: get getterAndMethod
|
| + // B: getterAndMethod()
|
| + // D: nothing inherited
|
| + checkMember(D, 'getterAndMethod',
|
| + erroneousFrom: [A, B],
|
| + checkType: NO_CLASS_MEMBER);
|
| + }));
|
| +}
|
| +
|
| +void testClassVsInterfaceMembers() {
|
| + asyncTest(() => TypeEnvironment.create(r"""
|
| + class A {
|
| + method1() {}
|
| + method2() {}
|
| + }
|
| + abstract class B {
|
| + method1();
|
| + method2(a);
|
| + }
|
| + abstract class C extends A implements B {}
|
| + """).then((env) {
|
| +
|
| + InterfaceType dynamic_ = env['dynamic'];
|
| + VoidType void_ = env['void'];
|
| + InterfaceType num_ = env['num'];
|
| + InterfaceType int_ = env['int'];
|
| +
|
| + InterfaceType A = env['A'];
|
| + InterfaceType B = env['B'];
|
| + InterfaceType C = env['C'];
|
| +
|
| + // A: method1()
|
| + // B: method1()
|
| + // C class: method1() -- inherited from A.
|
| + // C interface: dynamic method1() -- synthesized from A and B.
|
| + MemberSignature interfaceMember =
|
| + checkMember(C, 'method1', checkType: CHECK_INTERFACE,
|
| + synthesizedFrom: [A, B],
|
| + functionType: env.functionType(dynamic_ , []));
|
| + MemberSignature classMember =
|
| + checkMember(C, 'method1', checkType: CHECK_CLASS, inheritedFrom: A);
|
| + Expect.notEquals(interfaceMember, classMember);
|
| +
|
| + // A: method2()
|
| + // B: method2(a)
|
| + // C class: method2() -- inherited from A.
|
| + // C interface: dynamic method2([a]) -- synthesized from A and B.
|
| + interfaceMember =
|
| + checkMember(C, 'method2', checkType: CHECK_INTERFACE,
|
| + synthesizedFrom: [A, B],
|
| + functionType: env.functionType(dynamic_ , [],
|
| + optionalParameters: [dynamic_]));
|
| + classMember =
|
| + checkMember(C, 'method2', checkType: CHECK_CLASS, inheritedFrom: A);
|
| + Expect.notEquals(interfaceMember, classMember);
|
| + }));
|
| +}
|
| +
|
| +
|
| +void testMixinMembers() {
|
| + asyncTest(() => TypeEnvironment.create(r"""
|
| + class A<T> {
|
| + method1() {}
|
| + method2() {}
|
| + method3(T a) {}
|
| + method4(T a) {}
|
| + }
|
| + abstract class B<S> {
|
| + method1();
|
| + method2(a);
|
| + method3(S a) {}
|
| + }
|
| + abstract class C<U, V> extends Object with A<U> implements B<V> {}
|
| + """).then((env) {
|
| +
|
| + InterfaceType dynamic_ = env['dynamic'];
|
| + VoidType void_ = env['void'];
|
| + InterfaceType num_ = env['num'];
|
| + InterfaceType int_ = env['int'];
|
| +
|
| + ClassElement A = env.getElement('A');
|
| + ClassElement B = env.getElement('B');
|
| + ClassElement C = env.getElement('C');
|
| + InterfaceType C_this = C.thisType;
|
| + TypeVariableType C_U = C_this.typeArguments.head;
|
| + TypeVariableType C_V = C_this.typeArguments.tail.head;
|
| + InterfaceType A_U = instantiate(A, [C_U]);
|
| + InterfaceType B_V = instantiate(B, [C_V]);
|
| +
|
| + // A: method1()
|
| + // B: method1()
|
| + // C class: method1() -- inherited from A.
|
| + // C interface: dynamic method1() -- synthesized from A and B.
|
| + MemberSignature interfaceMember =
|
| + checkMember(C_this, 'method1', checkType: CHECK_INTERFACE,
|
| + synthesizedFrom: [A_U, B_V],
|
| + functionType: env.functionType(dynamic_ , []));
|
| + MemberSignature classMember =
|
| + checkMember(C_this, 'method1', checkType: CHECK_CLASS,
|
| + inheritedFrom: A_U);
|
| + Expect.notEquals(interfaceMember, classMember);
|
| +
|
| + // A: method2()
|
| + // B: method2(a)
|
| + // C class: method2() -- inherited from A.
|
| + // C interface: dynamic method2([a]) -- synthesized from A and B.
|
| + interfaceMember =
|
| + checkMember(C_this, 'method2', checkType: CHECK_INTERFACE,
|
| + synthesizedFrom: [A_U, B_V],
|
| + functionType: env.functionType(dynamic_ , [],
|
| + optionalParameters: [dynamic_]));
|
| + classMember =
|
| + checkMember(C_this, 'method2', checkType: CHECK_CLASS,
|
| + inheritedFrom: A_U);
|
| + Expect.notEquals(interfaceMember, classMember);
|
| +
|
| + // A: method3(U a)
|
| + // B: method3(V a)
|
| + // C class: method3(U a) -- inherited from A.
|
| + // C interface: dynamic method3(a) -- synthesized from A and B.
|
| + interfaceMember =
|
| + checkMember(C_this, 'method3', checkType: CHECK_INTERFACE,
|
| + synthesizedFrom: [A_U, B_V],
|
| + functionType: env.functionType(dynamic_ , [dynamic_]));
|
| + classMember =
|
| + checkMember(C_this, 'method3', checkType: CHECK_CLASS,
|
| + inheritedFrom: A_U);
|
| + Expect.notEquals(interfaceMember, classMember);
|
| +
|
| + // A: method4(U a)
|
| + // B: --
|
| + // C class: method4(U a) -- inherited from A.
|
| + // C interface: method4(U a) -- inherited from A.
|
| + checkMember(C_this, 'method4', checkType: ALSO_CLASS_MEMBER,
|
| + inheritedFrom: A_U);
|
| + }));
|
| +}
|
|
|