| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 dart2js.resolution.class_hierarchy; | 5 library dart2js.resolution.class_hierarchy; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/resolution.dart' show Feature; | 8 import '../common/resolution.dart' show Feature; |
| 9 import '../compiler.dart' show Compiler; | 9 import '../compiler.dart' show Compiler; |
| 10 import '../core_types.dart' show CoreClasses, CoreTypes; | 10 import '../core_types.dart' show CoreClasses, CoreTypes; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 reporter.internalError( | 167 reporter.internalError( |
| 168 node, "Cannot resolve default superclass for $element."); | 168 node, "Cannot resolve default superclass for $element."); |
| 169 } else { | 169 } else { |
| 170 superElement.ensureResolved(resolution); | 170 superElement.ensureResolved(resolution); |
| 171 } | 171 } |
| 172 element.supertype = superElement.computeType(resolution); | 172 element.supertype = superElement.computeType(resolution); |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 | 175 |
| 176 if (element.interfaces == null) { | 176 if (element.interfaces == null) { |
| 177 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); | 177 element.interfaces = |
| 178 resolveInterfaces(element, node.interfaces, node.superclass); |
| 178 } else { | 179 } else { |
| 179 assert(invariant(element, element.hasIncompleteHierarchy)); | 180 assert(invariant(element, element.hasIncompleteHierarchy)); |
| 180 } | 181 } |
| 181 calculateAllSupertypes(element); | 182 calculateAllSupertypes(element); |
| 182 | 183 |
| 183 if (!element.hasConstructor) { | 184 if (!element.hasConstructor) { |
| 184 Element superMember = element.superclass.localLookup(''); | 185 Element superMember = element.superclass.localLookup(''); |
| 185 if (superMember == null) { | 186 if (superMember == null) { |
| 186 MessageKind kind = MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR; | 187 MessageKind kind = MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR; |
| 187 Map arguments = {'className': element.superclass.name}; | 188 Map arguments = {'className': element.superclass.name}; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 assert(invariant(node, supertype.isObject)); | 366 assert(invariant(node, supertype.isObject)); |
| 366 } else { | 367 } else { |
| 367 mixinApplication.supertype = supertype; | 368 mixinApplication.supertype = supertype; |
| 368 } | 369 } |
| 369 | 370 |
| 370 // Named mixin application may have an 'implements' clause. | 371 // Named mixin application may have an 'implements' clause. |
| 371 NamedMixinApplication namedMixinApplication = | 372 NamedMixinApplication namedMixinApplication = |
| 372 node.asNamedMixinApplication(); | 373 node.asNamedMixinApplication(); |
| 373 Link<DartType> interfaces = (namedMixinApplication != null) | 374 Link<DartType> interfaces = (namedMixinApplication != null) |
| 374 ? resolveInterfaces( | 375 ? resolveInterfaces( |
| 376 mixinApplication, |
| 375 namedMixinApplication.interfaces, namedMixinApplication.superclass) | 377 namedMixinApplication.interfaces, namedMixinApplication.superclass) |
| 376 : const Link<DartType>(); | 378 : const Link<DartType>(); |
| 377 | 379 |
| 378 // The class that is the result of a mixin application implements | 380 // The class that is the result of a mixin application implements |
| 379 // the interface of the class that was mixed in so always prepend | 381 // the interface of the class that was mixed in so always prepend |
| 380 // that to the interface list. | 382 // that to the interface list. |
| 381 if (mixinApplication.interfaces == null) { | 383 if (mixinApplication.interfaces == null) { |
| 382 if (mixinType.isInterfaceType) { | 384 if (mixinType.isInterfaceType) { |
| 383 // Avoid malformed types in the interfaces. | 385 // Avoid malformed types in the interfaces. |
| 384 interfaces = interfaces.prepend(mixinType); | 386 interfaces = interfaces.prepend(mixinType); |
| 385 } | 387 } |
| 386 mixinApplication.interfaces = interfaces; | 388 mixinApplication.interfaces = interfaces; |
| 387 } else { | 389 } else { |
| 388 assert( | 390 assert( |
| 389 invariant(mixinApplication, mixinApplication.hasIncompleteHierarchy)); | 391 invariant(mixinApplication, mixinApplication.hasIncompleteHierarchy)); |
| 390 } | 392 } |
| 391 | 393 |
| 392 ClassElement superclass = supertype.element; | 394 ClassElement superclass = supertype.element; |
| 393 if (mixinType.kind != TypeKind.INTERFACE) { | 395 if (mixinType.kind != TypeKind.INTERFACE) { |
| 394 mixinApplication.hasIncompleteHierarchy = true; | 396 mixinApplication.hasIncompleteHierarchy = true; |
| 395 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; | 397 mixinType = objectType; |
| 396 return; | |
| 397 } | 398 } |
| 398 | 399 |
| 399 assert(mixinApplication.mixinType == null); | 400 assert(mixinApplication.mixinType == null); |
| 400 mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType); | 401 mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType); |
| 401 | 402 |
| 402 // Create forwarding constructors for constructor defined in the superclass | 403 // Create forwarding constructors for constructor defined in the superclass |
| 403 // because they are now hidden by the mixin application. | 404 // because they are now hidden by the mixin application. |
| 404 superclass.forEachLocalMember((Element member) { | 405 superclass.forEachLocalMember((Element member) { |
| 405 if (!member.isGenerativeConstructor) return; | 406 if (!member.isGenerativeConstructor) return; |
| 406 FunctionElement forwarder = | 407 FunctionElement forwarder = |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 } | 451 } |
| 451 | 452 |
| 452 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { | 453 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
| 453 DartType supertype = resolveType(superclass); | 454 DartType supertype = resolveType(superclass); |
| 454 if (supertype != null) { | 455 if (supertype != null) { |
| 455 if (supertype.isMalformed) { | 456 if (supertype.isMalformed) { |
| 456 reporter.reportErrorMessage( | 457 reporter.reportErrorMessage( |
| 457 superclass, | 458 superclass, |
| 458 MessageKind.CANNOT_EXTEND_MALFORMED, | 459 MessageKind.CANNOT_EXTEND_MALFORMED, |
| 459 {'className': element.name, 'malformedType': supertype}); | 460 {'className': element.name, 'malformedType': supertype}); |
| 461 cls.hasIncompleteHierarchy = true; |
| 460 return objectType; | 462 return objectType; |
| 461 } else if (supertype.isEnumType) { | 463 } else if (supertype.isEnumType) { |
| 462 reporter.reportErrorMessage(superclass, MessageKind.CANNOT_EXTEND_ENUM, | 464 reporter.reportErrorMessage(superclass, MessageKind.CANNOT_EXTEND_ENUM, |
| 463 {'className': element.name, 'enumType': supertype}); | 465 {'className': element.name, 'enumType': supertype}); |
| 466 cls.hasIncompleteHierarchy = true; |
| 464 return objectType; | 467 return objectType; |
| 465 } else if (!supertype.isInterfaceType) { | 468 } else if (!supertype.isInterfaceType) { |
| 466 reporter.reportErrorMessage( | 469 reporter.reportErrorMessage( |
| 467 superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); | 470 superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); |
| 471 cls.hasIncompleteHierarchy = true; |
| 468 return objectType; | 472 return objectType; |
| 469 } else if (isBlackListed(supertype)) { | 473 } else if (isBlackListed(supertype)) { |
| 470 reporter.reportErrorMessage( | 474 reporter.reportErrorMessage( |
| 471 superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); | 475 superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); |
| 476 cls.hasIncompleteHierarchy = true; |
| 472 return objectType; | 477 return objectType; |
| 473 } | 478 } |
| 474 } | 479 } |
| 475 return supertype; | 480 return supertype; |
| 476 } | 481 } |
| 477 | 482 |
| 478 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { | 483 Link<DartType> resolveInterfaces( |
| 484 BaseClassElementX cls, |
| 485 NodeList interfaces, |
| 486 Node superclass) { |
| 479 Link<DartType> result = const Link<DartType>(); | 487 Link<DartType> result = const Link<DartType>(); |
| 480 if (interfaces == null) return result; | 488 if (interfaces == null) return result; |
| 481 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { | 489 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { |
| 482 DartType interfaceType = resolveType(link.head); | 490 DartType interfaceType = resolveType(link.head); |
| 483 if (interfaceType != null) { | 491 if (interfaceType != null) { |
| 484 if (interfaceType.isMalformed) { | 492 if (interfaceType.isMalformed) { |
| 485 reporter.reportErrorMessage( | 493 reporter.reportErrorMessage( |
| 486 superclass, | 494 superclass, |
| 487 MessageKind.CANNOT_IMPLEMENT_MALFORMED, | 495 MessageKind.CANNOT_IMPLEMENT_MALFORMED, |
| 488 {'className': element.name, 'malformedType': interfaceType}); | 496 {'className': element.name, 'malformedType': interfaceType}); |
| 497 cls.hasIncompleteHierarchy = true; |
| 489 } else if (interfaceType.isEnumType) { | 498 } else if (interfaceType.isEnumType) { |
| 490 reporter.reportErrorMessage( | 499 reporter.reportErrorMessage( |
| 491 superclass, | 500 superclass, |
| 492 MessageKind.CANNOT_IMPLEMENT_ENUM, | 501 MessageKind.CANNOT_IMPLEMENT_ENUM, |
| 493 {'className': element.name, 'enumType': interfaceType}); | 502 {'className': element.name, 'enumType': interfaceType}); |
| 503 cls.hasIncompleteHierarchy = true; |
| 494 } else if (!interfaceType.isInterfaceType) { | 504 } else if (!interfaceType.isInterfaceType) { |
| 495 // TODO(johnniwinther): Handle dynamic. | 505 // TODO(johnniwinther): Handle dynamic. |
| 496 TypeAnnotation typeAnnotation = link.head; | 506 TypeAnnotation typeAnnotation = link.head; |
| 497 reporter.reportErrorMessage( | 507 reporter.reportErrorMessage( |
| 498 typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED); | 508 typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED); |
| 509 cls.hasIncompleteHierarchy = true; |
| 499 } else { | 510 } else { |
| 500 if (interfaceType == element.supertype) { | 511 if (interfaceType == element.supertype) { |
| 501 reporter.reportErrorMessage( | 512 reporter.reportErrorMessage( |
| 502 superclass, | 513 superclass, |
| 503 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 514 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
| 504 {'type': interfaceType}); | 515 {'type': interfaceType}); |
| 505 reporter.reportErrorMessage( | 516 reporter.reportErrorMessage( |
| 506 link.head, | 517 link.head, |
| 507 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 518 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
| 508 {'type': interfaceType}); | 519 {'type': interfaceType}); |
| 520 cls.hasIncompleteHierarchy = true; |
| 509 } | 521 } |
| 510 if (result.contains(interfaceType)) { | 522 if (result.contains(interfaceType)) { |
| 511 reporter.reportErrorMessage(link.head, | 523 reporter.reportErrorMessage(link.head, |
| 512 MessageKind.DUPLICATE_IMPLEMENTS, {'type': interfaceType}); | 524 MessageKind.DUPLICATE_IMPLEMENTS, {'type': interfaceType}); |
| 525 cls.hasIncompleteHierarchy = true; |
| 513 } | 526 } |
| 514 result = result.prepend(interfaceType); | 527 result = result.prepend(interfaceType); |
| 515 if (isBlackListed(interfaceType)) { | 528 if (isBlackListed(interfaceType)) { |
| 516 reporter.reportErrorMessage(link.head, MessageKind.CANNOT_IMPLEMENT, | 529 reporter.reportErrorMessage(link.head, MessageKind.CANNOT_IMPLEMENT, |
| 517 {'type': interfaceType}); | 530 {'type': interfaceType}); |
| 531 cls.hasIncompleteHierarchy = true; |
| 518 } | 532 } |
| 519 } | 533 } |
| 520 } | 534 } |
| 521 } | 535 } |
| 522 return result; | 536 return result; |
| 523 } | 537 } |
| 524 | 538 |
| 525 /** | 539 /** |
| 526 * Compute the list of all supertypes. | 540 * Compute the list of all supertypes. |
| 527 * | 541 * |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 Identifier selector = node.selector.asIdentifier(); | 660 Identifier selector = node.selector.asIdentifier(); |
| 647 var e = prefixElement.lookupLocalMember(selector.source); | 661 var e = prefixElement.lookupLocalMember(selector.source); |
| 648 if (e == null || !e.impliesType) { | 662 if (e == null || !e.impliesType) { |
| 649 reporter.reportErrorMessage(node.selector, | 663 reporter.reportErrorMessage(node.selector, |
| 650 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.selector}); | 664 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.selector}); |
| 651 return; | 665 return; |
| 652 } | 666 } |
| 653 loadSupertype(e, node); | 667 loadSupertype(e, node); |
| 654 } | 668 } |
| 655 } | 669 } |
| OLD | NEW |