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

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

Issue 1437463005: Compute NewStructure in resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Long line. Created 5 years, 1 month 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 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common/resolution.dart' show 8 import '../common/resolution.dart' show
9 Feature; 9 Feature;
10 import '../compiler.dart' show 10 import '../compiler.dart' show
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 diagnosticNode, kind, arguments); 496 diagnosticNode, kind, arguments);
497 } else { 497 } else {
498 reporter.reportWarningMessage( 498 reporter.reportWarningMessage(
499 diagnosticNode, kind, arguments); 499 diagnosticNode, kind, arguments);
500 } 500 }
501 ErroneousElement error = new ErroneousConstructorElementX( 501 ErroneousElement error = new ErroneousConstructorElementX(
502 kind, arguments, name, enclosing); 502 kind, arguments, name, enclosing);
503 if (type == null) { 503 if (type == null) {
504 type = new MalformedType(error, null); 504 type = new MalformedType(error, null);
505 } 505 }
506 return new ConstructorResult(resultKind, error, type); 506 return new ConstructorResult.forError(resultKind, error, type);
507 } 507 }
508 508
509 ConstructorResult resolveConstructor( 509 ConstructorResult resolveConstructor(
510 PrefixElement prefix,
510 InterfaceType type, 511 InterfaceType type,
511 Node diagnosticNode, 512 Node diagnosticNode,
512 String constructorName) { 513 String constructorName) {
513 ClassElement cls = type.element; 514 ClassElement cls = type.element;
514 cls.ensureResolved(resolution); 515 cls.ensureResolved(resolution);
515 ConstructorElement constructor = findConstructor( 516 ConstructorElement constructor = findConstructor(
516 resolver.enclosingElement.library, cls, constructorName); 517 resolver.enclosingElement.library, cls, constructorName);
517 if (constructor == null) { 518 if (constructor == null) {
518 MessageKind kind = constructorName.isEmpty 519 MessageKind kind = constructorName.isEmpty
519 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR 520 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR
520 : MessageKind.CANNOT_FIND_CONSTRUCTOR; 521 : MessageKind.CANNOT_FIND_CONSTRUCTOR;
521 return reportAndCreateErroneousConstructorElement( 522 return reportAndCreateErroneousConstructorElement(
522 diagnosticNode, 523 diagnosticNode,
523 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type, 524 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type,
524 cls, constructorName, kind, 525 cls, constructorName, kind,
525 {'className': cls.name, 'constructorName': constructorName}, 526 {'className': cls.name, 'constructorName': constructorName},
526 missingConstructor: true); 527 missingConstructor: true);
527 } else if (inConstContext && !constructor.isConst) { 528 } else if (inConstContext && !constructor.isConst) {
528 reporter.reportErrorMessage( 529 reporter.reportErrorMessage(
529 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 530 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
530 return new ConstructorResult( 531 return new ConstructorResult.forError(
531 ConstructorResultKind.NON_CONSTANT, constructor, type); 532 ConstructorResultKind.NON_CONSTANT, constructor, type);
532 } else { 533 } else {
534 if (cls.isEnumClass && resolver.currentClass != cls) {
535 return reportAndCreateErroneousConstructorElement(
536 diagnosticNode,
537 ConstructorResultKind.INVALID_TYPE, type,
538 cls, constructorName,
539 MessageKind.CANNOT_INSTANTIATE_ENUM,
540 {'enumName': cls.name},
541 isError: true);
542 }
533 if (constructor.isGenerativeConstructor) { 543 if (constructor.isGenerativeConstructor) {
534 if (cls.isAbstract) { 544 if (cls.isAbstract) {
535 reporter.reportWarningMessage( 545 reporter.reportWarningMessage(
536 diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION); 546 diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
537 registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION); 547 registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION);
538 return new ConstructorResult( 548 return new ConstructorResult(
539 ConstructorResultKind.ABSTRACT, constructor, type); 549 ConstructorResultKind.ABSTRACT, prefix, constructor, type);
540 } else { 550 } else {
541 return new ConstructorResult( 551 return new ConstructorResult(
542 ConstructorResultKind.GENERATIVE, constructor, type); 552 ConstructorResultKind.GENERATIVE, prefix, constructor, type);
543 } 553 }
544 } else { 554 } else {
545 assert(invariant(diagnosticNode, constructor.isFactoryConstructor, 555 assert(invariant(diagnosticNode, constructor.isFactoryConstructor,
546 message: "Unexpected constructor $constructor.")); 556 message: "Unexpected constructor $constructor."));
547 return new ConstructorResult( 557 return new ConstructorResult(
548 ConstructorResultKind.FACTORY, constructor, type); 558 ConstructorResultKind.FACTORY, prefix, constructor, type);
549 } 559 }
550 } 560 }
551 } 561 }
552 562
553 ConstructorResult visitNewExpression(NewExpression node) { 563 ConstructorResult visitNewExpression(NewExpression node) {
554 Node selector = node.send.selector; 564 Node selector = node.send.selector;
555 ConstructorResult result = visit(selector); 565 ConstructorResult result = visit(selector);
556 assert(invariant(selector, result != null, 566 assert(invariant(selector, result != null,
557 message: 'No result returned for $selector.')); 567 message: 'No result returned for $selector.'));
558 return finishConstructorReference(result, node.send.selector, node); 568 return finishConstructorReference(result, node.send.selector, node);
(...skipping 10 matching lines...) Expand all
569 579
570 if (result.kind != null) { 580 if (result.kind != null) {
571 resolver.registry.setType(expression, result.type); 581 resolver.registry.setType(expression, result.type);
572 return result; 582 return result;
573 } 583 }
574 584
575 // Find the unnamed constructor if the reference resolved to a 585 // Find the unnamed constructor if the reference resolved to a
576 // class. 586 // class.
577 if (result.type != null) { 587 if (result.type != null) {
578 // The unnamed constructor may not exist, so [e] may become unresolved. 588 // The unnamed constructor may not exist, so [e] may become unresolved.
579 result = resolveConstructor(result.type, diagnosticNode, ''); 589 result = resolveConstructor(
590 result.prefix, result.type, diagnosticNode, '');
580 } else { 591 } else {
581 Element element = result.element; 592 Element element = result.element;
582 if (element.isMalformed) { 593 if (element.isMalformed) {
583 result = constructorResultForErroneous(diagnosticNode, element); 594 result = constructorResultForErroneous(diagnosticNode, element);
584 } else { 595 } else {
585 result = reportAndCreateErroneousConstructorElement( 596 result = reportAndCreateErroneousConstructorElement(
586 diagnosticNode, 597 diagnosticNode,
587 ConstructorResultKind.INVALID_TYPE, null, 598 ConstructorResultKind.INVALID_TYPE, null,
588 element, element.name, 599 element, element.name,
589 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}); 600 MessageKind.NOT_A_TYPE, {'node': diagnosticNode});
590 } 601 }
591 } 602 }
592 resolver.registry.setType(expression, result.type); 603 resolver.registry.setType(expression, result.type);
593 return result; 604 return result;
594 } 605 }
595 606
596 ConstructorResult visitTypeAnnotation(TypeAnnotation node) { 607 ConstructorResult visitTypeAnnotation(TypeAnnotation node) {
597 // This is not really resolving a type-annotation, but the name of the 608 // This is not really resolving a type-annotation, but the name of the
598 // constructor. Therefore we allow deferred types. 609 // constructor. Therefore we allow deferred types.
599 DartType type = resolver.resolveTypeAnnotation( 610 DartType type = resolver.resolveTypeAnnotation(
600 node, 611 node,
601 malformedIsError: inConstContext, 612 malformedIsError: inConstContext,
602 deferredIsMalformed: false); 613 deferredIsMalformed: false);
603 return constructorResultForType(node, type); 614 Send send = node.typeName.asSend();
615 PrefixElement prefix;
616 if (send != null) {
617 // The type name is of the form [: prefix . identifier :].
618 String name = send.receiver.asIdentifier().source;
619 Element element = resolver.reportLookupErrorIfAny(
620 lookupInScope(reporter, send, resolver.scope, name), node, name);
621 if (element != null && element.isPrefix) {
622 prefix = element;
623 }
624 }
625 return constructorResultForType(node, type, prefix: prefix);
604 } 626 }
605 627
606 ConstructorResult visitSend(Send node) { 628 ConstructorResult visitSend(Send node) {
607 ConstructorResult receiver = visit(node.receiver); 629 ConstructorResult receiver = visit(node.receiver);
608 assert(invariant(node.receiver, receiver != null, 630 assert(invariant(node.receiver, receiver != null,
609 message: 'No result returned for $node.receiver.')); 631 message: 'No result returned for $node.receiver.'));
610 if (receiver.kind != null) { 632 if (receiver.kind != null) {
611 assert(invariant(node, receiver.element.isMalformed, 633 assert(invariant(node, receiver.element.isMalformed,
612 message: "Unexpected prefix result: $receiver.")); 634 message: "Unexpected prefix result: $receiver."));
613 // We have already found an error. 635 // We have already found an error.
614 return receiver; 636 return receiver;
615 } 637 }
616 638
617 Identifier name = node.selector.asIdentifier(); 639 Identifier name = node.selector.asIdentifier();
618 if (name == null) { 640 if (name == null) {
619 reporter.internalError(node.selector, 'unexpected node'); 641 reporter.internalError(node.selector, 'unexpected node');
620 } 642 }
621 643
622 if (receiver.type != null) { 644 if (receiver.type != null) {
623 if (receiver.type.isInterfaceType) { 645 if (receiver.type.isInterfaceType) {
624 return resolveConstructor(receiver.type, name, name.source); 646 return resolveConstructor(
647 receiver.prefix, receiver.type, name, name.source);
625 } else { 648 } else {
626 // TODO(johnniwinther): Update the message for the different types. 649 // TODO(johnniwinther): Update the message for the different types.
627 return reportAndCreateErroneousConstructorElement( 650 return reportAndCreateErroneousConstructorElement(
628 name, 651 name,
629 ConstructorResultKind.INVALID_TYPE, null, 652 ConstructorResultKind.INVALID_TYPE, null,
630 resolver.enclosingElement, name.source, 653 resolver.enclosingElement, name.source,
631 MessageKind.NOT_A_TYPE, {'node': name}); 654 MessageKind.NOT_A_TYPE, {'node': name});
632 } 655 }
633 } else if (receiver.element.isPrefix) { 656 } else if (receiver.element.isPrefix) {
634 PrefixElement prefix = receiver.element; 657 PrefixElement prefix = receiver.element;
635 Element member = prefix.lookupLocalMember(name.source); 658 Element member = prefix.lookupLocalMember(name.source);
636 return constructorResultForElement(node, name.source, member); 659 return constructorResultForElement(
660 node, name.source, member, prefix: prefix);
637 } else { 661 } else {
638 return reporter.internalError( 662 return reporter.internalError(
639 node.receiver, 'unexpected receiver $receiver'); 663 node.receiver, 'unexpected receiver $receiver');
640 } 664 }
641 } 665 }
642 666
643 ConstructorResult visitIdentifier(Identifier node) { 667 ConstructorResult visitIdentifier(Identifier node) {
644 String name = node.source; 668 String name = node.source;
645 Element element = resolver.reportLookupErrorIfAny( 669 Element element = resolver.reportLookupErrorIfAny(
646 lookupInScope(reporter, node, resolver.scope, name), node, name); 670 lookupInScope(reporter, node, resolver.scope, name), node, name);
647 registry.useElement(node, element); 671 registry.useElement(node, element);
648 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. 672 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
649 return constructorResultForElement(node, name, element); 673 return constructorResultForElement(node, name, element);
650 } 674 }
651 675
652 /// Assumed to be called by [resolveRedirectingFactory]. 676 /// Assumed to be called by [resolveRedirectingFactory].
653 ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) { 677 ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
654 Node constructorReference = node.constructorReference; 678 Node constructorReference = node.constructorReference;
655 return finishConstructorReference(visit(constructorReference), 679 return finishConstructorReference(visit(constructorReference),
656 constructorReference, node); 680 constructorReference, node);
657 } 681 }
658 682
659 ConstructorResult constructorResultForElement( 683 ConstructorResult constructorResultForElement(
660 Node node, String name, Element element) { 684 Node node, String name, Element element,
685 {PrefixElement prefix}) {
661 element = Elements.unwrap(element, reporter, node); 686 element = Elements.unwrap(element, reporter, node);
662 if (element == null) { 687 if (element == null) {
663 return reportAndCreateErroneousConstructorElement( 688 return reportAndCreateErroneousConstructorElement(
664 node, 689 node,
665 ConstructorResultKind.INVALID_TYPE, null, 690 ConstructorResultKind.INVALID_TYPE, null,
666 resolver.enclosingElement, name, 691 resolver.enclosingElement, name,
667 MessageKind.CANNOT_RESOLVE, 692 MessageKind.CANNOT_RESOLVE,
668 {'name': name}); 693 {'name': name});
669 } else if (element.isMalformed) { 694 } else if (element.isMalformed) {
670 return constructorResultForErroneous(node, element); 695 return constructorResultForErroneous(node, element);
671 } else if (element.isClass) { 696 } else if (element.isClass) {
672 ClassElement cls = element; 697 ClassElement cls = element;
673 cls.computeType(resolution); 698 cls.computeType(resolution);
674 return constructorResultForType(node, cls.rawType); 699 return constructorResultForType(node, cls.rawType, prefix: prefix);
675 } else if (element.isPrefix) { 700 } else if (element.isPrefix) {
676 return new ConstructorResult.forElement(element); 701 return new ConstructorResult.forElement(element);
677 } else if (element.isTypedef) { 702 } else if (element.isTypedef) {
678 TypedefElement typdef = element; 703 TypedefElement typdef = element;
679 typdef.ensureResolved(resolution); 704 typdef.ensureResolved(resolution);
680 return constructorResultForType(node, typdef.rawType); 705 return constructorResultForType(node, typdef.rawType);
681 } else if (element.isTypeVariable) { 706 } else if (element.isTypeVariable) {
682 TypeVariableElement typeVariableElement = element; 707 TypeVariableElement typeVariableElement = element;
683 return constructorResultForType(node, typeVariableElement.type); 708 return constructorResultForType(node, typeVariableElement.type);
684 } else { 709 } else {
685 return reportAndCreateErroneousConstructorElement( 710 return reportAndCreateErroneousConstructorElement(
686 node, 711 node,
687 ConstructorResultKind.INVALID_TYPE, null, 712 ConstructorResultKind.INVALID_TYPE, null,
688 resolver.enclosingElement, name, 713 resolver.enclosingElement, name,
689 MessageKind.NOT_A_TYPE, {'node': name}); 714 MessageKind.NOT_A_TYPE, {'node': name});
690 } 715 }
691 } 716 }
692 717
693 ConstructorResult constructorResultForErroneous( 718 ConstructorResult constructorResultForErroneous(
694 Node node, Element error) { 719 Node node, Element error) {
695 if (error is! ErroneousElementX) { 720 if (error is! ErroneousElementX) {
696 // Parser error. The error has already been reported. 721 // Parser error. The error has already been reported.
697 error = new ErroneousConstructorElementX( 722 error = new ErroneousConstructorElementX(
698 MessageKind.NOT_A_TYPE, {'node': node}, 723 MessageKind.NOT_A_TYPE, {'node': node},
699 error.name, error); 724 error.name, error);
700 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); 725 registry.registerFeature(Feature.THROW_RUNTIME_ERROR);
701 } 726 }
702 return new ConstructorResult( 727 return new ConstructorResult.forError(
703 ConstructorResultKind.INVALID_TYPE, 728 ConstructorResultKind.INVALID_TYPE,
704 error, 729 error,
705 new MalformedType(error, null)); 730 new MalformedType(error, null));
706 } 731 }
707 732
708 ConstructorResult constructorResultForType( 733 ConstructorResult constructorResultForType(
709 Node node, 734 Node node,
710 DartType type) { 735 DartType type,
736 {PrefixElement prefix}) {
711 String name = type.name; 737 String name = type.name;
712 if (type.isMalformed) { 738 if (type.isMalformed) {
713 return new ConstructorResult( 739 return new ConstructorResult.forError(
714 ConstructorResultKind.INVALID_TYPE, type.element, type); 740 ConstructorResultKind.INVALID_TYPE, type.element, type);
715 } else if (type.isInterfaceType) { 741 } else if (type.isInterfaceType) {
716 return new ConstructorResult.forType(type); 742 return new ConstructorResult.forType(prefix, type);
717 } else if (type.isTypedef) { 743 } else if (type.isTypedef) {
718 return reportAndCreateErroneousConstructorElement( 744 return reportAndCreateErroneousConstructorElement(
719 node, 745 node,
720 ConstructorResultKind.INVALID_TYPE, type, 746 ConstructorResultKind.INVALID_TYPE, type,
721 resolver.enclosingElement, name, 747 resolver.enclosingElement, name,
722 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name}); 748 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name});
723 } else if (type.isTypeVariable) { 749 } else if (type.isTypeVariable) {
724 return reportAndCreateErroneousConstructorElement( 750 return reportAndCreateErroneousConstructorElement(
725 node, 751 node,
726 ConstructorResultKind.INVALID_TYPE, type, 752 ConstructorResultKind.INVALID_TYPE, type,
727 resolver.enclosingElement, name, 753 resolver.enclosingElement, name,
728 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, 754 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
729 {'typeVariableName': name}); 755 {'typeVariableName': name});
730 } 756 }
731 return reporter.internalError(node, "Unexpected constructor type $type"); 757 return reporter.internalError(node, "Unexpected constructor type $type");
732 } 758 }
733 759
734 } 760 }
735 761
736 enum ConstructorResultKind { 762 enum ConstructorResultKind {
737 GENERATIVE, 763 GENERATIVE,
738 FACTORY, 764 FACTORY,
739 ABSTRACT, 765 ABSTRACT,
740 INVALID_TYPE, 766 INVALID_TYPE,
741 UNRESOLVED_CONSTRUCTOR, 767 UNRESOLVED_CONSTRUCTOR,
742 NON_CONSTANT, 768 NON_CONSTANT,
sigurdm 2015/11/11 08:24:52 Add comment to explain what NON_CONSTANT means? Is
Johnni Winther 2015/11/11 09:56:29 Done.
743 } 769 }
744 770
745 class ConstructorResult { 771 class ConstructorResult {
sigurdm 2015/11/11 08:24:52 Add dartdoc
Johnni Winther 2015/11/11 09:56:29 Done.
772 final PrefixElement prefix;
Johnni Winther 2015/11/10 13:42:20 This prepares for handling of deferred access whic
sigurdm 2015/11/11 08:24:51 Would it make sense to call it deferredPrefix and
Johnni Winther 2015/11/11 09:56:29 I'd rather have receivers test `result.isDeferred`
746 final ConstructorResultKind kind; 773 final ConstructorResultKind kind;
747 final Element element; 774 final Element element;
sigurdm 2015/11/11 08:24:52 Could this be a `ConstructorElement`?
748 final DartType type; 775 final DartType type;
749 776
750 ConstructorResult(this.kind, this.element, this.type); 777 ConstructorResult(this.kind, this.prefix, this.element, this.type);
778
779 ConstructorResult.forError(this.kind, this.element, this.type)
780 : prefix = null;
751 781
752 ConstructorResult.forElement(this.element) 782 ConstructorResult.forElement(this.element)
sigurdm 2015/11/11 08:24:52 Add dartdoc
Johnni Winther 2015/11/11 09:56:29 Done.
753 : kind = null, 783 : prefix = null,
784 kind = null,
754 type = null; 785 type = null;
755 786
756 ConstructorResult.forType(this.type) 787 ConstructorResult.forType(this.prefix, this.type)
sigurdm 2015/11/11 08:24:52 add dartdoc
Johnni Winther 2015/11/11 09:56:29 Done.
757 : kind = null, 788 : kind = null,
758 element = null; 789 element = null;
759 790
791 bool get isDeferred => prefix != null && prefix.isDeferred;
792
760 String toString() { 793 String toString() {
761 StringBuffer sb = new StringBuffer(); 794 StringBuffer sb = new StringBuffer();
762 sb.write('ConstructorResult('); 795 sb.write('ConstructorResult(');
763 if (kind != null) { 796 if (kind != null) {
764 sb.write('kind=$kind,'); 797 sb.write('kind=$kind,');
798 if (prefix != null) {
799 sb.write('prefix=$prefix,');
800 }
765 sb.write('element=$element,'); 801 sb.write('element=$element,');
766 sb.write('type=$type'); 802 sb.write('type=$type');
767 } else if (element != null) { 803 } else if (element != null) {
768 sb.write('element=$element'); 804 sb.write('element=$element');
769 } else { 805 } else {
806 if (prefix != null) {
807 sb.write('prefix=$prefix,');
808 }
770 sb.write('type=$type'); 809 sb.write('type=$type');
771 } 810 }
772 sb.write(')'); 811 sb.write(')');
773 return sb.toString(); 812 return sb.toString();
774 } 813 }
775 } 814 }
776 815
777 /// Lookup the [constructorName] constructor in [cls] and normalize the result 816 /// Lookup the [constructorName] constructor in [cls] and normalize the result
778 /// with respect to privacy and patching. 817 /// with respect to privacy and patching.
779 ConstructorElement findConstructor( 818 ConstructorElement findConstructor(
780 LibraryElement currentLibrary, 819 LibraryElement currentLibrary,
781 ClassElement cls, 820 ClassElement cls,
782 String constructorName) { 821 String constructorName) {
sigurdm 2015/11/11 08:24:52 Not this CL. This could take a Name instead of a
Johnni Winther 2015/11/11 09:56:29 Acknowledged.
783 if (Name.isPrivateName(constructorName) && 822 if (Name.isPrivateName(constructorName) &&
784 currentLibrary.library != cls.library) { 823 currentLibrary.library != cls.library) {
785 // TODO(johnniwinther): Report a special error on unaccessible private 824 // TODO(johnniwinther): Report a special error on unaccessible private
786 // constructors. 825 // constructors.
787 return null; 826 return null;
788 } 827 }
789 // TODO(johnniwinther): Use [Name] for lookup. 828 // TODO(johnniwinther): Use [Name] for lookup.
790 ConstructorElement constructor = cls.lookupConstructor(constructorName); 829 ConstructorElement constructor = cls.lookupConstructor(constructorName);
791 if (constructor != null) { 830 if (constructor != null) {
792 constructor = constructor.declaration; 831 constructor = constructor.declaration;
793 } 832 }
794 return constructor; 833 return constructor;
795 } 834 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698