| 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 3466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3477 element.functionSignature = signature; | 3477 element.functionSignature = signature; |
| 3478 | 3478 |
| 3479 scope = new MethodScope(scope, element); | 3479 scope = new MethodScope(scope, element); |
| 3480 signature.forEachParameter((Element element) { | 3480 signature.forEachParameter((Element element) { |
| 3481 defineElement(element.parseNode(compiler), element); | 3481 defineElement(element.parseNode(compiler), element); |
| 3482 }); | 3482 }); |
| 3483 | 3483 |
| 3484 element.alias = compiler.computeFunctionType(element, signature); | 3484 element.alias = compiler.computeFunctionType(element, signature); |
| 3485 | 3485 |
| 3486 void checkCyclicReference() { | 3486 void checkCyclicReference() { |
| 3487 var visitor = new TypedefCyclicVisitor(compiler, element); | 3487 element.checkCyclicReference(compiler); |
| 3488 type.accept(visitor, null); | |
| 3489 } | 3488 } |
| 3490 addPostProcessAction(element, checkCyclicReference); | 3489 addPostProcessAction(element, checkCyclicReference); |
| 3491 } | 3490 } |
| 3492 } | 3491 } |
| 3493 | 3492 |
| 3494 // TODO(johnniwinther): Replace with a traversal on the AST when the type | 3493 // TODO(johnniwinther): Replace with a traversal on the AST when the type |
| 3495 // annotations in typedef alias are stored in a [TreeElements] mapping. | 3494 // annotations in typedef alias are stored in a [TreeElements] mapping. |
| 3496 class TypedefCyclicVisitor extends DartTypeVisitor { | 3495 class TypedefCyclicVisitor extends DartTypeVisitor { |
| 3497 final Compiler compiler; | 3496 final Compiler compiler; |
| 3498 final TypedefElement element; | 3497 final TypedefElementX element; |
| 3499 bool hasCyclicReference = false; | 3498 bool hasCyclicReference = false; |
| 3500 | 3499 |
| 3501 /// Counter for how many bounds the visitor currently has on the call-stack. | |
| 3502 /// Used to detect when to report [Messagekind.CYCLIC_TYPEDEF_TYPEVAR]. | |
| 3503 int seenBoundsCount = 0; | |
| 3504 | |
| 3505 Link<TypedefElement> seenTypedefs = const Link<TypedefElement>(); | 3500 Link<TypedefElement> seenTypedefs = const Link<TypedefElement>(); |
| 3506 | 3501 |
| 3507 int seenTypedefsCount = 0; | 3502 int seenTypedefsCount = 0; |
| 3508 | 3503 |
| 3509 Link<TypeVariableElement> seenTypeVariables = | 3504 Link<TypeVariableElement> seenTypeVariables = |
| 3510 const Link<TypeVariableElement>(); | 3505 const Link<TypeVariableElement>(); |
| 3511 | 3506 |
| 3512 TypedefCyclicVisitor(Compiler this.compiler, TypedefElement this.element); | 3507 TypedefCyclicVisitor(Compiler this.compiler, TypedefElement this.element); |
| 3513 | 3508 |
| 3514 visitType(DartType type, _) { | 3509 visitType(DartType type, _) { |
| 3515 // Do nothing. | 3510 // Do nothing. |
| 3516 } | 3511 } |
| 3517 | 3512 |
| 3518 visitTypedefType(TypedefType type, _) { | 3513 visitTypedefType(TypedefType type, _) { |
| 3519 TypedefElement typedefElement = type.element; | 3514 TypedefElement typedefElement = type.element; |
| 3520 if (seenTypedefs.contains(typedefElement)) { | 3515 if (seenTypedefs.contains(typedefElement)) { |
| 3521 if (!hasCyclicReference && identical(element, typedefElement)) { | 3516 if (!hasCyclicReference && identical(element, typedefElement)) { |
| 3522 // Only report an error on the checked typedef to avoid generating | 3517 // Only report an error on the checked typedef to avoid generating |
| 3523 // multiple errors for the same cyclicity. | 3518 // multiple errors for the same cyclicity. |
| 3524 hasCyclicReference = true; | 3519 hasCyclicReference = true; |
| 3525 if (seenBoundsCount > 0) { | 3520 if (seenTypedefsCount == 1) { |
| 3526 compiler.reportError(element, MessageKind.CYCLIC_TYPEDEF_TYPEVAR); | |
| 3527 } else if (seenTypedefsCount == 1) { | |
| 3528 // Direct cyclicity. | 3521 // Direct cyclicity. |
| 3529 compiler.reportError(element, | 3522 compiler.reportError(element, |
| 3530 MessageKind.CYCLIC_TYPEDEF, | 3523 MessageKind.CYCLIC_TYPEDEF, |
| 3531 {'typedefName': element.name}); | 3524 {'typedefName': element.name}); |
| 3532 } else if (seenTypedefsCount == 2) { | 3525 } else if (seenTypedefsCount == 2) { |
| 3533 // Cyclicity through one other typedef. | 3526 // Cyclicity through one other typedef. |
| 3534 compiler.reportError(element, | 3527 compiler.reportError(element, |
| 3535 MessageKind.CYCLIC_TYPEDEF_ONE, | 3528 MessageKind.CYCLIC_TYPEDEF_ONE, |
| 3536 {'typedefName': element.name, | 3529 {'typedefName': element.name, |
| 3537 'otherTypedefName': seenTypedefs.head.name}); | 3530 'otherTypedefName': seenTypedefs.head.name}); |
| 3538 } else { | 3531 } else { |
| 3539 // Cyclicity through more than one other typedef. | 3532 // Cyclicity through more than one other typedef. |
| 3540 for (TypedefElement cycle in seenTypedefs) { | 3533 for (TypedefElement cycle in seenTypedefs) { |
| 3541 if (!identical(typedefElement, cycle)) { | 3534 if (!identical(typedefElement, cycle)) { |
| 3542 compiler.reportError(element, | 3535 compiler.reportError(element, |
| 3543 MessageKind.CYCLIC_TYPEDEF_ONE, | 3536 MessageKind.CYCLIC_TYPEDEF_ONE, |
| 3544 {'typedefName': element.name, | 3537 {'typedefName': element.name, |
| 3545 'otherTypedefName': cycle.name}); | 3538 'otherTypedefName': cycle.name}); |
| 3546 } | 3539 } |
| 3547 } | 3540 } |
| 3548 } | 3541 } |
| 3542 ErroneousElementX erroneousElement = new ErroneousElementX( |
| 3543 MessageKind.CYCLIC_TYPEDEF, |
| 3544 {'typedefName': element.name}, |
| 3545 element.name, element); |
| 3546 element.alias = |
| 3547 new MalformedType(erroneousElement, typedefElement.alias); |
| 3548 element.cyclicCheck = true; |
| 3549 } | 3549 } |
| 3550 } else { | 3550 } else { |
| 3551 seenTypedefs = seenTypedefs.prepend(typedefElement); | 3551 seenTypedefs = seenTypedefs.prepend(typedefElement); |
| 3552 seenTypedefsCount++; | 3552 seenTypedefsCount++; |
| 3553 type.visitChildren(this, null); | 3553 type.visitChildren(this, null); |
| 3554 typedefElement.alias.accept(this, null); | 3554 typedefElement.alias.accept(this, null); |
| 3555 seenTypedefs = seenTypedefs.tail; | 3555 seenTypedefs = seenTypedefs.tail; |
| 3556 seenTypedefsCount--; | 3556 seenTypedefsCount--; |
| 3557 } | 3557 } |
| 3558 } | 3558 } |
| 3559 | 3559 |
| 3560 visitFunctionType(FunctionType type, _) { | 3560 visitFunctionType(FunctionType type, _) { |
| 3561 type.visitChildren(this, null); | 3561 type.visitChildren(this, null); |
| 3562 } | 3562 } |
| 3563 | 3563 |
| 3564 visitInterfaceType(InterfaceType type, _) { | 3564 visitInterfaceType(InterfaceType type, _) { |
| 3565 type.visitChildren(this, null); | 3565 type.visitChildren(this, null); |
| 3566 } | 3566 } |
| 3567 | 3567 |
| 3568 visitTypeVariableType(TypeVariableType type, _) { | 3568 visitTypeVariableType(TypeVariableType type, _) { |
| 3569 TypeVariableElement typeVariableElement = type.element; | 3569 TypeVariableElement typeVariableElement = type.element; |
| 3570 if (seenTypeVariables.contains(typeVariableElement)) { | 3570 if (seenTypeVariables.contains(typeVariableElement)) { |
| 3571 // Avoid running in cycles on cyclic type variable bounds. | 3571 // Avoid running in cycles on cyclic type variable bounds. |
| 3572 // Cyclicity is reported elsewhere. | 3572 // Cyclicity is reported elsewhere. |
| 3573 return; | 3573 return; |
| 3574 } | 3574 } |
| 3575 seenTypeVariables = seenTypeVariables.prepend(typeVariableElement); | 3575 seenTypeVariables = seenTypeVariables.prepend(typeVariableElement); |
| 3576 seenBoundsCount++; | |
| 3577 typeVariableElement.bound.accept(this, null); | 3576 typeVariableElement.bound.accept(this, null); |
| 3578 seenBoundsCount--; | |
| 3579 seenTypeVariables = seenTypeVariables.tail; | 3577 seenTypeVariables = seenTypeVariables.tail; |
| 3580 } | 3578 } |
| 3581 } | 3579 } |
| 3582 | 3580 |
| 3583 /** | 3581 /** |
| 3584 * The implementation of [ResolverTask.resolveClass]. | 3582 * The implementation of [ResolverTask.resolveClass]. |
| 3585 * | 3583 * |
| 3586 * This visitor has to be extra careful as it is building the basic | 3584 * This visitor has to be extra careful as it is building the basic |
| 3587 * element information, and cannot safely look at other elements as | 3585 * element information, and cannot safely look at other elements as |
| 3588 * this may lead to cycles. | 3586 * this may lead to cycles. |
| (...skipping 938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4527 return finishConstructorReference(visit(expression), | 4525 return finishConstructorReference(visit(expression), |
| 4528 expression, expression); | 4526 expression, expression); |
| 4529 } | 4527 } |
| 4530 } | 4528 } |
| 4531 | 4529 |
| 4532 /// Looks up [name] in [scope] and unwraps the result. | 4530 /// Looks up [name] in [scope] and unwraps the result. |
| 4533 Element lookupInScope(Compiler compiler, Node node, | 4531 Element lookupInScope(Compiler compiler, Node node, |
| 4534 Scope scope, SourceString name) { | 4532 Scope scope, SourceString name) { |
| 4535 return Elements.unwrap(scope.lookup(name), compiler, node); | 4533 return Elements.unwrap(scope.lookup(name), compiler, node); |
| 4536 } | 4534 } |
| OLD | NEW |