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

Side by Side Diff: pkg/compiler/lib/src/resolution/constructors.dart

Issue 1323573002: Prepare for computation of NewStructure in Resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Fix erroneous prefix. Created 5 years, 3 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
OLDNEW
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.constructors; 5 library dart2js.resolution.constructors;
6 import '../compiler.dart' show 6 import '../compiler.dart' show
7 Compiler; 7 Compiler;
8 import '../constants/constructors.dart' show 8 import '../constants/constructors.dart' show
9 GenerativeConstantConstructor, 9 GenerativeConstantConstructor,
10 RedirectingGenerativeConstantConstructor; 10 RedirectingGenerativeConstantConstructor;
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 constructor.constantConstructor = new GenerativeConstantConstructor( 408 constructor.constantConstructor = new GenerativeConstantConstructor(
409 constructor.enclosingClass.thisType, 409 constructor.enclosingClass.thisType,
410 defaultValues, 410 defaultValues,
411 fieldInitializers, 411 fieldInitializers,
412 constructorInvocation); 412 constructorInvocation);
413 } 413 }
414 return null; // If there was no redirection always return null. 414 return null; // If there was no redirection always return null.
415 } 415 }
416 } 416 }
417 417
418 class ConstructorResolver extends CommonResolverVisitor<Element> { 418 class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> {
419 final ResolverVisitor resolver; 419 final ResolverVisitor resolver;
420 bool inConstContext; 420 final bool inConstContext;
421 DartType type;
422 421
423 ConstructorResolver(Compiler compiler, this.resolver, 422 ConstructorResolver(Compiler compiler, this.resolver,
424 {bool this.inConstContext: false}) 423 {bool this.inConstContext: false})
425 : super(compiler); 424 : super(compiler);
426 425
427 ResolutionRegistry get registry => resolver.registry; 426 ResolutionRegistry get registry => resolver.registry;
428 427
429 visitNode(Node node) { 428 visitNode(Node node) {
430 throw 'not supported'; 429 throw 'not supported';
431 } 430 }
432 431
433 ErroneousConstructorElementX failOrReturnErroneousConstructorElement( 432 ConstructorResult reportAndCreateErroneousConstructorElement(
434 Spannable diagnosticNode, 433 Spannable diagnosticNode,
434 ConstructorResultKind resultKind,
435 DartType type,
435 Element enclosing, 436 Element enclosing,
436 String name, 437 String name,
437 MessageKind kind, 438 MessageKind kind,
438 Map arguments, 439 Map arguments,
439 {bool isError: false, 440 {bool isError: false,
440 bool missingConstructor: false}) { 441 bool missingConstructor: false}) {
441 if (missingConstructor) { 442 if (missingConstructor) {
442 registry.registerThrowNoSuchMethod(); 443 registry.registerThrowNoSuchMethod();
443 } else { 444 } else {
444 registry.registerThrowRuntimeError(); 445 registry.registerThrowRuntimeError();
445 } 446 }
446 if (isError || inConstContext) { 447 if (isError || inConstContext) {
447 compiler.reportError(diagnosticNode, kind, arguments); 448 compiler.reportError(diagnosticNode, kind, arguments);
448 } else { 449 } else {
449 compiler.reportWarning(diagnosticNode, kind, arguments); 450 compiler.reportWarning(diagnosticNode, kind, arguments);
450 } 451 }
451 return new ErroneousConstructorElementX( 452 ErroneousElement error = new ErroneousConstructorElementX(
452 kind, arguments, name, enclosing); 453 kind, arguments, name, enclosing);
453 } 454 if (type == null) {
454 455 type = new MalformedType(error, null);
455 FunctionElement resolveConstructor(ClassElement cls, 456 }
456 Node diagnosticNode, 457 return new ConstructorResult(resultKind, error, type);
457 String constructorName) { 458 }
459
460 ConstructorResult resolveConstructor(
461 InterfaceType type,
462 Node diagnosticNode,
463 String constructorName) {
464 ClassElement cls = type.element;
458 cls.ensureResolved(compiler); 465 cls.ensureResolved(compiler);
459 Element result = cls.lookupConstructor(constructorName); 466 ConstructorElement constructor = cls.lookupConstructor(constructorName);
460 // TODO(johnniwinther): Use [Name] for lookup. 467 // TODO(johnniwinther): Use [Name] for lookup.
461 if (Name.isPrivateName(constructorName) && 468 if (Name.isPrivateName(constructorName) &&
462 resolver.enclosingElement.library != cls.library) { 469 resolver.enclosingElement.library != cls.library) {
463 result = null; 470 constructor = null;
464 } 471 }
465 if (result == null) { 472 if (constructor == null) {
466 String fullConstructorName = Elements.constructorNameForDiagnostics( 473 String fullConstructorName =
467 cls.name, 474 Elements.constructorNameForDiagnostics(cls.name, constructorName);
468 constructorName); 475 return reportAndCreateErroneousConstructorElement(
469 return failOrReturnErroneousConstructorElement(
470 diagnosticNode, 476 diagnosticNode,
477 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type,
471 cls, constructorName, 478 cls, constructorName,
472 MessageKind.CANNOT_FIND_CONSTRUCTOR, 479 MessageKind.CANNOT_FIND_CONSTRUCTOR,
473 {'constructorName': fullConstructorName}, 480 {'constructorName': fullConstructorName},
474 missingConstructor: true); 481 missingConstructor: true);
475 } else if (inConstContext && !result.isConst) { 482 } else if (inConstContext && !constructor.isConst) {
476 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 483 compiler.reportError(
477 } 484 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
478 return result; 485 return new ConstructorResult(
479 } 486 ConstructorResultKind.NON_CONSTANT, constructor, type);
480 487 } else {
481 Element visitNewExpression(NewExpression node) { 488 if (constructor.isGenerativeConstructor) {
482 inConstContext = node.isConst; 489 if (cls.isAbstract) {
490 compiler.reportWarning(
491 diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
492 registry.registerAbstractClassInstantiation();
493 return new ConstructorResult(
494 ConstructorResultKind.ABSTRACT, constructor, type);
495 } else {
496 return new ConstructorResult(
497 ConstructorResultKind.GENERATIVE, constructor, type);
498 }
499 } else {
500 assert(invariant(diagnosticNode, constructor.isFactoryConstructor,
501 message: "Unexpected constructor $constructor."));
502 return new ConstructorResult(
503 ConstructorResultKind.FACTORY, constructor, type);
504 }
505 }
506 }
507
508 ConstructorResult visitNewExpression(NewExpression node) {
483 Node selector = node.send.selector; 509 Node selector = node.send.selector;
484 Element element = visit(selector); 510 ConstructorResult result = visit(selector);
485 assert(invariant(selector, element != null, 511 assert(invariant(selector, result != null,
486 message: 'No element return for $selector.')); 512 message: 'No result returned for $selector.'));
487 return finishConstructorReference(element, node.send.selector, node); 513 return finishConstructorReference(result, node.send.selector, node);
488 } 514 }
489 515
490 /// Finishes resolution of a constructor reference and records the 516 /// Finishes resolution of a constructor reference and records the
491 /// type of the constructed instance on [expression]. 517 /// type of the constructed instance on [expression].
492 FunctionElement finishConstructorReference(Element element, 518 ConstructorResult finishConstructorReference(
493 Node diagnosticNode, 519 ConstructorResult result,
494 Node expression) { 520 Node diagnosticNode,
495 assert(invariant(diagnosticNode, element != null, 521 Node expression) {
496 message: 'No element return for $diagnosticNode.')); 522 assert(invariant(diagnosticNode, result != null,
523 message: 'No result returned for $diagnosticNode.'));
524
525 if (result.kind != null) {
526 resolver.registry.setType(expression, result.type);
527 return result;
528 }
529
497 // Find the unnamed constructor if the reference resolved to a 530 // Find the unnamed constructor if the reference resolved to a
498 // class. 531 // class.
499 if (!Elements.isUnresolved(element) && !element.isConstructor) { 532 if (result.type != null) {
500 if (element.isClass) { 533 // The unnamed constructor may not exist, so [e] may become unresolved.
501 ClassElement cls = element; 534 result = resolveConstructor(result.type, diagnosticNode, '');
502 cls.ensureResolved(compiler); 535 } else {
503 // The unnamed constructor may not exist, so [e] may become unresolved. 536 Element element = result.element;
504 element = resolveConstructor(cls, diagnosticNode, ''); 537 if (element.isErroneous) {
538 result = constructorResultForErroneous(diagnosticNode, element);
505 } else { 539 } else {
506 element = failOrReturnErroneousConstructorElement( 540 result = reportAndCreateErroneousConstructorElement(
507 diagnosticNode, 541 diagnosticNode,
542 ConstructorResultKind.INVALID_TYPE, null,
508 element, element.name, 543 element, element.name,
509 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}); 544 MessageKind.NOT_A_TYPE, {'node': diagnosticNode});
510 } 545 }
511 } else if (element.isErroneous && element is! ErroneousElementX) { 546 }
512 // Parser error. The error has already been reported. 547 resolver.registry.setType(expression, result.type);
513 element = new ErroneousConstructorElementX( 548 return result;
514 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}, 549 }
515 element.name, element); 550
516 registry.registerThrowRuntimeError(); 551 ConstructorResult visitTypeAnnotation(TypeAnnotation node) {
517 }
518
519 if (type == null) {
520 if (Elements.isUnresolved(element)) {
521 type = const DynamicType();
522 } else {
523 type = element.enclosingClass.rawType;
524 }
525 }
526 resolver.registry.setType(expression, type);
527 return element;
528 }
529
530 Element visitTypeAnnotation(TypeAnnotation node) {
531 assert(invariant(node, type == null));
532 // This is not really resolving a type-annotation, but the name of the 552 // This is not really resolving a type-annotation, but the name of the
533 // constructor. Therefore we allow deferred types. 553 // constructor. Therefore we allow deferred types.
534 type = resolver.resolveTypeAnnotation(node, 554 DartType type = resolver.resolveTypeAnnotation(
535 malformedIsError: inConstContext, 555 node,
536 deferredIsMalformed: false); 556 malformedIsError: inConstContext,
557 deferredIsMalformed: false);
537 registry.registerRequiredType(type, resolver.enclosingElement); 558 registry.registerRequiredType(type, resolver.enclosingElement);
538 return type.element; 559 return constructorResultForType(node, type);
539 } 560 }
540 561
541 Element visitSend(Send node) { 562 ConstructorResult visitSend(Send node) {
542 Element element = visit(node.receiver); 563 ConstructorResult receiver = visit(node.receiver);
543 assert(invariant(node.receiver, element != null, 564 assert(invariant(node.receiver, receiver != null,
544 message: 'No element return for $node.receiver.')); 565 message: 'No result returned for $node.receiver.'));
545 if (Elements.isUnresolved(element)) return element; 566 if (receiver.kind != null) {
567 assert(invariant(node, receiver.element.isErroneous,
568 message: "Unexpected prefix result: $receiver."));
569 // We have already found an error.
570 return receiver;
571 }
572
546 Identifier name = node.selector.asIdentifier(); 573 Identifier name = node.selector.asIdentifier();
547 if (name == null) internalError(node.selector, 'unexpected node'); 574 if (name == null) internalError(node.selector, 'unexpected node');
548 575
549 if (element.isClass) { 576 if (receiver.type != null) {
550 ClassElement cls = element; 577 if (receiver.type.isInterfaceType) {
551 cls.ensureResolved(compiler); 578 return resolveConstructor(receiver.type, name, name.source);
552 return resolveConstructor(cls, name, name.source); 579 } else {
553 } else if (element.isPrefix) { 580 // TODO(johnniwinther): Update the message for the different types.
554 PrefixElement prefix = element; 581 return reportAndCreateErroneousConstructorElement(
555 element = prefix.lookupLocalMember(name.source);
556 element = Elements.unwrap(element, compiler, node);
557 if (element == null) {
558 return failOrReturnErroneousConstructorElement(
559 name, 582 name,
583 ConstructorResultKind.INVALID_TYPE, null,
560 resolver.enclosingElement, name.source, 584 resolver.enclosingElement, name.source,
561 MessageKind.CANNOT_RESOLVE, {'name': name}); 585 MessageKind.NOT_A_TYPE, {'node': name});
562 } else if (!element.isClass) {
563 return failOrReturnErroneousConstructorElement(
564 name,
565 resolver.enclosingElement, name.source,
566 MessageKind.NOT_A_TYPE, {'node': name},
567 isError: true);
568 } 586 }
569 } else { 587 } else if (receiver.element.isPrefix) {
570 internalError(node.receiver, 'unexpected element $element'); 588 PrefixElement prefix = receiver.element;
571 } 589 Element member = prefix.lookupLocalMember(name.source);
572 return element; 590 return constructorResultForElement(node, name.source, member);
573 } 591 } else {
574 592 return internalError(node.receiver, 'unexpected receiver $receiver');
575 Element visitIdentifier(Identifier node) { 593 }
594 }
595
596 ConstructorResult visitIdentifier(Identifier node) {
576 String name = node.source; 597 String name = node.source;
577 Element element = resolver.reportLookupErrorIfAny( 598 Element element = resolver.reportLookupErrorIfAny(
578 lookupInScope(compiler, node, resolver.scope, name), node, name); 599 lookupInScope(compiler, node, resolver.scope, name), node, name);
579 registry.useElement(node, element); 600 registry.useElement(node, element);
580 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. 601 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
602 return constructorResultForElement(node, name, element);
603 }
604
605 /// Assumed to be called by [resolveRedirectingFactory].
606 ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
607 Node constructorReference = node.constructorReference;
608 return finishConstructorReference(visit(constructorReference),
609 constructorReference, node);
610 }
611
612 ConstructorResult constructorResultForElement(
613 Node node, String name, Element element) {
614 element = Elements.unwrap(element, compiler, node);
581 if (element == null) { 615 if (element == null) {
582 return failOrReturnErroneousConstructorElement( 616 return reportAndCreateErroneousConstructorElement(
583 node, 617 node,
618 ConstructorResultKind.INVALID_TYPE, null,
584 resolver.enclosingElement, name, 619 resolver.enclosingElement, name,
585 MessageKind.CANNOT_RESOLVE, 620 MessageKind.CANNOT_RESOLVE,
586 {'name': name}); 621 {'name': name});
587 } else if (element.isErroneous) { 622 } else if (element.isErroneous) {
588 return element; 623 return constructorResultForErroneous(node, element);
624 } else if (element.isClass) {
625 ClassElement cls = element;
626 cls.computeType(compiler);
627 return constructorResultForType(node, cls.rawType);
628 } else if (element.isPrefix) {
629 return new ConstructorResult.forElement(element);
589 } else if (element.isTypedef) { 630 } else if (element.isTypedef) {
590 element = failOrReturnErroneousConstructorElement( 631 TypedefElement typdef = element;
591 node, 632 typdef.ensureResolved(compiler);
592 resolver.enclosingElement, name, 633 return constructorResultForType(node, typdef.rawType);
593 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name},
594 isError: true);
595 } else if (element.isTypeVariable) { 634 } else if (element.isTypeVariable) {
596 element = failOrReturnErroneousConstructorElement( 635 TypeVariableElement typeVariableElement = element;
597 node, 636 return constructorResultForType(node, typeVariableElement.type);
637 } else {
638 return reportAndCreateErroneousConstructorElement(
639 node,
640 ConstructorResultKind.INVALID_TYPE, null,
641 resolver.enclosingElement, name,
642 MessageKind.NOT_A_TYPE, {'node': name});
643 }
644 }
645
646 ConstructorResult constructorResultForErroneous(
647 Node node, Element error) {
648 if (error is! ErroneousElementX) {
649 // Parser error. The error has already been reported.
650 error = new ErroneousConstructorElementX(
651 MessageKind.NOT_A_TYPE, {'node': node},
652 error.name, error);
653 registry.registerThrowRuntimeError();
654 }
655 return new ConstructorResult(
656 ConstructorResultKind.INVALID_TYPE,
657 error,
658 new MalformedType(error, null));
659 }
660
661 ConstructorResult constructorResultForType(
662 Node node,
663 DartType type) {
664 String name = type.name;
665 if (type.isMalformed) {
666 return new ConstructorResult(
667 ConstructorResultKind.INVALID_TYPE, type.element, type);
668 } else if (type.isInterfaceType) {
669 return new ConstructorResult.forType(type);
670 } else if (type.isTypedef) {
671 return reportAndCreateErroneousConstructorElement(
672 node,
673 ConstructorResultKind.INVALID_TYPE, type,
674 resolver.enclosingElement, name,
675 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name});
676 } else if (type.isTypeVariable) {
677 return reportAndCreateErroneousConstructorElement(
678 node,
679 ConstructorResultKind.INVALID_TYPE, type,
598 resolver.enclosingElement, name, 680 resolver.enclosingElement, name,
599 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, 681 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
600 {'typeVariableName': name}, 682 {'typeVariableName': name});
601 isError: true); 683 }
602 } else if (!element.isClass && !element.isPrefix) { 684 internalError(node, "Unexpected constructor type $type");
603 element = failOrReturnErroneousConstructorElement( 685 return null;
604 node, 686 }
605 resolver.enclosingElement, name, 687
606 MessageKind.NOT_A_TYPE, {'node': name},
607 isError: true);
608 }
609 return element;
610 }
611
612 /// Assumed to be called by [resolveRedirectingFactory].
613 Element visitRedirectingFactoryBody(RedirectingFactoryBody node) {
614 Node constructorReference = node.constructorReference;
615 return finishConstructorReference(visit(constructorReference),
616 constructorReference, node);
617 }
618 } 688 }
689
690 enum ConstructorResultKind {
691 GENERATIVE,
692 FACTORY,
693 ABSTRACT,
694 INVALID_TYPE,
695 UNRESOLVED_CONSTRUCTOR,
696 NON_CONSTANT,
697 }
698
699 class ConstructorResult {
700 final ConstructorResultKind kind;
701 final Element element;
702 final DartType type;
703
704 ConstructorResult(this.kind, this.element, this.type);
705
706 ConstructorResult.forElement(this.element)
707 : kind = null,
708 type = null;
709
710 ConstructorResult.forType(this.type)
711 : kind = null,
712 element = null;
713
714 String toString() {
715 StringBuffer sb = new StringBuffer();
716 sb.write('ConstructorResult(');
717 if (kind != null) {
718 sb.write('kind=$kind,');
719 sb.write('element=$element,');
720 sb.write('type=$type');
721 } else if (element != null) {
722 sb.write('element=$element');
723 } else {
724 sb.write('type=$type');
725 }
726 sb.write(')');
727 return sb.toString();
728 }
729 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/class_members.dart ('k') | pkg/compiler/lib/src/resolution/members.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698