| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library members_test; | 5 library members_test; |
| 6 | 6 |
| 7 import 'package:expect/expect.dart'; | 7 import 'package:expect/expect.dart'; |
| 8 import "package:async_helper/async_helper.dart"; | 8 import "package:async_helper/async_helper.dart"; |
| 9 import 'type_test_helper.dart'; | 9 import 'type_test_helper.dart'; |
| 10 import 'package:compiler/src/dart_types.dart'; | 10 import 'package:compiler/src/dart_types.dart'; |
| 11 import "package:compiler/src/elements/elements.dart" show | 11 import "package:compiler/src/elements/elements.dart" |
| 12 Element, | 12 show Element, ClassElement, MemberSignature, Name, PublicName, Member; |
| 13 ClassElement, | 13 import "package:compiler/src/resolution/class_members.dart" |
| 14 MemberSignature, | 14 show MembersCreator, DeclaredMember, ErroneousMember, SyntheticMember; |
| 15 Name, | |
| 16 PublicName, | |
| 17 Member; | |
| 18 import "package:compiler/src/resolution/class_members.dart" show | |
| 19 MembersCreator, | |
| 20 DeclaredMember, | |
| 21 ErroneousMember, | |
| 22 SyntheticMember; | |
| 23 | 15 |
| 24 void main() { | 16 void main() { |
| 25 testClassMembers(); | 17 testClassMembers(); |
| 26 testInterfaceMembers(); | 18 testInterfaceMembers(); |
| 27 testClassVsInterfaceMembers(); | 19 testClassVsInterfaceMembers(); |
| 28 testMixinMembers(); | 20 testMixinMembers(); |
| 29 testMixinMembersWithoutImplements(); | 21 testMixinMembersWithoutImplements(); |
| 30 } | 22 } |
| 31 | 23 |
| 32 MemberSignature getMember(InterfaceType cls, String name, | 24 MemberSignature getMember(InterfaceType cls, String name, |
| 33 {bool isSetter: false, | 25 {bool isSetter: false, int checkType: CHECK_INTERFACE}) { |
| 34 int checkType: CHECK_INTERFACE}) { | 26 Name memberName = new Name(name, cls.element.library, isSetter: isSetter); |
| 35 Name memberName = | |
| 36 new Name(name, cls.element.library, isSetter: isSetter); | |
| 37 MemberSignature member = checkType == CHECK_CLASS | 27 MemberSignature member = checkType == CHECK_CLASS |
| 38 ? cls.element.lookupClassMember(memberName) | 28 ? cls.element.lookupClassMember(memberName) |
| 39 : cls.element.lookupInterfaceMember(memberName); | 29 : cls.element.lookupInterfaceMember(memberName); |
| 40 if (member != null) { | 30 if (member != null) { |
| 41 Expect.equals(memberName, member.name); | 31 Expect.equals(memberName, member.name); |
| 42 } | 32 } |
| 43 return member; | 33 return member; |
| 44 } | 34 } |
| 45 | 35 |
| 46 /// Check interface member only. | 36 /// Check interface member only. |
| 47 const int CHECK_INTERFACE = 0; | 37 const int CHECK_INTERFACE = 0; |
| 38 |
| 48 /// Check class member only. | 39 /// Check class member only. |
| 49 const int CHECK_CLASS = 1; | 40 const int CHECK_CLASS = 1; |
| 41 |
| 50 /// Check that there is no class member for the interface member. | 42 /// Check that there is no class member for the interface member. |
| 51 const int NO_CLASS_MEMBER = 2; | 43 const int NO_CLASS_MEMBER = 2; |
| 44 |
| 52 /// Check that the interface member is also a class member. | 45 /// Check that the interface member is also a class member. |
| 53 const int ALSO_CLASS_MEMBER = 3; | 46 const int ALSO_CLASS_MEMBER = 3; |
| 54 | 47 |
| 55 /** | 48 /** |
| 56 * Checks [member] or interface member [name] of the declaration of [cls]. | 49 * Checks [member] or interface member [name] of the declaration of [cls]. |
| 57 * | 50 * |
| 58 * If [inheritFrom] is set, the member from [cls] must be identical to the | 51 * If [inheritFrom] is set, the member from [cls] must be identical to the |
| 59 * member from [inheritedFrom]. | 52 * member from [inheritedFrom]. |
| 60 * | 53 * |
| 61 * Otherwise, the properties of member are checked against the values of | 54 * Otherwise, the properties of member are checked against the values of |
| 62 * [isStatic], [isSetter], [isGetter], [declarer], [type] and | 55 * [isStatic], [isSetter], [isGetter], [declarer], [type] and |
| 63 * [functionType]. | 56 * [functionType]. |
| 64 * | 57 * |
| 65 * If [synthesizedFrom] or [erroneousFrom] is not `null`, the member is checked | 58 * If [synthesizedFrom] or [erroneousFrom] is not `null`, the member is checked |
| 66 * to be synthesized for the corresponding members found on the type is | 59 * to be synthesized for the corresponding members found on the type is |
| 67 * [synthesizedFrom] or or [erroneousFrom], respectively. | 60 * [synthesizedFrom] or or [erroneousFrom], respectively. |
| 68 * Otherwise, if [declarer] is `null`, the declarer is checked to be [cls], and | 61 * Otherwise, if [declarer] is `null`, the declarer is checked to be [cls], and |
| 69 * if [declarer] is not `null`, the declarer is checked to be [declarer]. | 62 * if [declarer] is not `null`, the declarer is checked to be [declarer]. |
| 70 * If [type] is `null` it is checked that the type of the member is also the | 63 * If [type] is `null` it is checked that the type of the member is also the |
| 71 * member type, otherwise the type is checked to be [type]. | 64 * member type, otherwise the type is checked to be [type]. |
| 72 * | 65 * |
| 73 * If [isClassMember] is `true` it is checked that the member is also a class | 66 * If [isClassMember] is `true` it is checked that the member is also a class |
| 74 * member. | 67 * member. |
| 75 */ | 68 */ |
| 76 MemberSignature checkMember(InterfaceType cls, | 69 MemberSignature checkMember(InterfaceType cls, String name, |
| 77 String name, | 70 {bool isStatic: false, |
| 78 {bool isStatic: false, | 71 bool isSetter: false, |
| 79 bool isSetter: false, | 72 bool isGetter: false, |
| 80 bool isGetter: false, | 73 InterfaceType declarer, |
| 81 InterfaceType declarer, | 74 DartType type, |
| 82 DartType type, | 75 FunctionType functionType, |
| 83 FunctionType functionType, | 76 InterfaceType inheritedFrom, |
| 84 InterfaceType inheritedFrom, | 77 List<InterfaceType> synthesizedFrom, |
| 85 List<InterfaceType> synthesizedFrom, | 78 List<InterfaceType> erroneousFrom, |
| 86 List<InterfaceType> erroneousFrom, | 79 int checkType: ALSO_CLASS_MEMBER}) { |
| 87 int checkType: ALSO_CLASS_MEMBER}) { | |
| 88 String memberKind = checkType == CHECK_CLASS ? 'class' : 'interface'; | 80 String memberKind = checkType == CHECK_CLASS ? 'class' : 'interface'; |
| 89 MemberSignature member = | 81 MemberSignature member = |
| 90 getMember(cls, name, isSetter: isSetter, checkType: checkType); | 82 getMember(cls, name, isSetter: isSetter, checkType: checkType); |
| 91 Expect.isNotNull(member, "No $memberKind member '$name' in $cls."); | 83 Expect.isNotNull(member, "No $memberKind member '$name' in $cls."); |
| 92 Name memberName = member.name; | 84 Name memberName = member.name; |
| 93 if (checkType == ALSO_CLASS_MEMBER) { | 85 if (checkType == ALSO_CLASS_MEMBER) { |
| 94 MemberSignature classMember = cls.element.lookupClassMember(memberName); | 86 MemberSignature classMember = cls.element.lookupClassMember(memberName); |
| 95 Expect.isNotNull(classMember, "No class member '$memberName' in $cls."); | 87 Expect.isNotNull(classMember, "No class member '$memberName' in $cls."); |
| 96 Expect.equals(member, classMember); | 88 Expect.equals(member, classMember); |
| 97 } else if (checkType == NO_CLASS_MEMBER) { | 89 } else if (checkType == NO_CLASS_MEMBER) { |
| 98 Expect.isNull(cls.element.lookupClassMember(memberName)); | 90 Expect.isNull(cls.element.lookupClassMember(memberName)); |
| 99 } | 91 } |
| 100 | 92 |
| 101 if (inheritedFrom != null) { | 93 if (inheritedFrom != null) { |
| 102 DeclaredMember inherited = checkType == CHECK_CLASS | 94 DeclaredMember inherited = checkType == CHECK_CLASS |
| 103 ? inheritedFrom.element.lookupClassMember(memberName) | 95 ? inheritedFrom.element.lookupClassMember(memberName) |
| 104 : inheritedFrom.element.lookupInterfaceMember(memberName); | 96 : inheritedFrom.element.lookupInterfaceMember(memberName); |
| 105 Expect.isNotNull(inherited, | 97 Expect.isNotNull( |
| 106 "No $memberKind member '$memberName' in $inheritedFrom."); | 98 inherited, "No $memberKind member '$memberName' in $inheritedFrom."); |
| 107 Expect.equals(inherited.inheritFrom(inheritedFrom), member); | 99 Expect.equals(inherited.inheritFrom(inheritedFrom), member); |
| 108 } else { | 100 } else { |
| 109 if (erroneousFrom != null || synthesizedFrom != null) { | 101 if (erroneousFrom != null || synthesizedFrom != null) { |
| 110 Expect.notEquals(checkType, CHECK_CLASS, | 102 Expect.notEquals( |
| 103 checkType, |
| 104 CHECK_CLASS, |
| 111 "Arguments 'erroneousFrom' and 'synthesizedFrom' only apply " | 105 "Arguments 'erroneousFrom' and 'synthesizedFrom' only apply " |
| 112 "to interface members."); | 106 "to interface members."); |
| 113 if (synthesizedFrom != null) { | 107 if (synthesizedFrom != null) { |
| 114 Expect.isTrue(member is SyntheticMember, | 108 Expect.isTrue( |
| 115 "Member '$member' is not synthesized."); | 109 member is SyntheticMember, "Member '$member' is not synthesized."); |
| 116 } else { | 110 } else { |
| 117 Expect.isTrue(member is ErroneousMember, | 111 Expect.isTrue( |
| 118 "Member '$member' is not erroneous."); | 112 member is ErroneousMember, "Member '$member' is not erroneous."); |
| 119 } | 113 } |
| 120 Set<MemberSignature> members = new Set<MemberSignature>(); | 114 Set<MemberSignature> members = new Set<MemberSignature>(); |
| 121 List from = synthesizedFrom != null ? synthesizedFrom : erroneousFrom; | 115 List from = synthesizedFrom != null ? synthesizedFrom : erroneousFrom; |
| 122 for (InterfaceType type in from) { | 116 for (InterfaceType type in from) { |
| 123 DeclaredMember inheritedMember = | 117 DeclaredMember inheritedMember = |
| 124 type.element.lookupInterfaceMember(memberName); | 118 type.element.lookupInterfaceMember(memberName); |
| 125 Expect.isNotNull(inheritedMember); | 119 Expect.isNotNull(inheritedMember); |
| 126 members.add(inheritedMember.inheritFrom(type)); | 120 members.add(inheritedMember.inheritFrom(type)); |
| 127 } | 121 } |
| 128 Expect.setEquals(members, member.declarations); | 122 Expect.setEquals(members, member.declarations); |
| 129 } else if (declarer != null) { | 123 } else if (declarer != null) { |
| 130 DeclaredMember declared = member; | 124 DeclaredMember declared = member; |
| 131 Expect.equals(declarer, declared.declarer, | 125 Expect.equals( |
| 126 declarer, |
| 127 declared.declarer, |
| 132 "Unexpected declarer '${declared.declarer}' of $memberKind member " | 128 "Unexpected declarer '${declared.declarer}' of $memberKind member " |
| 133 "'$member'. Expected '${declarer}'."); | 129 "'$member'. Expected '${declarer}'."); |
| 134 } else { | 130 } else { |
| 135 DeclaredMember declared = member; | 131 DeclaredMember declared = member; |
| 136 Expect.equals(cls.element, declared.element.enclosingClass); | 132 Expect.equals(cls.element, declared.element.enclosingClass); |
| 137 Expect.equals(cls, declared.declarer); | 133 Expect.equals(cls, declared.declarer); |
| 138 } | 134 } |
| 139 Expect.equals(isSetter, member.isSetter); | 135 Expect.equals(isSetter, member.isSetter); |
| 140 Expect.equals(isGetter, member.isGetter); | 136 Expect.equals(isGetter, member.isGetter); |
| 141 if (type != null) { | 137 if (type != null) { |
| 142 Expect.equals(type, member.type, | 138 Expect.equals(type, member.type, |
| 143 "Unexpected type of $memberKind member '$member'."); | 139 "Unexpected type of $memberKind member '$member'."); |
| 144 } | 140 } |
| 145 if (functionType != null) { | 141 if (functionType != null) { |
| 146 if (type == null) { | 142 if (type == null) { |
| 147 Expect.equals(member.type, member.functionType, | 143 Expect.equals(member.type, member.functionType, |
| 148 "Unexpected type of $memberKind member '$member'."); | 144 "Unexpected type of $memberKind member '$member'."); |
| 149 } | 145 } |
| 150 Expect.equals(functionType, member.functionType, | 146 Expect.equals(functionType, member.functionType, |
| 151 "Unexpected member type of $memberKind member '$member'."); | 147 "Unexpected member type of $memberKind member '$member'."); |
| 152 } | 148 } |
| 153 } | 149 } |
| 154 return member; | 150 return member; |
| 155 } | 151 } |
| 156 | 152 |
| 157 void checkMemberCount(InterfaceType cls, int expectedCount, | 153 void checkMemberCount(InterfaceType cls, int expectedCount, |
| 158 {bool interfaceMembers: true}) { | 154 {bool interfaceMembers: true}) { |
| 159 int count = 0; | 155 int count = 0; |
| 160 if (interfaceMembers) { | 156 if (interfaceMembers) { |
| 161 cls.element.forEachInterfaceMember((_) => count++); | 157 cls.element.forEachInterfaceMember((_) => count++); |
| 162 } else { | 158 } else { |
| 163 cls.element.forEachClassMember((_) => count++); | 159 cls.element.forEachClassMember((_) => count++); |
| 164 } | 160 } |
| 165 Expect.equals(expectedCount, count); | 161 Expect.equals(expectedCount, count); |
| 166 } | 162 } |
| 167 | 163 |
| 168 void testClassMembers() { | 164 void testClassMembers() { |
| 169 asyncTest(() => TypeEnvironment.create(r""" | 165 asyncTest(() => TypeEnvironment |
| 166 .create( |
| 167 r""" |
| 170 abstract class A { | 168 abstract class A { |
| 171 int field; | 169 int field; |
| 172 final finalField = 0; | 170 final finalField = 0; |
| 173 static var staticField; | 171 static var staticField; |
| 174 | 172 |
| 175 int get getter => 0; | 173 int get getter => 0; |
| 176 get abstractGetter; | 174 get abstractGetter; |
| 177 void set setter(int _) {} | 175 void set setter(int _) {} |
| 178 set abstractSetter(_); | 176 set abstractSetter(_); |
| 179 | 177 |
| 180 method() {} | 178 method() {} |
| 181 abstractMethod(); | 179 abstractMethod(); |
| 182 static staticMethod() {} | 180 static staticMethod() {} |
| 183 } | 181 } |
| 184 class B<T> { | 182 class B<T> { |
| 185 T field; | 183 T field; |
| 186 void method(T t) {} | 184 void method(T t) {} |
| 187 static staticMethod() {} | 185 static staticMethod() {} |
| 188 toString([T t]) {} | 186 toString([T t]) {} |
| 189 } | 187 } |
| 190 class C<S> extends B<S> {} | 188 class C<S> extends B<S> {} |
| 191 class D extends C<int> {} | 189 class D extends C<int> {} |
| 192 class E extends D {} | 190 class E extends D {} |
| 193 """, useMockCompiler: false).then((env) { | 191 """, |
| 194 | 192 useMockCompiler: false) |
| 195 InterfaceType bool_ = env['bool']; | 193 .then((env) { |
| 196 InterfaceType String_ = env['String']; | 194 InterfaceType bool_ = env['bool']; |
| 197 InterfaceType num_ = env['num']; | 195 InterfaceType String_ = env['String']; |
| 198 InterfaceType int_ = env['int']; | 196 InterfaceType num_ = env['num']; |
| 199 DynamicType dynamic_ = env['dynamic']; | 197 InterfaceType int_ = env['int']; |
| 200 VoidType void_ = env['void']; | 198 DynamicType dynamic_ = env['dynamic']; |
| 201 InterfaceType Type_ = env['Type']; | 199 VoidType void_ = env['void']; |
| 202 InterfaceType Invocation_ = env['Invocation']; | 200 InterfaceType Type_ = env['Type']; |
| 203 | 201 InterfaceType Invocation_ = env['Invocation']; |
| 204 InterfaceType Object_ = env['Object']; | 202 |
| 205 checkMemberCount(Object_, 5 /*declared*/, interfaceMembers: true); | 203 InterfaceType Object_ = env['Object']; |
| 206 checkMemberCount(Object_, 5 /*declared*/, interfaceMembers: false); | 204 checkMemberCount(Object_, 5 /*declared*/, interfaceMembers: true); |
| 207 | 205 checkMemberCount(Object_, 5 /*declared*/, interfaceMembers: false); |
| 208 checkMember(Object_, '==', | 206 |
| 209 functionType: env.functionType(bool_, [dynamic_])); | 207 checkMember(Object_, '==', |
| 210 checkMember(Object_, 'hashCode', | 208 functionType: env.functionType(bool_, [dynamic_])); |
| 211 isGetter: true, | 209 checkMember(Object_, 'hashCode', |
| 212 type: int_, functionType: env.functionType(int_, [])); | 210 isGetter: true, |
| 213 checkMember(Object_, 'noSuchMethod', | 211 type: int_, |
| 214 functionType: env.functionType(dynamic_, [Invocation_])); | 212 functionType: env.functionType(int_, [])); |
| 215 checkMember(Object_, 'runtimeType', | 213 checkMember(Object_, 'noSuchMethod', |
| 216 isGetter: true, | 214 functionType: env.functionType(dynamic_, [Invocation_])); |
| 217 type: Type_, functionType: env.functionType(Type_, [])); | 215 checkMember(Object_, 'runtimeType', |
| 218 checkMember(Object_, 'toString', | 216 isGetter: true, |
| 219 functionType: env.functionType(String_, [])); | 217 type: Type_, |
| 220 | 218 functionType: env.functionType(Type_, [])); |
| 221 InterfaceType A = env['A']; | 219 checkMember(Object_, 'toString', |
| 222 MembersCreator.computeAllClassMembers(env.resolution, A.element); | 220 functionType: env.functionType(String_, [])); |
| 223 | 221 |
| 224 checkMemberCount(A, 5 /*inherited*/ + 9 /*non-static declared*/, | 222 InterfaceType A = env['A']; |
| 225 interfaceMembers: true); | 223 MembersCreator.computeAllClassMembers(env.resolution, A.element); |
| 226 checkMemberCount(A, 5 /*inherited*/ + 9 /*non-abstract declared*/ + | 224 |
| 227 3 /* abstract declared */, | 225 checkMemberCount(A, 5 /*inherited*/ + 9 /*non-static declared*/, |
| 228 interfaceMembers: false); | 226 interfaceMembers: true); |
| 229 | 227 checkMemberCount( |
| 230 checkMember(A, '==', inheritedFrom: Object_); | 228 A, |
| 231 checkMember(A, 'hashCode', inheritedFrom: Object_); | 229 5 /*inherited*/ + |
| 232 checkMember(A, 'noSuchMethod', inheritedFrom: Object_); | 230 9 /*non-abstract declared*/ + |
| 233 checkMember(A, 'runtimeType', inheritedFrom: Object_); | 231 3 /* abstract declared */, |
| 234 checkMember(A, 'toString', inheritedFrom: Object_); | 232 interfaceMembers: false); |
| 235 | 233 |
| 236 checkMember(A, 'field', isGetter: true, | 234 checkMember(A, '==', inheritedFrom: Object_); |
| 237 type: int_, functionType: env.functionType(int_, [])); | 235 checkMember(A, 'hashCode', inheritedFrom: Object_); |
| 238 checkMember(A, 'field', isSetter: true, | 236 checkMember(A, 'noSuchMethod', inheritedFrom: Object_); |
| 239 type: int_, functionType: env.functionType(void_, [int_])); | 237 checkMember(A, 'runtimeType', inheritedFrom: Object_); |
| 240 checkMember(A, 'finalField', isGetter: true, | 238 checkMember(A, 'toString', inheritedFrom: Object_); |
| 241 type: dynamic_, functionType: env.functionType(dynamic_, [])); | 239 |
| 242 checkMember(A, 'staticField', isGetter: true, isStatic: true, | 240 checkMember(A, 'field', |
| 243 checkType: CHECK_CLASS, | 241 isGetter: true, |
| 244 type: dynamic_, functionType: env.functionType(dynamic_, [])); | 242 type: int_, |
| 245 checkMember(A, 'staticField', isSetter: true, isStatic: true, | 243 functionType: env.functionType(int_, [])); |
| 246 checkType: CHECK_CLASS, type: dynamic_, | 244 checkMember(A, 'field', |
| 247 functionType: env.functionType(void_, [dynamic_])); | 245 isSetter: true, |
| 248 | 246 type: int_, |
| 249 checkMember(A, 'getter', isGetter: true, | 247 functionType: env.functionType(void_, [int_])); |
| 250 type: int_, functionType: env.functionType(int_, [])); | 248 checkMember(A, 'finalField', |
| 251 checkMember(A, 'abstractGetter', isGetter: true, | 249 isGetter: true, |
| 252 type: dynamic_, functionType: env.functionType(dynamic_, [])); | 250 type: dynamic_, |
| 253 checkMember(A, 'setter', isSetter: true, | 251 functionType: env.functionType(dynamic_, [])); |
| 254 type: int_, functionType: env.functionType(void_, [int_])); | 252 checkMember(A, 'staticField', |
| 255 checkMember(A, 'abstractSetter', isSetter: true, | 253 isGetter: true, |
| 256 type: dynamic_, | 254 isStatic: true, |
| 257 functionType: env.functionType(dynamic_, [dynamic_])); | 255 checkType: CHECK_CLASS, |
| 258 | 256 type: dynamic_, |
| 259 checkMember(A, 'method', functionType: env.functionType(dynamic_, [])); | 257 functionType: env.functionType(dynamic_, [])); |
| 260 checkMember(A, 'abstractMethod', | 258 checkMember(A, 'staticField', |
| 261 functionType: env.functionType(dynamic_, [])); | 259 isSetter: true, |
| 262 checkMember(A, 'staticMethod', | 260 isStatic: true, |
| 263 checkType: CHECK_CLASS, | 261 checkType: CHECK_CLASS, |
| 264 isStatic: true, functionType: env.functionType(dynamic_, [])); | 262 type: dynamic_, |
| 265 | 263 functionType: env.functionType(void_, [dynamic_])); |
| 266 ClassElement B = env.getElement('B'); | 264 |
| 267 MembersCreator.computeAllClassMembers(env.resolution, B); | 265 checkMember(A, 'getter', |
| 268 InterfaceType B_this = B.thisType; | 266 isGetter: true, |
| 269 TypeVariableType B_T = B_this.typeArguments.first; | 267 type: int_, |
| 270 checkMemberCount(B_this, 4 /*inherited*/ + 4 /*non-static declared*/, | 268 functionType: env.functionType(int_, [])); |
| 271 interfaceMembers: true); | 269 checkMember(A, 'abstractGetter', |
| 272 checkMemberCount(B_this, 4 /*inherited*/ + 5 /*declared*/, | 270 isGetter: true, |
| 273 interfaceMembers: false); | 271 type: dynamic_, |
| 274 | 272 functionType: env.functionType(dynamic_, [])); |
| 275 checkMember(B_this, '==', inheritedFrom: Object_); | 273 checkMember(A, 'setter', |
| 276 checkMember(B_this, 'hashCode', inheritedFrom: Object_); | 274 isSetter: true, |
| 277 checkMember(B_this, 'noSuchMethod', inheritedFrom: Object_); | 275 type: int_, |
| 278 checkMember(B_this, 'runtimeType', inheritedFrom: Object_); | 276 functionType: env.functionType(void_, [int_])); |
| 279 | 277 checkMember(A, 'abstractSetter', |
| 280 checkMember(B_this, 'field', isGetter: true, | 278 isSetter: true, |
| 281 type: B_T, functionType: env.functionType(B_T, [])); | 279 type: dynamic_, |
| 282 checkMember(B_this, 'field', isSetter: true, | 280 functionType: env.functionType(dynamic_, [dynamic_])); |
| 283 type: B_T, functionType: env.functionType(void_, [B_T])); | 281 |
| 284 checkMember(B_this, 'method', functionType: env.functionType(void_, [B_T])); | 282 checkMember(A, 'method', functionType: env.functionType(dynamic_, [])); |
| 285 checkMember(B_this, 'staticMethod', | 283 checkMember(A, 'abstractMethod', |
| 286 checkType: CHECK_CLASS, | 284 functionType: env.functionType(dynamic_, [])); |
| 287 isStatic: true, functionType: env.functionType(dynamic_, [])); | 285 checkMember(A, 'staticMethod', |
| 288 checkMember(B_this, 'toString', | 286 checkType: CHECK_CLASS, |
| 289 functionType: env.functionType(dynamic_, [], | 287 isStatic: true, |
| 290 optionalParameters: [B_T])); | 288 functionType: env.functionType(dynamic_, [])); |
| 291 | 289 |
| 292 ClassElement C = env.getElement('C'); | 290 ClassElement B = env.getElement('B'); |
| 293 MembersCreator.computeAllClassMembers(env.resolution, C); | 291 MembersCreator.computeAllClassMembers(env.resolution, B); |
| 294 InterfaceType C_this = C.thisType; | 292 InterfaceType B_this = B.thisType; |
| 295 TypeVariableType C_S = C_this.typeArguments.first; | 293 TypeVariableType B_T = B_this.typeArguments.first; |
| 296 checkMemberCount(C_this, 8 /*inherited*/, interfaceMembers: true); | 294 checkMemberCount(B_this, 4 /*inherited*/ + 4 /*non-static declared*/, |
| 297 checkMemberCount(C_this, 8 /*inherited*/, interfaceMembers: false); | 295 interfaceMembers: true); |
| 298 InterfaceType B_S = instantiate(B, [C_S]); | 296 checkMemberCount(B_this, 4 /*inherited*/ + 5 /*declared*/, |
| 299 | 297 interfaceMembers: false); |
| 300 checkMember(C_this, '==', inheritedFrom: Object_); | 298 |
| 301 checkMember(C_this, 'hashCode', inheritedFrom: Object_); | 299 checkMember(B_this, '==', inheritedFrom: Object_); |
| 302 checkMember(C_this, 'noSuchMethod', inheritedFrom: Object_); | 300 checkMember(B_this, 'hashCode', inheritedFrom: Object_); |
| 303 checkMember(C_this, 'runtimeType', inheritedFrom: Object_); | 301 checkMember(B_this, 'noSuchMethod', inheritedFrom: Object_); |
| 304 | 302 checkMember(B_this, 'runtimeType', inheritedFrom: Object_); |
| 305 checkMember(C_this, 'field', isGetter: true, | 303 |
| 306 declarer: B_S, | 304 checkMember(B_this, 'field', |
| 307 type: C_S, functionType: env.functionType(C_S, [])); | 305 isGetter: true, type: B_T, functionType: env.functionType(B_T, [])); |
| 308 checkMember(C_this, 'field', isSetter: true, | 306 checkMember(B_this, 'field', |
| 309 declarer: B_S, | 307 isSetter: true, |
| 310 type: C_S, functionType: env.functionType(void_, [C_S])); | 308 type: B_T, |
| 311 checkMember(C_this, 'method', | 309 functionType: env.functionType(void_, [B_T])); |
| 312 declarer: B_S, | 310 checkMember(B_this, 'method', |
| 313 functionType: env.functionType(void_, [C_S])); | 311 functionType: env.functionType(void_, [B_T])); |
| 314 checkMember(C_this, 'toString', | 312 checkMember(B_this, 'staticMethod', |
| 315 declarer: B_S, | 313 checkType: CHECK_CLASS, |
| 316 functionType: env.functionType(dynamic_, [], | 314 isStatic: true, |
| 317 optionalParameters: [C_S])); | 315 functionType: env.functionType(dynamic_, [])); |
| 318 | 316 checkMember(B_this, 'toString', |
| 319 InterfaceType D = env['D']; | 317 functionType: |
| 320 MembersCreator.computeAllClassMembers(env.resolution, D.element); | 318 env.functionType(dynamic_, [], optionalParameters: [B_T])); |
| 321 checkMemberCount(D, 8 /*inherited*/, interfaceMembers: true); | 319 |
| 322 checkMemberCount(D, 8 /*inherited*/, interfaceMembers: false); | 320 ClassElement C = env.getElement('C'); |
| 323 InterfaceType B_int = instantiate(B, [int_]); | 321 MembersCreator.computeAllClassMembers(env.resolution, C); |
| 324 | 322 InterfaceType C_this = C.thisType; |
| 325 checkMember(D, '==', inheritedFrom: Object_); | 323 TypeVariableType C_S = C_this.typeArguments.first; |
| 326 checkMember(D, 'hashCode', inheritedFrom: Object_); | 324 checkMemberCount(C_this, 8 /*inherited*/, interfaceMembers: true); |
| 327 checkMember(D, 'noSuchMethod', inheritedFrom: Object_); | 325 checkMemberCount(C_this, 8 /*inherited*/, interfaceMembers: false); |
| 328 checkMember(D, 'runtimeType', inheritedFrom: Object_); | 326 InterfaceType B_S = instantiate(B, [C_S]); |
| 329 | 327 |
| 330 checkMember(D, 'field', isGetter: true, | 328 checkMember(C_this, '==', inheritedFrom: Object_); |
| 331 declarer: B_int, | 329 checkMember(C_this, 'hashCode', inheritedFrom: Object_); |
| 332 type: int_, functionType: env.functionType(int_, [])); | 330 checkMember(C_this, 'noSuchMethod', inheritedFrom: Object_); |
| 333 checkMember(D, 'field', isSetter: true, | 331 checkMember(C_this, 'runtimeType', inheritedFrom: Object_); |
| 334 declarer: B_int, | 332 |
| 335 type: int_, functionType: env.functionType(void_, [int_])); | 333 checkMember(C_this, 'field', |
| 336 checkMember(D, 'method', | 334 isGetter: true, |
| 337 declarer: B_int, | 335 declarer: B_S, |
| 338 functionType: env.functionType(void_, [int_])); | 336 type: C_S, |
| 339 checkMember(D, 'toString', | 337 functionType: env.functionType(C_S, [])); |
| 340 declarer: B_int, | 338 checkMember(C_this, 'field', |
| 341 functionType: env.functionType(dynamic_, [], | 339 isSetter: true, |
| 342 optionalParameters: [int_])); | 340 declarer: B_S, |
| 343 | 341 type: C_S, |
| 344 InterfaceType E = env['E']; | 342 functionType: env.functionType(void_, [C_S])); |
| 345 MembersCreator.computeAllClassMembers(env.resolution, E.element); | 343 checkMember(C_this, 'method', |
| 346 checkMemberCount(E, 8 /*inherited*/, interfaceMembers: true); | 344 declarer: B_S, functionType: env.functionType(void_, [C_S])); |
| 347 checkMemberCount(E, 8 /*inherited*/, interfaceMembers: false); | 345 checkMember(C_this, 'toString', |
| 348 | 346 declarer: B_S, |
| 349 checkMember(E, '==', inheritedFrom: Object_); | 347 functionType: |
| 350 checkMember(E, 'hashCode', inheritedFrom: Object_); | 348 env.functionType(dynamic_, [], optionalParameters: [C_S])); |
| 351 checkMember(E, 'noSuchMethod', inheritedFrom: Object_); | 349 |
| 352 checkMember(E, 'runtimeType', inheritedFrom: Object_); | 350 InterfaceType D = env['D']; |
| 353 | 351 MembersCreator.computeAllClassMembers(env.resolution, D.element); |
| 354 checkMember(E, 'field', isGetter: true, | 352 checkMemberCount(D, 8 /*inherited*/, interfaceMembers: true); |
| 355 declarer: B_int, | 353 checkMemberCount(D, 8 /*inherited*/, interfaceMembers: false); |
| 356 type: int_, functionType: env.functionType(int_, [])); | 354 InterfaceType B_int = instantiate(B, [int_]); |
| 357 checkMember(E, 'field', isSetter: true, | 355 |
| 358 declarer: B_int, | 356 checkMember(D, '==', inheritedFrom: Object_); |
| 359 type: int_, functionType: env.functionType(void_, [int_])); | 357 checkMember(D, 'hashCode', inheritedFrom: Object_); |
| 360 checkMember(E, 'method', | 358 checkMember(D, 'noSuchMethod', inheritedFrom: Object_); |
| 361 declarer: B_int, | 359 checkMember(D, 'runtimeType', inheritedFrom: Object_); |
| 362 functionType: env.functionType(void_, [int_])); | 360 |
| 363 checkMember(E, 'toString', | 361 checkMember(D, 'field', |
| 364 declarer: B_int, | 362 isGetter: true, |
| 365 functionType: env.functionType(dynamic_, [], | 363 declarer: B_int, |
| 366 optionalParameters: [int_])); | 364 type: int_, |
| 367 })); | 365 functionType: env.functionType(int_, [])); |
| 366 checkMember(D, 'field', |
| 367 isSetter: true, |
| 368 declarer: B_int, |
| 369 type: int_, |
| 370 functionType: env.functionType(void_, [int_])); |
| 371 checkMember(D, 'method', |
| 372 declarer: B_int, functionType: env.functionType(void_, [int_])); |
| 373 checkMember(D, 'toString', |
| 374 declarer: B_int, |
| 375 functionType: |
| 376 env.functionType(dynamic_, [], optionalParameters: [int_])); |
| 377 |
| 378 InterfaceType E = env['E']; |
| 379 MembersCreator.computeAllClassMembers(env.resolution, E.element); |
| 380 checkMemberCount(E, 8 /*inherited*/, interfaceMembers: true); |
| 381 checkMemberCount(E, 8 /*inherited*/, interfaceMembers: false); |
| 382 |
| 383 checkMember(E, '==', inheritedFrom: Object_); |
| 384 checkMember(E, 'hashCode', inheritedFrom: Object_); |
| 385 checkMember(E, 'noSuchMethod', inheritedFrom: Object_); |
| 386 checkMember(E, 'runtimeType', inheritedFrom: Object_); |
| 387 |
| 388 checkMember(E, 'field', |
| 389 isGetter: true, |
| 390 declarer: B_int, |
| 391 type: int_, |
| 392 functionType: env.functionType(int_, [])); |
| 393 checkMember(E, 'field', |
| 394 isSetter: true, |
| 395 declarer: B_int, |
| 396 type: int_, |
| 397 functionType: env.functionType(void_, [int_])); |
| 398 checkMember(E, 'method', |
| 399 declarer: B_int, functionType: env.functionType(void_, [int_])); |
| 400 checkMember(E, 'toString', |
| 401 declarer: B_int, |
| 402 functionType: |
| 403 env.functionType(dynamic_, [], optionalParameters: [int_])); |
| 404 })); |
| 368 } | 405 } |
| 369 | 406 |
| 370 void testInterfaceMembers() { | 407 void testInterfaceMembers() { |
| 371 asyncTest(() => TypeEnvironment.create(r""" | 408 asyncTest(() => TypeEnvironment.create(r""" |
| 372 abstract class A { | 409 abstract class A { |
| 373 num method1(); | 410 num method1(); |
| 374 void method2(); | 411 void method2(); |
| 375 void method3(); | 412 void method3(); |
| 376 void method4(); | 413 void method4(); |
| 377 method5(a); | 414 method5(a); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 406 set setter2(num _); | 443 set setter2(num _); |
| 407 void set setter3(int _); | 444 void set setter3(int _); |
| 408 getterAndMethod(); | 445 getterAndMethod(); |
| 409 } | 446 } |
| 410 abstract class C { | 447 abstract class C { |
| 411 int method3(); | 448 int method3(); |
| 412 num method4(); | 449 num method4(); |
| 413 } | 450 } |
| 414 abstract class D implements A, B, C {} | 451 abstract class D implements A, B, C {} |
| 415 """).then((env) { | 452 """).then((env) { |
| 453 DynamicType dynamic_ = env['dynamic']; |
| 454 VoidType void_ = env['void']; |
| 455 InterfaceType num_ = env['num']; |
| 456 InterfaceType int_ = env['int']; |
| 416 | 457 |
| 417 DynamicType dynamic_ = env['dynamic']; | 458 InterfaceType A = env['A']; |
| 418 VoidType void_ = env['void']; | 459 InterfaceType B = env['B']; |
| 419 InterfaceType num_ = env['num']; | 460 InterfaceType C = env['C']; |
| 420 InterfaceType int_ = env['int']; | 461 InterfaceType D = env['D']; |
| 421 | 462 |
| 422 InterfaceType A = env['A']; | 463 // Ensure that members have been computed on all classes. |
| 423 InterfaceType B = env['B']; | 464 MembersCreator.computeAllClassMembers(env.resolution, D.element); |
| 424 InterfaceType C = env['C']; | |
| 425 InterfaceType D = env['D']; | |
| 426 | 465 |
| 427 // Ensure that members have been computed on all classes. | 466 // A: num method1() |
| 428 MembersCreator.computeAllClassMembers(env.resolution, D.element); | 467 // B: int method1() |
| 468 // D: dynamic method1() -- synthesized from A and B. |
| 469 checkMember(D, 'method1', |
| 470 synthesizedFrom: [A, B], |
| 471 functionType: env.functionType(dynamic_, []), |
| 472 checkType: NO_CLASS_MEMBER); |
| 429 | 473 |
| 430 // A: num method1() | 474 // A: void method2() |
| 431 // B: int method1() | 475 // B: int method2() |
| 432 // D: dynamic method1() -- synthesized from A and B. | 476 // D: int method2() -- inherited from B |
| 433 checkMember(D, 'method1', | 477 checkMember(D, 'method2', inheritedFrom: B, checkType: NO_CLASS_MEMBER); |
| 434 synthesizedFrom: [A, B], | |
| 435 functionType: env.functionType(dynamic_ , []), | |
| 436 checkType: NO_CLASS_MEMBER); | |
| 437 | 478 |
| 438 // A: void method2() | 479 // A: void method3() |
| 439 // B: int method2() | 480 // B: num method3() |
| 440 // D: int method2() -- inherited from B | 481 // C: int method3() |
| 441 checkMember(D, 'method2', inheritedFrom: B, checkType: NO_CLASS_MEMBER); | 482 // D: dynamic method3() -- synthesized from A, B, and C. |
| 483 checkMember(D, 'method3', |
| 484 synthesizedFrom: [A, B, C], |
| 485 functionType: env.functionType(dynamic_, []), |
| 486 checkType: NO_CLASS_MEMBER); |
| 442 | 487 |
| 443 // A: void method3() | 488 // A: void method4() |
| 444 // B: num method3() | 489 // B: num method4() |
| 445 // C: int method3() | 490 // C: num method4() |
| 446 // D: dynamic method3() -- synthesized from A, B, and C. | 491 // D: num method4() -- synthesized from B and C. |
| 447 checkMember(D, 'method3', | 492 checkMember(D, 'method4', |
| 448 synthesizedFrom: [A, B, C], | 493 synthesizedFrom: [B, C], |
| 449 functionType: env.functionType(dynamic_ , []), | 494 functionType: env.functionType(num_, []), |
| 450 checkType: NO_CLASS_MEMBER); | 495 checkType: NO_CLASS_MEMBER); |
| 451 | 496 |
| 452 // A: void method4() | 497 // A: method5(a) |
| 453 // B: num method4() | 498 // B: method5([a]) |
| 454 // C: num method4() | 499 // D: method5([a]) -- inherited from B |
| 455 // D: num method4() -- synthesized from B and C. | 500 checkMember(D, 'method5', inheritedFrom: B, checkType: NO_CLASS_MEMBER); |
| 456 checkMember(D, 'method4', | |
| 457 synthesizedFrom: [B, C], | |
| 458 functionType: env.functionType(num_, []), | |
| 459 checkType: NO_CLASS_MEMBER); | |
| 460 | 501 |
| 461 // A: method5(a) | 502 // A: method6(a) |
| 462 // B: method5([a]) | 503 // B: method6([a, b]) |
| 463 // D: method5([a]) -- inherited from B | 504 // D: method6([a, b]) -- inherited from B |
| 464 checkMember(D, 'method5', inheritedFrom: B, checkType: NO_CLASS_MEMBER); | 505 checkMember(D, 'method6', inheritedFrom: B, checkType: NO_CLASS_MEMBER); |
| 465 | 506 |
| 466 // A: method6(a) | 507 // A: method7(a) |
| 467 // B: method6([a, b]) | 508 // B: method7(a, [b]) |
| 468 // D: method6([a, b]) -- inherited from B | 509 // D: method7(a, [b]) -- inherited from B |
| 469 checkMember(D, 'method6', inheritedFrom: B, checkType: NO_CLASS_MEMBER); | 510 checkMember(D, 'method7', inheritedFrom: B, checkType: NO_CLASS_MEMBER); |
| 470 | 511 |
| 471 // A: method7(a) | 512 // A: method8(a, b) |
| 472 // B: method7(a, [b]) | 513 // B: method8([a]) |
| 473 // D: method7(a, [b]) -- inherited from B | 514 // D: method8([a, b]) -- synthesized from A and B. |
| 474 checkMember(D, 'method7', inheritedFrom: B, checkType: NO_CLASS_MEMBER); | 515 checkMember(D, 'method8', |
| 516 synthesizedFrom: [A, B], |
| 517 functionType: env.functionType(dynamic_, [], |
| 518 optionalParameters: [dynamic_, dynamic_]), |
| 519 checkType: NO_CLASS_MEMBER); |
| 475 | 520 |
| 476 // A: method8(a, b) | 521 // A: method9(a, b, c) |
| 477 // B: method8([a]) | 522 // B: method9(a, [b]) |
| 478 // D: method8([a, b]) -- synthesized from A and B. | 523 // D: method9(a, [b, c]) -- synthesized from A and B. |
| 479 checkMember(D, 'method8', | 524 checkMember(D, 'method9', |
| 480 synthesizedFrom: [A, B], | 525 synthesizedFrom: [A, B], |
| 481 functionType: env.functionType( | 526 functionType: env.functionType(dynamic_, [dynamic_], |
| 482 dynamic_, [], optionalParameters: [dynamic_, dynamic_]), | 527 optionalParameters: [dynamic_, dynamic_]), |
| 483 checkType: NO_CLASS_MEMBER); | 528 checkType: NO_CLASS_MEMBER); |
| 484 | 529 |
| 485 // A: method9(a, b, c) | 530 // A: method10(a, {b, c}) |
| 486 // B: method9(a, [b]) | 531 // B: method10(a, {c, d}) |
| 487 // D: method9(a, [b, c]) -- synthesized from A and B. | 532 // D: method10(a, {b, c, d}) -- synthesized from A and B. |
| 488 checkMember(D, 'method9', | 533 checkMember(D, 'method10', |
| 489 synthesizedFrom: [A, B], | 534 synthesizedFrom: [A, B], |
| 490 functionType: env.functionType( | 535 functionType: env.functionType(dynamic_, [dynamic_], |
| 491 dynamic_, [dynamic_], optionalParameters: [dynamic_, dynamic_]), | 536 namedParameters: {'b': dynamic_, 'c': dynamic_, 'd': dynamic_}), |
| 492 checkType: NO_CLASS_MEMBER); | 537 checkType: NO_CLASS_MEMBER); |
| 493 | 538 |
| 494 // A: method10(a, {b, c}) | 539 // A: method11(a, {b, c}) |
| 495 // B: method10(a, {c, d}) | 540 // B: method11(a, b, {c, d}) |
| 496 // D: method10(a, {b, c, d}) -- synthesized from A and B. | 541 // D: method11(a, [b], {c, d}) -- synthesized from A and B. |
| 497 checkMember(D, 'method10', | 542 // TODO(johnniwinther): Change to check synthesized member when function |
| 498 synthesizedFrom: [A, B], | 543 // types with both optional and named parameters are supported. |
| 499 functionType: env.functionType(dynamic_, [dynamic_], | 544 Expect.isNull(getMember(D, 'method11')); |
| 500 namedParameters: {'b': dynamic_, | 545 /*checkMember(D, 'method11', |
| 501 'c': dynamic_, | |
| 502 'd': dynamic_}), | |
| 503 checkType: NO_CLASS_MEMBER); | |
| 504 | |
| 505 // A: method11(a, {b, c}) | |
| 506 // B: method11(a, b, {c, d}) | |
| 507 // D: method11(a, [b], {c, d}) -- synthesized from A and B. | |
| 508 // TODO(johnniwinther): Change to check synthesized member when function | |
| 509 // types with both optional and named parameters are supported. | |
| 510 Expect.isNull(getMember(D, 'method11')); | |
| 511 /*checkMember(D, 'method11', | |
| 512 synthesizedFrom: [A, B], | 546 synthesizedFrom: [A, B], |
| 513 functionType: env.functionType(dynamic_, [dynamic_], | 547 functionType: env.functionType(dynamic_, [dynamic_], |
| 514 optionalParameters: [dynamic_], | 548 optionalParameters: [dynamic_], |
| 515 namedParameters: {'c': dynamic_, | 549 namedParameters: {'c': dynamic_, |
| 516 'd': dynamic_,}), | 550 'd': dynamic_,}), |
| 517 checkType: NO_CLASS_MEMBER);*/ | 551 checkType: NO_CLASS_MEMBER);*/ |
| 518 | 552 |
| 519 // A: num get getter1 | 553 // A: num get getter1 |
| 520 // B: num get getter1 | 554 // B: num get getter1 |
| 521 // D: num get getter1 -- synthesized from A and B. | 555 // D: num get getter1 -- synthesized from A and B. |
| 522 checkMember(D, 'getter1', | 556 checkMember(D, 'getter1', |
| 523 isGetter: true, | 557 isGetter: true, |
| 524 synthesizedFrom: [A, B], type: num_, | 558 synthesizedFrom: [A, B], |
| 525 functionType: env.functionType(num_ , []), | 559 type: num_, |
| 526 checkType: NO_CLASS_MEMBER); | 560 functionType: env.functionType(num_, []), |
| 561 checkType: NO_CLASS_MEMBER); |
| 527 | 562 |
| 528 // A: num get getter2 | 563 // A: num get getter2 |
| 529 // B: int get getter2 | 564 // B: int get getter2 |
| 530 // D: dynamic get getter2 -- synthesized from A and B. | 565 // D: dynamic get getter2 -- synthesized from A and B. |
| 531 checkMember(D, 'getter2', | 566 checkMember(D, 'getter2', |
| 532 isGetter: true, | 567 isGetter: true, |
| 533 synthesizedFrom: [A, B], type: dynamic_, | 568 synthesizedFrom: [A, B], |
| 534 functionType: env.functionType(dynamic_ , []), | 569 type: dynamic_, |
| 535 checkType: NO_CLASS_MEMBER); | 570 functionType: env.functionType(dynamic_, []), |
| 571 checkType: NO_CLASS_MEMBER); |
| 536 | 572 |
| 537 // A: void set setter1(num _) | 573 // A: void set setter1(num _) |
| 538 // B: void set setter1(num _) | 574 // B: void set setter1(num _) |
| 539 // D: void set setter1(num _) -- synthesized from A and B. | 575 // D: void set setter1(num _) -- synthesized from A and B. |
| 540 checkMember(D, 'setter1', | 576 checkMember(D, 'setter1', |
| 541 isSetter: true, | 577 isSetter: true, |
| 542 synthesizedFrom: [A, B], type: num_, | 578 synthesizedFrom: [A, B], |
| 543 functionType: env.functionType(void_ , [num_]), | 579 type: num_, |
| 544 checkType: NO_CLASS_MEMBER); | 580 functionType: env.functionType(void_, [num_]), |
| 581 checkType: NO_CLASS_MEMBER); |
| 545 | 582 |
| 546 // A: void set setter2(num _) | 583 // A: void set setter2(num _) |
| 547 // B: set setter2(num _) | 584 // B: set setter2(num _) |
| 548 // D: dynamic set setter2(dynamic _) -- synthesized from A and B. | 585 // D: dynamic set setter2(dynamic _) -- synthesized from A and B. |
| 549 checkMember(D, 'setter2', | 586 checkMember(D, 'setter2', |
| 550 isSetter: true, | 587 isSetter: true, |
| 551 synthesizedFrom: [A, B], type: dynamic_, | 588 synthesizedFrom: [A, B], |
| 552 functionType: env.functionType(dynamic_ , [dynamic_]), | 589 type: dynamic_, |
| 553 checkType: NO_CLASS_MEMBER); | 590 functionType: env.functionType(dynamic_, [dynamic_]), |
| 591 checkType: NO_CLASS_MEMBER); |
| 554 | 592 |
| 555 // A: void set setter3(num _) | 593 // A: void set setter3(num _) |
| 556 // B: void set setter3(int _) | 594 // B: void set setter3(int _) |
| 557 // D: dynamic set setter3(dynamic _) -- synthesized from A and B. | 595 // D: dynamic set setter3(dynamic _) -- synthesized from A and B. |
| 558 checkMember(D, 'setter3', | 596 checkMember(D, 'setter3', |
| 559 isSetter: true, | 597 isSetter: true, |
| 560 synthesizedFrom: [A, B], type: dynamic_, | 598 synthesizedFrom: [A, B], |
| 561 functionType: env.functionType(dynamic_ , [dynamic_]), | 599 type: dynamic_, |
| 562 checkType: NO_CLASS_MEMBER); | 600 functionType: env.functionType(dynamic_, [dynamic_]), |
| 601 checkType: NO_CLASS_MEMBER); |
| 563 | 602 |
| 564 // A: get getterAndMethod | 603 // A: get getterAndMethod |
| 565 // B: getterAndMethod() | 604 // B: getterAndMethod() |
| 566 // D: nothing inherited | 605 // D: nothing inherited |
| 567 checkMember(D, 'getterAndMethod', | 606 checkMember(D, 'getterAndMethod', |
| 568 erroneousFrom: [A, B], | 607 erroneousFrom: [A, B], checkType: NO_CLASS_MEMBER); |
| 569 checkType: NO_CLASS_MEMBER); | 608 })); |
| 570 })); | |
| 571 } | 609 } |
| 572 | 610 |
| 573 void testClassVsInterfaceMembers() { | 611 void testClassVsInterfaceMembers() { |
| 574 asyncTest(() => TypeEnvironment.create(r""" | 612 asyncTest(() => TypeEnvironment.create(r""" |
| 575 class A { | 613 class A { |
| 576 method1() {} | 614 method1() {} |
| 577 method2() {} | 615 method2() {} |
| 578 } | 616 } |
| 579 abstract class B { | 617 abstract class B { |
| 580 method1(); | 618 method1(); |
| 581 method2(a); | 619 method2(a); |
| 582 } | 620 } |
| 583 abstract class C extends A implements B {} | 621 abstract class C extends A implements B {} |
| 584 """).then((env) { | 622 """).then((env) { |
| 623 DynamicType dynamic_ = env['dynamic']; |
| 624 VoidType void_ = env['void']; |
| 625 InterfaceType num_ = env['num']; |
| 626 InterfaceType int_ = env['int']; |
| 585 | 627 |
| 586 DynamicType dynamic_ = env['dynamic']; | 628 InterfaceType A = env['A']; |
| 587 VoidType void_ = env['void']; | 629 InterfaceType B = env['B']; |
| 588 InterfaceType num_ = env['num']; | 630 InterfaceType C = env['C']; |
| 589 InterfaceType int_ = env['int']; | |
| 590 | 631 |
| 591 InterfaceType A = env['A']; | 632 // Ensure that members have been computed on all classes. |
| 592 InterfaceType B = env['B']; | 633 MembersCreator.computeAllClassMembers(env.resolution, C.element); |
| 593 InterfaceType C = env['C']; | |
| 594 | 634 |
| 595 // Ensure that members have been computed on all classes. | 635 // A: method1() |
| 596 MembersCreator.computeAllClassMembers(env.resolution, C.element); | 636 // B: method1() |
| 637 // C class: method1() -- inherited from A. |
| 638 // C interface: dynamic method1() -- synthesized from A and B. |
| 639 MemberSignature interfaceMember = checkMember(C, 'method1', |
| 640 checkType: CHECK_INTERFACE, |
| 641 synthesizedFrom: [A, B], |
| 642 functionType: env.functionType(dynamic_, [])); |
| 643 MemberSignature classMember = |
| 644 checkMember(C, 'method1', checkType: CHECK_CLASS, inheritedFrom: A); |
| 645 Expect.notEquals(interfaceMember, classMember); |
| 597 | 646 |
| 598 // A: method1() | 647 // A: method2() |
| 599 // B: method1() | 648 // B: method2(a) |
| 600 // C class: method1() -- inherited from A. | 649 // C class: method2() -- inherited from A. |
| 601 // C interface: dynamic method1() -- synthesized from A and B. | 650 // C interface: dynamic method2([a]) -- synthesized from A and B. |
| 602 MemberSignature interfaceMember = | 651 interfaceMember = checkMember(C, 'method2', |
| 603 checkMember(C, 'method1', checkType: CHECK_INTERFACE, | 652 checkType: CHECK_INTERFACE, |
| 604 synthesizedFrom: [A, B], | 653 synthesizedFrom: [A, B], |
| 605 functionType: env.functionType(dynamic_ , [])); | 654 functionType: |
| 606 MemberSignature classMember = | 655 env.functionType(dynamic_, [], optionalParameters: [dynamic_])); |
| 607 checkMember(C, 'method1', checkType: CHECK_CLASS, inheritedFrom: A); | 656 classMember = |
| 608 Expect.notEquals(interfaceMember, classMember); | 657 checkMember(C, 'method2', checkType: CHECK_CLASS, inheritedFrom: A); |
| 609 | 658 Expect.notEquals(interfaceMember, classMember); |
| 610 // A: method2() | 659 })); |
| 611 // B: method2(a) | |
| 612 // C class: method2() -- inherited from A. | |
| 613 // C interface: dynamic method2([a]) -- synthesized from A and B. | |
| 614 interfaceMember = | |
| 615 checkMember(C, 'method2', checkType: CHECK_INTERFACE, | |
| 616 synthesizedFrom: [A, B], | |
| 617 functionType: env.functionType(dynamic_ , [], | |
| 618 optionalParameters: [dynamic_])); | |
| 619 classMember = | |
| 620 checkMember(C, 'method2', checkType: CHECK_CLASS, inheritedFrom: A); | |
| 621 Expect.notEquals(interfaceMember, classMember); | |
| 622 })); | |
| 623 } | 660 } |
| 624 | 661 |
| 625 | |
| 626 void testMixinMembers() { | 662 void testMixinMembers() { |
| 627 asyncTest(() => TypeEnvironment.create(r""" | 663 asyncTest(() => TypeEnvironment.create(r""" |
| 628 class A<T> { | 664 class A<T> { |
| 629 method1() {} | 665 method1() {} |
| 630 method2() {} | 666 method2() {} |
| 631 method3(T a) {} | 667 method3(T a) {} |
| 632 method4(T a) {} | 668 method4(T a) {} |
| 633 } | 669 } |
| 634 abstract class B<S> { | 670 abstract class B<S> { |
| 635 method1(); | 671 method1(); |
| 636 method2(a); | 672 method2(a); |
| 637 method3(S a) {} | 673 method3(S a) {} |
| 638 } | 674 } |
| 639 abstract class C<U, V> extends Object with A<U> implements B<V> {} | 675 abstract class C<U, V> extends Object with A<U> implements B<V> {} |
| 640 """).then((env) { | 676 """).then((env) { |
| 677 DynamicType dynamic_ = env['dynamic']; |
| 678 VoidType void_ = env['void']; |
| 679 InterfaceType num_ = env['num']; |
| 680 InterfaceType int_ = env['int']; |
| 641 | 681 |
| 642 DynamicType dynamic_ = env['dynamic']; | 682 ClassElement A = env.getElement('A'); |
| 643 VoidType void_ = env['void']; | 683 ClassElement B = env.getElement('B'); |
| 644 InterfaceType num_ = env['num']; | 684 ClassElement C = env.getElement('C'); |
| 645 InterfaceType int_ = env['int']; | 685 InterfaceType C_this = C.thisType; |
| 686 TypeVariableType C_U = C_this.typeArguments[0]; |
| 687 TypeVariableType C_V = C_this.typeArguments[1]; |
| 688 InterfaceType A_U = instantiate(A, [C_U]); |
| 689 InterfaceType B_V = instantiate(B, [C_V]); |
| 646 | 690 |
| 647 ClassElement A = env.getElement('A'); | 691 // Ensure that members have been computed on all classes. |
| 648 ClassElement B = env.getElement('B'); | 692 MembersCreator.computeAllClassMembers(env.resolution, C); |
| 649 ClassElement C = env.getElement('C'); | |
| 650 InterfaceType C_this = C.thisType; | |
| 651 TypeVariableType C_U = C_this.typeArguments[0]; | |
| 652 TypeVariableType C_V = C_this.typeArguments[1]; | |
| 653 InterfaceType A_U = instantiate(A, [C_U]); | |
| 654 InterfaceType B_V = instantiate(B, [C_V]); | |
| 655 | 693 |
| 656 // Ensure that members have been computed on all classes. | 694 // A: method1() |
| 657 MembersCreator.computeAllClassMembers(env.resolution, C); | 695 // B: method1() |
| 696 // C class: method1() -- inherited from A. |
| 697 // C interface: dynamic method1() -- synthesized from A and B. |
| 698 MemberSignature interfaceMember = checkMember(C_this, 'method1', |
| 699 checkType: CHECK_INTERFACE, |
| 700 synthesizedFrom: [A_U, B_V], |
| 701 functionType: env.functionType(dynamic_, [])); |
| 702 MemberSignature classMember = checkMember(C_this, 'method1', |
| 703 checkType: CHECK_CLASS, inheritedFrom: A_U); |
| 704 Expect.notEquals(interfaceMember, classMember); |
| 658 | 705 |
| 659 // A: method1() | 706 // A: method2() |
| 660 // B: method1() | 707 // B: method2(a) |
| 661 // C class: method1() -- inherited from A. | 708 // C class: method2() -- inherited from A. |
| 662 // C interface: dynamic method1() -- synthesized from A and B. | 709 // C interface: dynamic method2([a]) -- synthesized from A and B. |
| 663 MemberSignature interfaceMember = | 710 interfaceMember = checkMember(C_this, 'method2', |
| 664 checkMember(C_this, 'method1', checkType: CHECK_INTERFACE, | 711 checkType: CHECK_INTERFACE, |
| 665 synthesizedFrom: [A_U, B_V], | 712 synthesizedFrom: [A_U, B_V], |
| 666 functionType: env.functionType(dynamic_ , [])); | 713 functionType: |
| 667 MemberSignature classMember = | 714 env.functionType(dynamic_, [], optionalParameters: [dynamic_])); |
| 668 checkMember(C_this, 'method1', checkType: CHECK_CLASS, | 715 classMember = checkMember(C_this, 'method2', |
| 669 inheritedFrom: A_U); | 716 checkType: CHECK_CLASS, inheritedFrom: A_U); |
| 670 Expect.notEquals(interfaceMember, classMember); | 717 Expect.notEquals(interfaceMember, classMember); |
| 671 | 718 |
| 672 // A: method2() | 719 // A: method3(U a) |
| 673 // B: method2(a) | 720 // B: method3(V a) |
| 674 // C class: method2() -- inherited from A. | 721 // C class: method3(U a) -- inherited from A. |
| 675 // C interface: dynamic method2([a]) -- synthesized from A and B. | 722 // C interface: dynamic method3(a) -- synthesized from A and B. |
| 676 interfaceMember = | 723 interfaceMember = checkMember(C_this, 'method3', |
| 677 checkMember(C_this, 'method2', checkType: CHECK_INTERFACE, | 724 checkType: CHECK_INTERFACE, |
| 678 synthesizedFrom: [A_U, B_V], | 725 synthesizedFrom: [A_U, B_V], |
| 679 functionType: env.functionType(dynamic_ , [], | 726 functionType: env.functionType(dynamic_, [dynamic_])); |
| 680 optionalParameters: [dynamic_])); | 727 classMember = checkMember(C_this, 'method3', |
| 681 classMember = | 728 checkType: CHECK_CLASS, inheritedFrom: A_U); |
| 682 checkMember(C_this, 'method2', checkType: CHECK_CLASS, | 729 Expect.notEquals(interfaceMember, classMember); |
| 683 inheritedFrom: A_U); | |
| 684 Expect.notEquals(interfaceMember, classMember); | |
| 685 | 730 |
| 686 // A: method3(U a) | 731 // A: method4(U a) |
| 687 // B: method3(V a) | 732 // B: -- |
| 688 // C class: method3(U a) -- inherited from A. | 733 // C class: method4(U a) -- inherited from A. |
| 689 // C interface: dynamic method3(a) -- synthesized from A and B. | 734 // C interface: method4(U a) -- inherited from A. |
| 690 interfaceMember = | 735 checkMember(C_this, 'method4', |
| 691 checkMember(C_this, 'method3', checkType: CHECK_INTERFACE, | 736 checkType: ALSO_CLASS_MEMBER, inheritedFrom: A_U); |
| 692 synthesizedFrom: [A_U, B_V], | 737 })); |
| 693 functionType: env.functionType(dynamic_ , [dynamic_])); | |
| 694 classMember = | |
| 695 checkMember(C_this, 'method3', checkType: CHECK_CLASS, | |
| 696 inheritedFrom: A_U); | |
| 697 Expect.notEquals(interfaceMember, classMember); | |
| 698 | |
| 699 // A: method4(U a) | |
| 700 // B: -- | |
| 701 // C class: method4(U a) -- inherited from A. | |
| 702 // C interface: method4(U a) -- inherited from A. | |
| 703 checkMember(C_this, 'method4', checkType: ALSO_CLASS_MEMBER, | |
| 704 inheritedFrom: A_U); | |
| 705 })); | |
| 706 } | 738 } |
| 707 | 739 |
| 708 void testMixinMembersWithoutImplements() { | 740 void testMixinMembersWithoutImplements() { |
| 709 asyncTest(() => TypeEnvironment.create(r""" | 741 asyncTest(() => TypeEnvironment.create(r""" |
| 710 abstract class A { | 742 abstract class A { |
| 711 m(); | 743 m(); |
| 712 } | 744 } |
| 713 abstract class B implements A { | 745 abstract class B implements A { |
| 714 } | 746 } |
| 715 abstract class C extends Object with B {} | 747 abstract class C extends Object with B {} |
| 716 """).then((env) { | 748 """).then((env) { |
| 749 DynamicType dynamic_ = env['dynamic']; |
| 750 VoidType void_ = env['void']; |
| 751 InterfaceType num_ = env['num']; |
| 752 InterfaceType int_ = env['int']; |
| 717 | 753 |
| 718 DynamicType dynamic_ = env['dynamic']; | 754 InterfaceType A = env['A']; |
| 719 VoidType void_ = env['void']; | 755 InterfaceType B = env['B']; |
| 720 InterfaceType num_ = env['num']; | 756 InterfaceType C = env['C']; |
| 721 InterfaceType int_ = env['int']; | |
| 722 | 757 |
| 723 InterfaceType A = env['A']; | 758 // Ensure that members have been computed on all classes. |
| 724 InterfaceType B = env['B']; | 759 MembersCreator.computeAllClassMembers(env.resolution, C.element); |
| 725 InterfaceType C = env['C']; | |
| 726 | 760 |
| 727 // Ensure that members have been computed on all classes. | 761 checkMember(C, 'm', |
| 728 MembersCreator.computeAllClassMembers(env.resolution, C.element); | 762 checkType: NO_CLASS_MEMBER, |
| 729 | 763 inheritedFrom: A, |
| 730 checkMember(C, 'm', checkType: NO_CLASS_MEMBER, | 764 functionType: env.functionType(dynamic_, [])); |
| 731 inheritedFrom: A, | 765 })); |
| 732 functionType: env.functionType(dynamic_ , [])); | 766 } |
| 733 })); | |
| 734 } | |
| OLD | NEW |