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

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: Add positive test 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 3466 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698