Chromium Code Reviews| Index: lib/compiler/implementation/resolver.dart |
| diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart |
| index 5d7e76f1f8f7b44f032af4ee7efa6073981c5d86..a6f5e638992ad4cc0202acd46e0c6499fe6f23ff 100644 |
| --- a/lib/compiler/implementation/resolver.dart |
| +++ b/lib/compiler/implementation/resolver.dart |
| @@ -591,9 +591,114 @@ class StatementScope { |
| } |
| } |
| +class TypeResolver { |
| + final Compiler compiler; |
| + TypeResolver(this.compiler); |
| + |
| + Element resolveTypeName(Scope context, TypeAnnotation node) { |
| + Identifier typeName = node.typeName.asIdentifier(); |
| + Send send = node.typeName.asSend(); |
| + if (send !== null) { |
| + typeName = send.selector; |
| + } |
| + if (typeName.source == Types.VOID) { |
| + return compiler.types.voidType.element; |
| + } else if (send !== null) { |
| + Element e = context.lookup(send.receiver.asIdentifier().source); |
| + if (e !== null && e.kind === ElementKind.PREFIX) { |
| + // The receiver is a prefix. Lookup in the imported members. |
| + PrefixElement prefix = e; |
| + return prefix.lookupLocalMember(typeName.source); |
| + } else if (e !== null && e.kind === ElementKind.CLASS) { |
| + // The receiver is the class part of a named constructor. |
| + return e; |
| + } else { |
| + return null; |
| + } |
| + } else { |
| + return context.lookup(typeName.source); |
| + } |
| + } |
| + |
| + Type resolveTypeAnnotation(TypeAnnotation node, |
| + [Scope inContext, ClassElement inClass, |
| + onFailure(Node, MessageKind, [List arguments]), |
| + whenResolved(Node, Type)]) { |
| + if (onFailure === null) { |
| + onFailure = (n, k, [arguments]) => {}; |
|
ngeoffray
2012/06/06 11:12:26
Returns a map? :-)
karlklose
2012/06/06 11:43:37
Done.
|
| + } |
| + if (whenResolved === null) { |
| + whenResolved = (n, t) => {}; |
|
ngeoffray
2012/06/06 11:12:26
ditto
karlklose
2012/06/06 11:43:37
Done.
|
| + } |
| + if (inClass !== null) { |
| + inContext = new ClassScope(inClass, inClass.getLibrary()); |
| + } |
| + if (inContext === null) { |
| + compiler.internalError('resolveTypeAnnotation: no scope specified'); |
| + } |
| + return resolveTypeAnnotationInContext(inContext, node, onFailure, |
| + whenResolved); |
| + } |
| + |
| + Type resolveTypeAnnotationInContext(Scope context, TypeAnnotation node, |
| + onFailure, whenResolved) { |
| + Element element = resolveTypeName(context, node); |
| + Type type; |
| + if (element === null) { |
| + onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); |
| + } else if (!element.impliesType()) { |
| + onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); |
| + } else { |
| + if (element === compiler.types.voidType.element || |
| + element === compiler.types.dynamicType.element) { |
| + type = element.computeType(compiler); |
| + } else if (element.isClass()) { |
| + ClassElement cls = element; |
| + if (!cls.isResolved) compiler.resolveClass(cls); |
| + LinkBuilder<Type> arguments = new LinkBuilder<Type>(); |
| + if (node.typeArguments !== null) { |
| + int index = 0; |
| + for (Link<Node> typeArguments = node.typeArguments.nodes; |
| + !typeArguments.isEmpty(); |
| + typeArguments = typeArguments.tail) { |
| + if (++index > cls.typeParameters.length) { |
| + onFailure(typeArguments.head, |
| + MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
| + } |
| + Type argType = resolveTypeAnnotationInContext(context, |
| + typeArguments.head, |
| + onFailure, |
| + whenResolved); |
| + arguments.addLast(argType); |
| + } |
| + if (index < cls.typeParameters.length) { |
| + onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
| + } |
| + } |
| + if (cls.typeParameters.length == 0) { |
| + // Return the canonical type if it has no type parameters. |
| + type = cls.computeType(compiler); |
| + } else { |
| + type = new InterfaceType(cls, arguments.toLink()); |
| + } |
| + } else if (element.isTypedef()) { |
| + type = element.computeType(compiler); |
| + } else if (element.isTypeVariable()) { |
| + type = element.computeType(compiler); |
| + } else { |
| + compiler.cancel("unexpected element kind ${element.kind}", |
| + node: node); |
| + } |
| + } |
| + whenResolved(node, type); |
| + return type; |
| + } |
| +} |
| + |
| class ResolverVisitor extends CommonResolverVisitor<Element> { |
| final TreeElementMapping mapping; |
| final Element enclosingElement; |
| + final TypeResolver typeResolver; |
| bool inInstanceContext; |
| Scope context; |
| ClassElement currentClass; |
| @@ -608,6 +713,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> { |
| || element.isGenerativeConstructor(), |
| this.currentClass = element.isMember() ? element.enclosingElement : null, |
| this.statementScope = new StatementScope(), |
| + typeResolver = new TypeResolver(compiler), |
| super(compiler) { |
| LibraryElement library = element.getLibrary(); |
| element = element.getEnclosingMember(); |
| @@ -1096,77 +1202,11 @@ class ResolverVisitor extends CommonResolverVisitor<Element> { |
| return result; |
| } |
| - Element resolveTypeName(TypeAnnotation node) { |
| - Identifier typeName = node.typeName.asIdentifier(); |
| - Send send = node.typeName.asSend(); |
| - if (send !== null) { |
| - typeName = send.selector; |
| - } |
| - if (typeName.source == Types.VOID) { |
| - return compiler.types.voidType.element; |
| - } else if (send !== null) { |
| - Element e = context.lookup(send.receiver.asIdentifier().source); |
| - if (e !== null && e.kind === ElementKind.PREFIX) { |
| - // The receiver is a prefix. Lookup in the imported members. |
| - PrefixElement prefix = e; |
| - return prefix.lookupLocalMember(typeName.source); |
| - } else if (e !== null && e.kind === ElementKind.CLASS) { |
| - // The receiver is the class part of a named constructor. |
| - return e; |
| - } else { |
| - return null; |
| - } |
| - } else { |
| - return context.lookup(typeName.source); |
| - } |
| - } |
| - |
| Type resolveTypeAnnotation(TypeAnnotation node) { |
| Function report = typeRequired ? error : warning; |
| - Element element = resolveTypeName(node); |
| - Type type; |
| - if (element === null) { |
| - report(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); |
| - } else if (!element.impliesType()) { |
| - report(node, MessageKind.NOT_A_TYPE, [node.typeName]); |
| - } else { |
| - if (element === compiler.types.voidType.element || |
| - element === compiler.types.dynamicType.element) { |
| - type = element.computeType(compiler); |
| - } else if (element.isClass()) { |
| - ClassElement cls = element; |
| - if (!cls.isResolved) compiler.resolveClass(cls); |
| - LinkBuilder<Type> arguments = new LinkBuilder<Type>(); |
| - if (node.typeArguments !== null) { |
| - int index = 0; |
| - for (Link<Node> typeArguments = node.typeArguments.nodes; |
| - !typeArguments.isEmpty(); |
| - typeArguments = typeArguments.tail) { |
| - if (++index > cls.typeParameters.length) { |
| - report(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
| - } |
| - arguments.addLast(resolveTypeAnnotation(typeArguments.head)); |
| - } |
| - if (index < cls.typeParameters.length) { |
| - report(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
| - } |
| - } |
| - if (cls.typeParameters.length == 0) { |
| - // Return the canonical type if it has no type parameters. |
| - type = cls.computeType(compiler); |
| - } else { |
| - type = new InterfaceType(cls, arguments.toLink()); |
| - } |
| - } else if (element.isTypedef()) { |
| - type = element.computeType(compiler); |
| - } else if (element.isTypeVariable()) { |
| - type = element.computeType(compiler); |
| - } else { |
| - compiler.cancel("unexpected element kind ${element.kind}", |
| - node: node); |
| - } |
| - } |
| - return useType(node, type); |
| + return typeResolver.resolveTypeAnnotation(node, inContext: context, |
| + onFailure: report, |
| + whenResolved: useType); |
| } |
| visitModifiers(Modifiers node) { |