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 |