Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/resolution/members.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
| index e6fd47862ac1280627bedfdbbf339ae86f10a11c..9e2e458b1b6ba4d60a4a11d8c8d0372e529947fc 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
| @@ -3006,7 +3006,58 @@ class TypedefResolverVisitor extends TypeDefinitionVisitor { |
| element.alias = compiler.computeFunctionType( |
| element, element.functionSignature); |
| - // TODO(johnniwinther): Check for cyclic references in the typedef alias. |
| + void checkCyclicReference() { |
| + var visitor = new TypedefCyclicVisitor(compiler, element); |
| + visitor.visit(type); |
|
ahe
2013/04/02 08:22:39
This is probably slightly faster:
type.accept(vis
Johnni Winther
2013/04/02 09:40:14
Done.
|
| + } |
| + compiler.enqueuer.resolution.addPostProcessing(element, |
| + checkCyclicReference); |
| + } |
| +} |
| + |
| +// TODO(johnniwinther): Replace with a traversal on the AST when the type |
| +// annotations in typedef alias are stored in a [TreeElements] mapping. |
| +class TypedefCyclicVisitor extends DartTypeTraversal { |
| + final Compiler compiler; |
| + final TypedefElement element; |
| + bool hasCyclicReference = false; |
| + Link<TypedefElement> seenTypedefs = const Link<TypedefElement>(); |
| + |
| + TypedefCyclicVisitor(Compiler this.compiler, TypedefElement this.element); |
| + |
| + visitType(DartType type, _) { |
| + // Do nothing. |
| + } |
| + |
| + visitTypedefType(TypedefType type, _) { |
| + TypedefElement typedefElement = type.element; |
| + if (seenTypedefs.contains(typedefElement)) { |
| + if (!hasCyclicReference && identical(element, typedefElement)) { |
| + // Only report an error on the checked typedef to avoid generating |
| + // multiple errors for the same cyclicity. |
| + hasCyclicReference = true; |
| + if (seenTypedefs.tail.isEmpty) { |
| + // Direct cyclicity. |
|
ahe
2013/04/02 08:22:39
I don't think "cyclicity" is a word.
Johnni Winther
2013/04/02 09:40:14
It is! (and not just in my vocabulary: http://en.w
|
| + compiler.reportErrorCode(element, |
| + MessageKind.CYCLIC_TYPEDEF, {'typedefName': element.name}); |
| + } else if (seenTypedefs.tail.tail.isEmpty) { |
| + // Cyclicity through one other typedef. |
|
ahe
2013/04/02 08:22:39
"cyclicity"
Johnni Winther
2013/04/02 09:40:14
Ditto.
|
| + compiler.reportErrorCode(element, |
| + MessageKind.CYCLIC_TYPEDEF_ONE, |
| + {'typedefName': element.name, |
| + 'otherTypedefName': seenTypedefs.head.name}); |
| + } else { |
| + // Cyclicity through more than one other typedef. |
| + compiler.reportErrorCode(element, |
|
ahe
2013/04/02 08:22:39
I'd drop this error code and use:
for (TypedefEle
Johnni Winther
2013/04/02 09:40:14
Done.
|
| + MessageKind.CYCLIC_TYPEDEF_MORE, {'typedefName': element.name}); |
| + } |
| + } |
| + return; |
| + } |
| + seenTypedefs = seenTypedefs.prepend(typedefElement); |
| + visitList(type.typeArguments); |
| + visit(typedefElement.alias); |
| + seenTypedefs = seenTypedefs.tail; |
| } |
| } |