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

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

Powered by Google App Engine
This is Rietveld 408576698