Chromium Code Reviews| 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 21 matching lines...) Expand all Loading... | |
| 32 cls.interfaceMembers = creator.interfaceMembers; | 32 cls.interfaceMembers = creator.interfaceMembers; |
| 33 } | 33 } |
| 34 | 34 |
| 35 class MembersCreator { | 35 class MembersCreator { |
| 36 final ClassElement cls; | 36 final ClassElement cls; |
| 37 final Compiler compiler; | 37 final Compiler compiler; |
| 38 | 38 |
| 39 Map<Name, Member> classMembers = new Map<Name, Member>(); | 39 Map<Name, Member> classMembers = new Map<Name, Member>(); |
| 40 Map<Name, Signature> interfaceMembers = new Map<Name, Signature>(); | 40 Map<Name, Signature> interfaceMembers = new Map<Name, Signature>(); |
| 41 | 41 |
| 42 Map<Object, Set<MessageKind>> reportedMessages = | |
|
karlklose
2014/01/28 12:27:45
Please add a comment about the possible types of k
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 43 new Map<Object, Set<MessageKind>>(); | |
| 44 | |
| 42 MembersCreator(Compiler this.compiler, ClassElement this.cls); | 45 MembersCreator(Compiler this.compiler, ClassElement this.cls); |
| 43 | 46 |
| 47 void reportMessage(var marker, MessageKind kind, report()) { | |
| 48 Set<MessageKind> messages = | |
| 49 reportedMessages.putIfAbsent(marker, | |
| 50 () => new Set<MessageKind>()); | |
| 51 if (messages.add(kind)) { | |
| 52 report(); | |
| 53 } | |
| 54 } | |
| 55 | |
| 44 void computeMembers() { | 56 void computeMembers() { |
| 45 Map<Name, Set<Member>> inheritedInterfaceMembers = | 57 Map<Name, Set<Member>> inheritedInterfaceMembers = |
| 46 _computeSuperMembers(); | 58 _computeSuperMembers(); |
| 47 Map<Name, Member> declaredMembers = _computeClassMembers(); | 59 Map<Name, Member> declaredMembers = _computeClassMembers(); |
| 48 _computeInterfaceMembers(inheritedInterfaceMembers, declaredMembers); | 60 _computeInterfaceMembers(inheritedInterfaceMembers, declaredMembers); |
| 61 | |
| 62 if (!cls.modifiers.isAbstract() && | |
| 63 !cls.isProxy && | |
| 64 !declaredMembers.containsKey(const PublicName('noSuchMethod'))) { | |
| 65 // Check for unimplemented member on concrete classes that neither have | |
|
karlklose
2014/01/28 12:27:45
'member' -> 'members'?
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 66 // a @proxy annotation nor declare a `noSuchMethod` method. | |
|
karlklose
2014/01/28 12:27:45
'@proxy' -> '`@proxy`'.
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 67 checkInterfaceImplementation(); | |
| 68 } | |
| 49 } | 69 } |
| 50 | 70 |
| 51 Map<Name, Set<Member>> _computeSuperMembers() { | 71 Map<Name, Set<Member>> _computeSuperMembers() { |
| 52 Map<Name, Set<Member>> inheritedInterfaceMembers = | 72 Map<Name, Set<Member>> inheritedInterfaceMembers = |
| 53 new Map<Name, Set<Member>>(); | 73 new Map<Name, Set<Member>>(); |
| 54 | 74 |
| 55 void inheritInterfaceMembers(InterfaceType supertype) { | 75 void inheritInterfaceMembers(InterfaceType supertype) { |
| 56 supertype.element.forEachInterfaceMember((Signature member) { | 76 supertype.element.forEachInterfaceMember((Signature member) { |
| 57 Set<Member> members = | 77 Set<Member> members = |
| 58 inheritedInterfaceMembers.putIfAbsent( | 78 inheritedInterfaceMembers.putIfAbsent( |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 87 | 107 |
| 88 return inheritedInterfaceMembers; | 108 return inheritedInterfaceMembers; |
| 89 } | 109 } |
| 90 | 110 |
| 91 Map<Name, Member> _computeClassMembers() { | 111 Map<Name, Member> _computeClassMembers() { |
| 92 Map<Name, Member> declaredMembers = new Map<Name, Member>(); | 112 Map<Name, Member> declaredMembers = new Map<Name, Member>(); |
| 93 | 113 |
| 94 void overrideMember(DeclaredMember declared) { | 114 void overrideMember(DeclaredMember declared) { |
| 95 DeclaredMember inherited = classMembers[declared.name]; | 115 DeclaredMember inherited = classMembers[declared.name]; |
| 96 classMembers[declared.name] = declared; | 116 classMembers[declared.name] = declared; |
| 117 checkValidOverride(declared, inherited); | |
| 97 } | 118 } |
| 98 | 119 |
| 99 if (cls.isMixinApplication) { | 120 if (cls.isMixinApplication) { |
| 100 MixinApplicationElement mixinApplication = cls; | 121 MixinApplicationElement mixinApplication = cls; |
| 101 if (mixinApplication.mixin != null) { | 122 if (mixinApplication.mixin != null) { |
| 102 // Only mix in class members when the mixin type is not malformed. | 123 // Only mix in class members when the mixin type is not malformed. |
| 103 computeClassMembers(compiler, mixinApplication.mixin); | 124 computeClassMembers(compiler, mixinApplication.mixin); |
| 104 | 125 |
| 105 mixinApplication.mixin.forEachClassMember((DeclaredMember member) { | 126 mixinApplication.mixin.forEachClassMember((DeclaredMember member) { |
| 106 if (!member.isStatic) { | 127 if (!member.isStatic) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 | 189 |
| 169 void _computeInterfaceMembers( | 190 void _computeInterfaceMembers( |
| 170 Map<Name, Set<Member>> inheritedInterfaceMembers, | 191 Map<Name, Set<Member>> inheritedInterfaceMembers, |
| 171 Map<Name, Member> declaredMembers) { | 192 Map<Name, Member> declaredMembers) { |
| 172 InterfaceType thisType = cls.thisType; | 193 InterfaceType thisType = cls.thisType; |
| 173 // Compute the interface members by overriding the inherited members with | 194 // Compute the interface members by overriding the inherited members with |
| 174 inheritedInterfaceMembers.forEach( | 195 inheritedInterfaceMembers.forEach( |
| 175 (Name name, Set<Member> inheritedMembers) { | 196 (Name name, Set<Member> inheritedMembers) { |
| 176 Member declared = declaredMembers[name]; | 197 Member declared = declaredMembers[name]; |
| 177 if (declared != null) { | 198 if (declared != null) { |
| 199 // Check that [declaredMember] is a valid override | |
| 200 for (Member inherited in inheritedMembers) { | |
| 201 checkValidOverride(declared, inherited); | |
| 202 } | |
| 178 if (!declared.isStatic) { | 203 if (!declared.isStatic) { |
| 179 interfaceMembers[name] = declared; | 204 interfaceMembers[name] = declared; |
| 180 } | 205 } |
| 181 } else { | 206 } else { |
| 182 bool someAreGetters = false; | 207 bool someAreGetters = false; |
| 183 bool allAreGetters = true; | 208 bool allAreGetters = true; |
| 184 Map<DartType, Set<Member>> subtypesOfAllInherited = | 209 Map<DartType, Set<Member>> subtypesOfAllInherited = |
| 185 new Map<DartType, Set<Member>>(); | 210 new Map<DartType, Set<Member>>(); |
| 186 outer: for (Member inherited in inheritedMembers) { | 211 outer: for (Member inherited in inheritedMembers) { |
| 187 if (inherited.isGetter) { | 212 if (inherited.isGetter) { |
| 188 someAreGetters = true; | 213 someAreGetters = true; |
| 189 if (!allAreGetters) break outer; | 214 if (!allAreGetters) break outer; |
| 190 } else { | 215 } else { |
| 191 allAreGetters = false; | 216 allAreGetters = false; |
| 192 if (someAreGetters) break outer; | 217 if (someAreGetters) break outer; |
| 193 } | 218 } |
| 194 for (Signature other in inheritedMembers) { | 219 for (Signature other in inheritedMembers) { |
| 195 if (!compiler.types.isSubtype(inherited.functionType, | 220 if (!compiler.types.isSubtype(inherited.functionType, |
| 196 other.functionType)) { | 221 other.functionType)) { |
| 197 continue outer; | 222 continue outer; |
| 198 } | 223 } |
| 199 } | 224 } |
| 200 subtypesOfAllInherited.putIfAbsent(inherited.functionType, | 225 subtypesOfAllInherited.putIfAbsent(inherited.functionType, |
| 201 () => new Set<Member>()).add(inherited); | 226 () => new Set<Member>()).add(inherited); |
| 202 } | 227 } |
| 203 if (someAreGetters && !allAreGetters) { | 228 if (someAreGetters && !allAreGetters) { |
| 229 compiler.reportWarningCode(cls, | |
| 230 MessageKind.INHERIT_GETTER_AND_METHOD, | |
| 231 {'class': thisType, 'name': name.text }); | |
| 232 for (Member inherited in inheritedMembers) { | |
| 233 MessageKind kind; | |
| 234 if (inherited.isMethod) { | |
| 235 kind = MessageKind.INHERITED_METHOD; | |
| 236 } else { | |
| 237 assert(invariant(cls, inherited.isGetter, | |
| 238 message: 'Conflicting member is neither a method nor a ' | |
| 239 'getter.')); | |
| 240 if (inherited.isDeclaredByField) { | |
| 241 kind = MessageKind.INHERITED_IMPLICIT_GETTER; | |
| 242 } else { | |
| 243 kind = MessageKind.INHERITED_EXPLICIT_GETTER; | |
| 244 } | |
| 245 } | |
| 246 compiler.reportInfo(inherited.element, kind, | |
| 247 {'class': inherited.declarer, 'name': name.text }); | |
| 248 } | |
| 204 interfaceMembers[name] = new ErroneousMember(inheritedMembers); | 249 interfaceMembers[name] = new ErroneousMember(inheritedMembers); |
| 205 } else if (subtypesOfAllInherited.length == 1) { | 250 } else if (subtypesOfAllInherited.length == 1) { |
| 206 // All signatures have the same type. | 251 // All signatures have the same type. |
| 207 Set<Member> members = subtypesOfAllInherited.values.first; | 252 Set<Member> members = subtypesOfAllInherited.values.first; |
| 208 Signature inherited = members.first; | 253 Signature inherited = members.first; |
| 209 if (members.length != 1) { | 254 if (members.length != 1) { |
| 210 // Multiple signatures with the same type => return a | 255 // Multiple signatures with the same type => return a |
| 211 // synthesized signature. | 256 // synthesized signature. |
| 212 inherited = new SyntheticMember( | 257 inherited = new SyntheticMember( |
| 213 members, inherited.type, inherited.functionType); | 258 members, inherited.type, inherited.functionType); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 } | 328 } |
| 284 }); | 329 }); |
| 285 | 330 |
| 286 // Add the non-overriding instance methods to the interface members. | 331 // Add the non-overriding instance methods to the interface members. |
| 287 declaredMembers.forEach((Name name, Member member) { | 332 declaredMembers.forEach((Name name, Member member) { |
| 288 if (!member.isStatic) { | 333 if (!member.isStatic) { |
| 289 interfaceMembers.putIfAbsent(name, () => member); | 334 interfaceMembers.putIfAbsent(name, () => member); |
| 290 } | 335 } |
| 291 }); | 336 }); |
| 292 } | 337 } |
| 338 | |
| 339 void checkInterfaceImplementation() { | |
|
karlklose
2014/01/28 12:27:45
Please add a comment on what this method checks.
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 340 LibraryElement library = cls.getLibrary(); | |
| 341 | |
| 342 interfaceMembers.forEach((Name name, Signature interfaceMember) { | |
| 343 if (!name.isAccessibleFrom(library)) return; | |
| 344 Member classMember = classMembers[name]; | |
| 345 /*if (compiler.inUserCode(cls)) { | |
|
karlklose
2014/01/28 12:27:45
Remove debug code.
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 346 print('cls:$cls, sig:$interfaceMember, member=$classMember (${classMembe r == null || classMember.isAbstract})'); | |
| 347 }*/ | |
| 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, Signature superMember) { | |
| 411 if (superMember != null) { | |
|
karlklose
2014/01/28 12:27:45
Perhaps 'assert(declared.name == superMember.name)
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 412 if (declared.isStatic) { | |
| 413 for (Member inherited in superMember.declarations) { | |
| 414 reportMessage( | |
| 415 inherited.element, MessageKind.NO_STATIC_OVERRIDE, () { | |
| 416 reportErrorWithContext( | |
| 417 declared.element, MessageKind.NO_STATIC_OVERRIDE, | |
| 418 inherited.element, MessageKind.NO_STATIC_OVERRIDE_CONT); | |
| 419 }); | |
| 420 } | |
| 421 } | |
| 422 | |
| 423 DartType declaredType = declared.functionType; | |
| 424 for (Member inherited in superMember.declarations) { | |
| 425 | |
| 426 void reportError(MessageKind errorKind, MessageKind infoKind) { | |
| 427 reportMessage( | |
| 428 inherited.element, MessageKind.INVALID_OVERRIDE_METHOD, () { | |
| 429 compiler.reportError(declared.element, errorKind, | |
| 430 {'name': declared.name.text, | |
| 431 'class': cls.thisType, | |
| 432 'inheritedClass': inherited.declarer}); | |
| 433 compiler.reportInfo(inherited.element, infoKind, | |
| 434 {'name': declared.name.text, | |
| 435 'class': inherited.declarer}); | |
| 436 }); | |
| 437 } | |
| 438 | |
| 439 if (declared.isDeclaredByField && inherited.isMethod) { | |
| 440 reportError(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD, | |
| 441 MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT); | |
| 442 } else if (declared.isMethod && inherited.isDeclaredByField) { | |
| 443 reportError(MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD, | |
| 444 MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT); | |
| 445 } else if (declared.isGetter && inherited.isMethod) { | |
| 446 reportError(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER, | |
| 447 MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT); | |
| 448 } else if (declared.isMethod && inherited.isGetter) { | |
| 449 reportError(MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD, | |
| 450 MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT); | |
| 451 } else { | |
| 452 DartType inheritedType = inherited.functionType; | |
| 453 if (!compiler.types.isSubtype(declaredType, inheritedType)) { | |
| 454 void reportWarning(var marker, | |
| 455 MessageKind warningKind, | |
| 456 MessageKind infoKind) { | |
| 457 reportMessage(marker, MessageKind.INVALID_OVERRIDE_METHOD, () { | |
| 458 compiler.reportWarningCode(declared.element, warningKind, | |
| 459 {'declaredType': declared.type, | |
| 460 'name': declared.name.text, | |
| 461 'class': cls.thisType, | |
| 462 'inheritedType': inherited.type, | |
| 463 'inheritedClass': inherited.declarer}); | |
| 464 compiler.reportInfo(inherited.element, infoKind, | |
| 465 {'name': declared.name.text, | |
| 466 'class': inherited.declarer}); | |
| 467 }); | |
| 468 } | |
| 469 if (declared.isDeclaredByField) { | |
| 470 if (inherited.isDeclaredByField) { | |
| 471 reportWarning(inherited.element, | |
| 472 MessageKind.INVALID_OVERRIDE_FIELD, | |
| 473 MessageKind.INVALID_OVERRIDDEN_FIELD); | |
| 474 } else if (inherited.isGetter) { | |
| 475 reportWarning(inherited, | |
| 476 MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD, | |
| 477 MessageKind.INVALID_OVERRIDDEN_GETTER); | |
| 478 } else if (inherited.isSetter) { | |
| 479 reportWarning(inherited, | |
| 480 MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD, | |
| 481 MessageKind.INVALID_OVERRIDDEN_SETTER); | |
| 482 } | |
| 483 } else if (declared.isGetter) { | |
| 484 if (inherited.isDeclaredByField) { | |
| 485 reportWarning(inherited, | |
| 486 MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER, | |
| 487 MessageKind.INVALID_OVERRIDDEN_FIELD); | |
| 488 } else { | |
| 489 reportWarning(inherited, | |
| 490 MessageKind.INVALID_OVERRIDE_GETTER, | |
| 491 MessageKind.INVALID_OVERRIDDEN_GETTER); | |
| 492 } | |
| 493 } else if (declared.isSetter) { | |
| 494 if (inherited.isDeclaredByField) { | |
| 495 reportWarning(inherited, | |
| 496 MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER, | |
| 497 MessageKind.INVALID_OVERRIDDEN_FIELD); | |
| 498 } else { | |
| 499 reportWarning(inherited, | |
| 500 MessageKind.INVALID_OVERRIDE_SETTER, | |
| 501 MessageKind.INVALID_OVERRIDDEN_SETTER); | |
| 502 } | |
| 503 } else { | |
| 504 reportWarning(inherited, | |
| 505 MessageKind.INVALID_OVERRIDE_METHOD, | |
| 506 MessageKind.INVALID_OVERRIDDEN_METHOD); | |
| 507 } | |
| 508 } | |
| 509 } | |
| 510 } | |
| 511 } else { | |
|
karlklose
2014/01/28 12:27:45
Consider changing the else-branch to be the then-b
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 512 if (!declared.isStatic) { | |
| 513 ClassElement superclass = cls.superclass; | |
| 514 while (superclass != null) { | |
| 515 //print('checkValidOverride($declared,$superclass'); | |
|
karlklose
2014/01/28 12:27:45
Remove debug code.
Johnni Winther
2014/01/31 12:29:30
Done.
| |
| 516 Member superMember = | |
| 517 superclass.lookupClassMember(declared.name); | |
| 518 if (superMember != null && superMember.isStatic) { | |
| 519 reportMessage(superMember, MessageKind.INSTANCE_STATIC_SAME_NAME, | |
| 520 () { | |
| 521 compiler.reportWarningCode( | |
| 522 declared.element, | |
| 523 MessageKind.INSTANCE_STATIC_SAME_NAME, | |
| 524 {'memberName': declared.name, | |
| 525 'className': superclass.name}); | |
| 526 compiler.reportInfo(superMember.element, | |
| 527 MessageKind.INSTANCE_STATIC_SAME_NAME_CONT); | |
| 528 }); | |
| 529 break; | |
| 530 } | |
| 531 superclass = superclass.superclass; | |
| 532 } | |
| 533 } | |
| 534 } | |
| 535 } | |
| 536 | |
| 537 void reportErrorWithContext(Element errorneousElement, | |
| 538 MessageKind errorMessage, | |
| 539 Element contextElement, | |
| 540 MessageKind contextMessage) { | |
| 541 compiler.reportError( | |
| 542 errorneousElement, | |
| 543 errorMessage, | |
| 544 {'memberName': contextElement.name, | |
| 545 'className': contextElement.getEnclosingClass().name}); | |
| 546 compiler.reportInfo(contextElement, contextMessage); | |
| 547 } | |
| 293 } | 548 } |
| OLD | NEW |