| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |