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

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

Issue 27019003: Update check for cyclic typedefs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 7 years, 2 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 part of resolution; 5 part of resolution;
6 6
7 abstract class TreeElements { 7 abstract class TreeElements {
8 Element get currentElement; 8 Element get currentElement;
9 Set<Node> get superUses; 9 Set<Node> get superUses;
10 10
(...skipping 3572 matching lines...) Expand 10 before | Expand all | Expand 10 after
3583 element.functionSignature = signature; 3583 element.functionSignature = signature;
3584 3584
3585 scope = new MethodScope(scope, element); 3585 scope = new MethodScope(scope, element);
3586 signature.forEachParameter((Element element) { 3586 signature.forEachParameter((Element element) {
3587 defineElement(element.parseNode(compiler), element); 3587 defineElement(element.parseNode(compiler), element);
3588 }); 3588 });
3589 3589
3590 element.alias = compiler.computeFunctionType(element, signature); 3590 element.alias = compiler.computeFunctionType(element, signature);
3591 3591
3592 void checkCyclicReference() { 3592 void checkCyclicReference() {
3593 var visitor = new TypedefCyclicVisitor(compiler, element); 3593 element.checkCyclicReference(compiler);
3594 type.accept(visitor, null);
3595 } 3594 }
3596 addPostProcessAction(element, checkCyclicReference); 3595 addPostProcessAction(element, checkCyclicReference);
3597 } 3596 }
3598 } 3597 }
3599 3598
3600 // TODO(johnniwinther): Replace with a traversal on the AST when the type 3599 // TODO(johnniwinther): Replace with a traversal on the AST when the type
3601 // annotations in typedef alias are stored in a [TreeElements] mapping. 3600 // annotations in typedef alias are stored in a [TreeElements] mapping.
3602 class TypedefCyclicVisitor extends DartTypeVisitor { 3601 class TypedefCyclicVisitor extends DartTypeVisitor {
3603 final Compiler compiler; 3602 final Compiler compiler;
3604 final TypedefElement element; 3603 final TypedefElementX element;
3605 bool hasCyclicReference = false; 3604 bool hasCyclicReference = false;
3606 3605
3607 /// Counter for how many bounds the visitor currently has on the call-stack.
3608 /// Used to detect when to report [Messagekind.CYCLIC_TYPEDEF_TYPEVAR].
3609 int seenBoundsCount = 0;
3610
3611 Link<TypedefElement> seenTypedefs = const Link<TypedefElement>(); 3606 Link<TypedefElement> seenTypedefs = const Link<TypedefElement>();
3612 3607
3613 int seenTypedefsCount = 0; 3608 int seenTypedefsCount = 0;
3614 3609
3615 Link<TypeVariableElement> seenTypeVariables = 3610 Link<TypeVariableElement> seenTypeVariables =
3616 const Link<TypeVariableElement>(); 3611 const Link<TypeVariableElement>();
3617 3612
3618 TypedefCyclicVisitor(Compiler this.compiler, TypedefElement this.element); 3613 TypedefCyclicVisitor(Compiler this.compiler, TypedefElement this.element);
3619 3614
3620 visitType(DartType type, _) { 3615 visitType(DartType type, _) {
3621 // Do nothing. 3616 // Do nothing.
3622 } 3617 }
3623 3618
3624 visitTypedefType(TypedefType type, _) { 3619 visitTypedefType(TypedefType type, _) {
3625 TypedefElement typedefElement = type.element; 3620 TypedefElement typedefElement = type.element;
3626 if (seenTypedefs.contains(typedefElement)) { 3621 if (seenTypedefs.contains(typedefElement)) {
3627 if (!hasCyclicReference && identical(element, typedefElement)) { 3622 if (!hasCyclicReference && identical(element, typedefElement)) {
3628 // Only report an error on the checked typedef to avoid generating 3623 // Only report an error on the checked typedef to avoid generating
3629 // multiple errors for the same cyclicity. 3624 // multiple errors for the same cyclicity.
3630 hasCyclicReference = true; 3625 hasCyclicReference = true;
3631 if (seenBoundsCount > 0) { 3626 if (seenTypedefsCount == 1) {
3632 compiler.reportError(element, MessageKind.CYCLIC_TYPEDEF_TYPEVAR);
3633 } else if (seenTypedefsCount == 1) {
3634 // Direct cyclicity. 3627 // Direct cyclicity.
3635 compiler.reportError(element, 3628 compiler.reportError(element,
3636 MessageKind.CYCLIC_TYPEDEF, 3629 MessageKind.CYCLIC_TYPEDEF,
3637 {'typedefName': element.name}); 3630 {'typedefName': element.name});
3638 } else if (seenTypedefsCount == 2) { 3631 } else if (seenTypedefsCount == 2) {
3639 // Cyclicity through one other typedef. 3632 // Cyclicity through one other typedef.
3640 compiler.reportError(element, 3633 compiler.reportError(element,
3641 MessageKind.CYCLIC_TYPEDEF_ONE, 3634 MessageKind.CYCLIC_TYPEDEF_ONE,
3642 {'typedefName': element.name, 3635 {'typedefName': element.name,
3643 'otherTypedefName': seenTypedefs.head.name}); 3636 'otherTypedefName': seenTypedefs.head.name});
3644 } else { 3637 } else {
3645 // Cyclicity through more than one other typedef. 3638 // Cyclicity through more than one other typedef.
3646 for (TypedefElement cycle in seenTypedefs) { 3639 for (TypedefElement cycle in seenTypedefs) {
3647 if (!identical(typedefElement, cycle)) { 3640 if (!identical(typedefElement, cycle)) {
3648 compiler.reportError(element, 3641 compiler.reportError(element,
3649 MessageKind.CYCLIC_TYPEDEF_ONE, 3642 MessageKind.CYCLIC_TYPEDEF_ONE,
3650 {'typedefName': element.name, 3643 {'typedefName': element.name,
3651 'otherTypedefName': cycle.name}); 3644 'otherTypedefName': cycle.name});
3652 } 3645 }
3653 } 3646 }
3654 } 3647 }
3648 ErroneousElementX erroneousElement = new ErroneousElementX(
3649 MessageKind.CYCLIC_TYPEDEF,
3650 {'typedefName': element.name},
3651 element.name, element);
3652 element.alias =
3653 new MalformedType(erroneousElement, typedefElement.alias);
3654 element.hasBeenCheckedForCycles = true;
3655 } 3655 }
3656 } else { 3656 } else {
3657 seenTypedefs = seenTypedefs.prepend(typedefElement); 3657 seenTypedefs = seenTypedefs.prepend(typedefElement);
3658 seenTypedefsCount++; 3658 seenTypedefsCount++;
3659 type.visitChildren(this, null); 3659 type.visitChildren(this, null);
3660 typedefElement.alias.accept(this, null); 3660 typedefElement.alias.accept(this, null);
3661 seenTypedefs = seenTypedefs.tail; 3661 seenTypedefs = seenTypedefs.tail;
3662 seenTypedefsCount--; 3662 seenTypedefsCount--;
3663 } 3663 }
3664 } 3664 }
3665 3665
3666 visitFunctionType(FunctionType type, _) { 3666 visitFunctionType(FunctionType type, _) {
3667 type.visitChildren(this, null); 3667 type.visitChildren(this, null);
3668 } 3668 }
3669 3669
3670 visitInterfaceType(InterfaceType type, _) { 3670 visitInterfaceType(InterfaceType type, _) {
3671 type.visitChildren(this, null); 3671 type.visitChildren(this, null);
3672 } 3672 }
3673 3673
3674 visitTypeVariableType(TypeVariableType type, _) { 3674 visitTypeVariableType(TypeVariableType type, _) {
3675 TypeVariableElement typeVariableElement = type.element; 3675 TypeVariableElement typeVariableElement = type.element;
3676 if (seenTypeVariables.contains(typeVariableElement)) { 3676 if (seenTypeVariables.contains(typeVariableElement)) {
3677 // Avoid running in cycles on cyclic type variable bounds. 3677 // Avoid running in cycles on cyclic type variable bounds.
3678 // Cyclicity is reported elsewhere. 3678 // Cyclicity is reported elsewhere.
3679 return; 3679 return;
3680 } 3680 }
3681 seenTypeVariables = seenTypeVariables.prepend(typeVariableElement); 3681 seenTypeVariables = seenTypeVariables.prepend(typeVariableElement);
3682 seenBoundsCount++;
3683 typeVariableElement.bound.accept(this, null); 3682 typeVariableElement.bound.accept(this, null);
3684 seenBoundsCount--;
3685 seenTypeVariables = seenTypeVariables.tail; 3683 seenTypeVariables = seenTypeVariables.tail;
3686 } 3684 }
3687 } 3685 }
3688 3686
3689 /** 3687 /**
3690 * The implementation of [ResolverTask.resolveClass]. 3688 * The implementation of [ResolverTask.resolveClass].
3691 * 3689 *
3692 * This visitor has to be extra careful as it is building the basic 3690 * This visitor has to be extra careful as it is building the basic
3693 * element information, and cannot safely look at other elements as 3691 * element information, and cannot safely look at other elements as
3694 * this may lead to cycles. 3692 * this may lead to cycles.
(...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after
4642 return finishConstructorReference(visit(expression), 4640 return finishConstructorReference(visit(expression),
4643 expression, expression); 4641 expression, expression);
4644 } 4642 }
4645 } 4643 }
4646 4644
4647 /// Looks up [name] in [scope] and unwraps the result. 4645 /// Looks up [name] in [scope] and unwraps the result.
4648 Element lookupInScope(Compiler compiler, Node node, 4646 Element lookupInScope(Compiler compiler, Node node,
4649 Scope scope, SourceString name) { 4647 Scope scope, SourceString name) {
4650 return Elements.unwrap(scope.lookup(name), compiler, node); 4648 return Elements.unwrap(scope.lookup(name), compiler, node);
4651 } 4649 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698