Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/resolution/class_members.dart

Issue 140803002: Perform override and inheritance checks. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698