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