OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 resolution.compute_members; | 5 library resolution.compute_members; |
6 | 6 |
7 import '../elements/elements.dart' | 7 import '../elements/elements.dart' |
8 show Element, | 8 show Element, |
9 Name, | 9 Name, |
10 PublicName, | 10 PublicName, |
(...skipping 14 matching lines...) Expand all Loading... |
25 part 'member_impl.dart'; | 25 part 'member_impl.dart'; |
26 | 26 |
27 class MembersCreator { | 27 class MembersCreator { |
28 final ClassElement cls; | 28 final ClassElement cls; |
29 final Compiler compiler; | 29 final Compiler compiler; |
30 | 30 |
31 Map<Name, Member> classMembers = new Map<Name, Member>(); | 31 Map<Name, Member> classMembers = new Map<Name, Member>(); |
32 Map<Name, MemberSignature> interfaceMembers = | 32 Map<Name, MemberSignature> interfaceMembers = |
33 new Map<Name, MemberSignature>(); | 33 new Map<Name, MemberSignature>(); |
34 | 34 |
| 35 Map<dynamic/* Member | Element */, Set<MessageKind>> reportedMessages = |
| 36 new Map<dynamic, Set<MessageKind>>(); |
| 37 |
35 MembersCreator(Compiler this.compiler, ClassElement this.cls); | 38 MembersCreator(Compiler this.compiler, ClassElement this.cls); |
36 | 39 |
| 40 void reportMessage(var marker, MessageKind kind, report()) { |
| 41 Set<MessageKind> messages = |
| 42 reportedMessages.putIfAbsent(marker, |
| 43 () => new Set<MessageKind>()); |
| 44 if (messages.add(kind)) { |
| 45 report(); |
| 46 } |
| 47 } |
| 48 |
37 void computeMembers() { | 49 void computeMembers() { |
38 Map<Name, Set<Member>> inheritedInterfaceMembers = | 50 Map<Name, Set<Member>> inheritedInterfaceMembers = |
39 _computeSuperMembers(); | 51 _computeSuperMembers(); |
40 Map<Name, Member> declaredMembers = _computeClassMembers(); | 52 Map<Name, Member> declaredMembers = _computeClassMembers(); |
41 _computeInterfaceMembers(inheritedInterfaceMembers, declaredMembers); | 53 _computeInterfaceMembers(inheritedInterfaceMembers, declaredMembers); |
| 54 |
| 55 if (!cls.modifiers.isAbstract() && |
| 56 !declaredMembers.containsKey(const PublicName('noSuchMethod'))) { |
| 57 // Check for unimplemented members on concrete classes that neither have |
| 58 // a `@proxy` annotation nor declare a `noSuchMethod` method. |
| 59 checkInterfaceImplementation(); |
| 60 } |
42 } | 61 } |
43 | 62 |
44 Map<Name, Set<Member>> _computeSuperMembers() { | 63 Map<Name, Set<Member>> _computeSuperMembers() { |
45 Map<Name, Set<Member>> inheritedInterfaceMembers = | 64 Map<Name, Set<Member>> inheritedInterfaceMembers = |
46 new Map<Name, Set<Member>>(); | 65 new Map<Name, Set<Member>>(); |
47 | 66 |
48 void inheritInterfaceMembers(InterfaceType supertype) { | 67 void inheritInterfaceMembers(InterfaceType supertype) { |
49 supertype.element.forEachInterfaceMember((MemberSignature member) { | 68 supertype.element.forEachInterfaceMember((MemberSignature member) { |
50 Set<Member> members = | 69 Set<Member> members = |
51 inheritedInterfaceMembers.putIfAbsent( | 70 inheritedInterfaceMembers.putIfAbsent( |
(...skipping 26 matching lines...) Expand all Loading... |
78 inheritInterfaceMembers(superinterface); | 97 inheritInterfaceMembers(superinterface); |
79 } | 98 } |
80 | 99 |
81 return inheritedInterfaceMembers; | 100 return inheritedInterfaceMembers; |
82 } | 101 } |
83 | 102 |
84 Map<Name, Member> _computeClassMembers() { | 103 Map<Name, Member> _computeClassMembers() { |
85 Map<Name, Member> declaredMembers = new Map<Name, Member>(); | 104 Map<Name, Member> declaredMembers = new Map<Name, Member>(); |
86 | 105 |
87 void overrideMember(DeclaredMember declared) { | 106 void overrideMember(DeclaredMember declared) { |
| 107 DeclaredMember inherited = classMembers[declared.name]; |
88 classMembers[declared.name] = declared; | 108 classMembers[declared.name] = declared; |
| 109 checkValidOverride(declared, inherited); |
89 } | 110 } |
90 | 111 |
91 if (cls.isMixinApplication) { | 112 if (cls.isMixinApplication) { |
92 MixinApplicationElement mixinApplication = cls; | 113 MixinApplicationElement mixinApplication = cls; |
93 if (mixinApplication.mixin != null) { | 114 if (mixinApplication.mixin != null) { |
94 // Only mix in class members when the mixin type is not malformed. | 115 // Only mix in class members when the mixin type is not malformed. |
95 computeClassMembers(compiler, mixinApplication.mixin); | 116 computeClassMembers(compiler, mixinApplication.mixin); |
96 | 117 |
97 mixinApplication.mixin.forEachClassMember((DeclaredMember member) { | 118 mixinApplication.mixin.forEachClassMember((DeclaredMember member) { |
98 if (!member.isStatic) { | 119 if (!member.isStatic) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 Map<Name, Set<Member>> inheritedInterfaceMembers, | 184 Map<Name, Set<Member>> inheritedInterfaceMembers, |
164 Map<Name, Member> declaredMembers) { | 185 Map<Name, Member> declaredMembers) { |
165 InterfaceType thisType = cls.thisType; | 186 InterfaceType thisType = cls.thisType; |
166 // Compute the interface members by overriding the inherited members with | 187 // Compute the interface members by overriding the inherited members with |
167 // a declared member or by computing a single, possibly synthesized, | 188 // a declared member or by computing a single, possibly synthesized, |
168 // inherited member. | 189 // inherited member. |
169 inheritedInterfaceMembers.forEach( | 190 inheritedInterfaceMembers.forEach( |
170 (Name name, Set<Member> inheritedMembers) { | 191 (Name name, Set<Member> inheritedMembers) { |
171 Member declared = declaredMembers[name]; | 192 Member declared = declaredMembers[name]; |
172 if (declared != null) { | 193 if (declared != null) { |
| 194 // Check that [declaredMember] is a valid override |
| 195 for (Member inherited in inheritedMembers) { |
| 196 checkValidOverride(declared, inherited); |
| 197 } |
173 if (!declared.isStatic) { | 198 if (!declared.isStatic) { |
174 interfaceMembers[name] = declared; | 199 interfaceMembers[name] = declared; |
175 } | 200 } |
176 } else { | 201 } else { |
177 bool someAreGetters = false; | 202 bool someAreGetters = false; |
178 bool allAreGetters = true; | 203 bool allAreGetters = true; |
179 Map<DartType, Set<Member>> subtypesOfAllInherited = | 204 Map<DartType, Set<Member>> subtypesOfAllInherited = |
180 new Map<DartType, Set<Member>>(); | 205 new Map<DartType, Set<Member>>(); |
181 outer: for (Member inherited in inheritedMembers) { | 206 outer: for (Member inherited in inheritedMembers) { |
182 if (inherited.isGetter) { | 207 if (inherited.isGetter) { |
183 someAreGetters = true; | 208 someAreGetters = true; |
184 if (!allAreGetters) break outer; | 209 if (!allAreGetters) break outer; |
185 } else { | 210 } else { |
186 allAreGetters = false; | 211 allAreGetters = false; |
187 if (someAreGetters) break outer; | 212 if (someAreGetters) break outer; |
188 } | 213 } |
189 for (MemberSignature other in inheritedMembers) { | 214 for (MemberSignature other in inheritedMembers) { |
190 if (!compiler.types.isSubtype(inherited.functionType, | 215 if (!compiler.types.isSubtype(inherited.functionType, |
191 other.functionType)) { | 216 other.functionType)) { |
192 continue outer; | 217 continue outer; |
193 } | 218 } |
194 } | 219 } |
195 subtypesOfAllInherited.putIfAbsent(inherited.functionType, | 220 subtypesOfAllInherited.putIfAbsent(inherited.functionType, |
196 () => new Set<Member>()).add(inherited); | 221 () => new Set<Member>()).add(inherited); |
197 } | 222 } |
198 if (someAreGetters && !allAreGetters) { | 223 if (someAreGetters && !allAreGetters) { |
| 224 compiler.reportWarningCode(cls, |
| 225 MessageKind.INHERIT_GETTER_AND_METHOD, |
| 226 {'class': thisType, 'name': name.text }); |
| 227 for (Member inherited in inheritedMembers) { |
| 228 MessageKind kind; |
| 229 if (inherited.isMethod) { |
| 230 kind = MessageKind.INHERITED_METHOD; |
| 231 } else { |
| 232 assert(invariant(cls, inherited.isGetter, |
| 233 message: 'Conflicting member is neither a method nor a ' |
| 234 'getter.')); |
| 235 if (inherited.isDeclaredByField) { |
| 236 kind = MessageKind.INHERITED_IMPLICIT_GETTER; |
| 237 } else { |
| 238 kind = MessageKind.INHERITED_EXPLICIT_GETTER; |
| 239 } |
| 240 } |
| 241 compiler.reportInfo(inherited.element, kind, |
| 242 {'class': inherited.declarer, 'name': name.text }); |
| 243 } |
199 interfaceMembers[name] = new ErroneousMember(inheritedMembers); | 244 interfaceMembers[name] = new ErroneousMember(inheritedMembers); |
200 } else if (subtypesOfAllInherited.length == 1) { | 245 } else if (subtypesOfAllInherited.length == 1) { |
201 // All signatures have the same type. | 246 // All signatures have the same type. |
202 Set<Member> members = subtypesOfAllInherited.values.first; | 247 Set<Member> members = subtypesOfAllInherited.values.first; |
203 MemberSignature inherited = members.first; | 248 MemberSignature inherited = members.first; |
204 if (members.length != 1) { | 249 if (members.length != 1) { |
205 // Multiple signatures with the same type => return a | 250 // Multiple signatures with the same type => return a |
206 // synthesized signature. | 251 // synthesized signature. |
207 inherited = new SyntheticMember( | 252 inherited = new SyntheticMember( |
208 members, inherited.type, inherited.functionType); | 253 members, inherited.type, inherited.functionType); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 DartType type = memberType; | 331 DartType type = memberType; |
287 if (inheritedMembers.first.isGetter || | 332 if (inheritedMembers.first.isGetter || |
288 inheritedMembers.first.isSetter) { | 333 inheritedMembers.first.isSetter) { |
289 type = compiler.types.dynamicType; | 334 type = compiler.types.dynamicType; |
290 } | 335 } |
291 interfaceMembers[name] = new SyntheticMember( | 336 interfaceMembers[name] = new SyntheticMember( |
292 inheritedMembers, type, memberType); | 337 inheritedMembers, type, memberType); |
293 } | 338 } |
294 } | 339 } |
295 | 340 |
| 341 /// Checks that a class member exists for every interface member. |
| 342 void checkInterfaceImplementation() { |
| 343 LibraryElement library = cls.getLibrary(); |
| 344 |
| 345 interfaceMembers.forEach((Name name, MemberSignature interfaceMember) { |
| 346 if (!name.isAccessibleFrom(library)) return; |
| 347 Member classMember = classMembers[name]; |
| 348 if (classMember != null) return; |
| 349 if (interfaceMember is DeclaredMember && |
| 350 interfaceMember.declarer.element == cls) { |
| 351 // Abstract method declared in [cls]. |
| 352 MessageKind kind = MessageKind.ABSTRACT_METHOD; |
| 353 if (interfaceMember.isSetter) { |
| 354 kind = MessageKind.ABSTRACT_SETTER; |
| 355 } else if (interfaceMember.isGetter) { |
| 356 kind = MessageKind.ABSTRACT_GETTER; |
| 357 } |
| 358 reportMessage( |
| 359 interfaceMember.element, MessageKind.ABSTRACT_METHOD, () { |
| 360 compiler.reportWarningCode( |
| 361 interfaceMember.element, kind, |
| 362 {'class': cls.name, 'name': name.text}); |
| 363 }); |
| 364 } else { |
| 365 reportWarning(MessageKind singleKind, |
| 366 MessageKind multipleKind, |
| 367 MessageKind explicitlyDeclaredKind, |
| 368 [MessageKind implicitlyDeclaredKind]) { |
| 369 Member inherited = interfaceMember.declarations.first; |
| 370 reportMessage( |
| 371 interfaceMember, MessageKind.UNIMPLEMENTED_METHOD, () { |
| 372 compiler.reportWarningCode(cls, |
| 373 interfaceMember.declarations.length == 1 |
| 374 ? singleKind : multipleKind, |
| 375 {'class': cls.name, |
| 376 'name': name.text, |
| 377 'method': interfaceMember, |
| 378 'declarer': inherited.declarer}); |
| 379 for (Member inherited in interfaceMember.declarations) { |
| 380 compiler.reportInfo(inherited.element, |
| 381 inherited.isDeclaredByField ? |
| 382 implicitlyDeclaredKind : explicitlyDeclaredKind, |
| 383 {'class': inherited.declarer.name, |
| 384 'name': name.text}); |
| 385 } |
| 386 }); |
| 387 } |
| 388 if (interfaceMember.isSetter) { |
| 389 reportWarning(MessageKind.UNIMPLEMENTED_SETTER_ONE, |
| 390 MessageKind.UNIMPLEMENTED_SETTER, |
| 391 MessageKind.UNIMPLEMENTED_EXPLICIT_SETTER, |
| 392 MessageKind.UNIMPLEMENTED_IMPLICIT_SETTER); |
| 393 } else if (interfaceMember.isGetter) { |
| 394 reportWarning(MessageKind.UNIMPLEMENTED_GETTER_ONE, |
| 395 MessageKind.UNIMPLEMENTED_GETTER, |
| 396 MessageKind.UNIMPLEMENTED_EXPLICIT_GETTER, |
| 397 MessageKind.UNIMPLEMENTED_IMPLICIT_GETTER); |
| 398 } else if (interfaceMember.isMethod) { |
| 399 reportWarning(MessageKind.UNIMPLEMENTED_METHOD_ONE, |
| 400 MessageKind.UNIMPLEMENTED_METHOD, |
| 401 MessageKind.UNIMPLEMENTED_METHOD_CONT); |
| 402 } |
| 403 } |
| 404 // TODO(johnniwinther): If [cls] is not abstract, check that for all |
| 405 // interface members, there is a class member whose type is a subtype of |
| 406 // the interface member. |
| 407 }); |
| 408 } |
| 409 |
| 410 void checkValidOverride(Member declared, MemberSignature superMember) { |
| 411 if (superMember == null) { |
| 412 // No override. |
| 413 if (!declared.isStatic) { |
| 414 ClassElement superclass = cls.superclass; |
| 415 while (superclass != null) { |
| 416 Member superMember = |
| 417 superclass.lookupClassMember(declared.name); |
| 418 if (superMember != null && superMember.isStatic) { |
| 419 reportMessage(superMember, MessageKind.INSTANCE_STATIC_SAME_NAME, |
| 420 () { |
| 421 compiler.reportWarningCode( |
| 422 declared.element, |
| 423 MessageKind.INSTANCE_STATIC_SAME_NAME, |
| 424 {'memberName': declared.name, |
| 425 'className': superclass.name}); |
| 426 compiler.reportInfo(superMember.element, |
| 427 MessageKind.INSTANCE_STATIC_SAME_NAME_CONT); |
| 428 }); |
| 429 break; |
| 430 } |
| 431 superclass = superclass.superclass; |
| 432 } |
| 433 } |
| 434 } else { |
| 435 assert(declared.name == superMember.name); |
| 436 if (declared.isStatic) { |
| 437 for (Member inherited in superMember.declarations) { |
| 438 reportMessage( |
| 439 inherited.element, MessageKind.NO_STATIC_OVERRIDE, () { |
| 440 reportErrorWithContext( |
| 441 declared.element, MessageKind.NO_STATIC_OVERRIDE, |
| 442 inherited.element, MessageKind.NO_STATIC_OVERRIDE_CONT); |
| 443 }); |
| 444 } |
| 445 } |
| 446 |
| 447 DartType declaredType = declared.functionType; |
| 448 for (Member inherited in superMember.declarations) { |
| 449 |
| 450 void reportError(MessageKind errorKind, MessageKind infoKind) { |
| 451 reportMessage( |
| 452 inherited.element, MessageKind.INVALID_OVERRIDE_METHOD, () { |
| 453 compiler.reportError(declared.element, errorKind, |
| 454 {'name': declared.name.text, |
| 455 'class': cls.thisType, |
| 456 'inheritedClass': inherited.declarer}); |
| 457 compiler.reportInfo(inherited.element, infoKind, |
| 458 {'name': declared.name.text, |
| 459 'class': inherited.declarer}); |
| 460 }); |
| 461 } |
| 462 |
| 463 if (declared.isDeclaredByField && inherited.isMethod) { |
| 464 reportError(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD, |
| 465 MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT); |
| 466 } else if (declared.isMethod && inherited.isDeclaredByField) { |
| 467 reportError(MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD, |
| 468 MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT); |
| 469 } else if (declared.isGetter && inherited.isMethod) { |
| 470 reportError(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER, |
| 471 MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT); |
| 472 } else if (declared.isMethod && inherited.isGetter) { |
| 473 reportError(MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD, |
| 474 MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT); |
| 475 } else { |
| 476 DartType inheritedType = inherited.functionType; |
| 477 if (!compiler.types.isSubtype(declaredType, inheritedType)) { |
| 478 void reportWarning(var marker, |
| 479 MessageKind warningKind, |
| 480 MessageKind infoKind) { |
| 481 reportMessage(marker, MessageKind.INVALID_OVERRIDE_METHOD, () { |
| 482 compiler.reportWarningCode(declared.element, warningKind, |
| 483 {'declaredType': declared.type, |
| 484 'name': declared.name.text, |
| 485 'class': cls.thisType, |
| 486 'inheritedType': inherited.type, |
| 487 'inheritedClass': inherited.declarer}); |
| 488 compiler.reportInfo(inherited.element, infoKind, |
| 489 {'name': declared.name.text, |
| 490 'class': inherited.declarer}); |
| 491 }); |
| 492 } |
| 493 if (declared.isDeclaredByField) { |
| 494 if (inherited.isDeclaredByField) { |
| 495 reportWarning(inherited.element, |
| 496 MessageKind.INVALID_OVERRIDE_FIELD, |
| 497 MessageKind.INVALID_OVERRIDDEN_FIELD); |
| 498 } else if (inherited.isGetter) { |
| 499 reportWarning(inherited, |
| 500 MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD, |
| 501 MessageKind.INVALID_OVERRIDDEN_GETTER); |
| 502 } else if (inherited.isSetter) { |
| 503 reportWarning(inherited, |
| 504 MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD, |
| 505 MessageKind.INVALID_OVERRIDDEN_SETTER); |
| 506 } |
| 507 } else if (declared.isGetter) { |
| 508 if (inherited.isDeclaredByField) { |
| 509 reportWarning(inherited, |
| 510 MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER, |
| 511 MessageKind.INVALID_OVERRIDDEN_FIELD); |
| 512 } else { |
| 513 reportWarning(inherited, |
| 514 MessageKind.INVALID_OVERRIDE_GETTER, |
| 515 MessageKind.INVALID_OVERRIDDEN_GETTER); |
| 516 } |
| 517 } else if (declared.isSetter) { |
| 518 if (inherited.isDeclaredByField) { |
| 519 reportWarning(inherited, |
| 520 MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER, |
| 521 MessageKind.INVALID_OVERRIDDEN_FIELD); |
| 522 } else { |
| 523 reportWarning(inherited, |
| 524 MessageKind.INVALID_OVERRIDE_SETTER, |
| 525 MessageKind.INVALID_OVERRIDDEN_SETTER); |
| 526 } |
| 527 } else { |
| 528 reportWarning(inherited, |
| 529 MessageKind.INVALID_OVERRIDE_METHOD, |
| 530 MessageKind.INVALID_OVERRIDDEN_METHOD); |
| 531 } |
| 532 } |
| 533 } |
| 534 } |
| 535 } |
| 536 } |
| 537 |
| 538 void reportErrorWithContext(Element errorneousElement, |
| 539 MessageKind errorMessage, |
| 540 Element contextElement, |
| 541 MessageKind contextMessage) { |
| 542 compiler.reportError( |
| 543 errorneousElement, |
| 544 errorMessage, |
| 545 {'memberName': contextElement.name, |
| 546 'className': contextElement.getEnclosingClass().name}); |
| 547 compiler.reportInfo(contextElement, contextMessage); |
| 548 } |
| 549 |
296 static void computeClassMembers(Compiler compiler, BaseClassElementX cls) { | 550 static void computeClassMembers(Compiler compiler, BaseClassElementX cls) { |
297 if (cls.classMembers != null) return; | 551 if (cls.classMembers != null) return; |
298 MembersCreator creator = new MembersCreator(compiler, cls); | 552 MembersCreator creator = new MembersCreator(compiler, cls); |
299 creator.computeMembers(); | 553 creator.computeMembers(); |
300 cls.classMembers = creator.classMembers; | 554 cls.classMembers = creator.classMembers; |
301 cls.interfaceMembers = creator.interfaceMembers; | 555 cls.interfaceMembers = creator.interfaceMembers; |
302 } | 556 } |
303 } | 557 } |
OLD | NEW |