| Index: lib/compiler/implementation/resolver.dart
|
| diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart
|
| index 1c569db76aa3ae4dd5089a5a9c735ee873db2887..f7929f2178c1414385a24ae573fc4ea00766ce23 100644
|
| --- a/lib/compiler/implementation/resolver.dart
|
| +++ b/lib/compiler/implementation/resolver.dart
|
| @@ -231,7 +231,7 @@ class ResolverTask extends CompilerTask {
|
| measure(() {
|
| ClassNode tree = element.parseNode(compiler);
|
| ClassResolverVisitor visitor =
|
| - new ClassResolverVisitor(compiler, element.getLibrary(), element);
|
| + new ClassResolverVisitor(compiler, element);
|
| visitor.visit(tree);
|
| element.isBeingResolved = false;
|
| element.isResolved = true;
|
| @@ -569,7 +569,8 @@ class CommonResolverVisitor<R> extends AbstractVisitor<R> {
|
| CommonResolverVisitor(Compiler this.compiler);
|
|
|
| R visitNode(Node node) {
|
| - cancel(node, 'internal error');
|
| + cancel(node,
|
| + 'internal error: Unhandled node: ${node.getObjectDescription()}');
|
| }
|
|
|
| R visitEmptyStatement(Node node) => null;
|
| @@ -653,6 +654,7 @@ class StatementScope {
|
| LabelElement lookupLabel(String label) {
|
| return labels.lookup(label);
|
| }
|
| +
|
| TargetElement currentBreakTarget() =>
|
| breakTargetStack.isEmpty() ? null : breakTargetStack.head;
|
|
|
| @@ -697,18 +699,23 @@ class StatementScope {
|
|
|
| class TypeResolver {
|
| final Compiler compiler;
|
| +
|
| TypeResolver(this.compiler);
|
|
|
| - Element resolveTypeName(Scope context, TypeAnnotation node) {
|
| + Element resolveTypeName(Scope scope, TypeAnnotation node) {
|
| Identifier typeName = node.typeName.asIdentifier();
|
| Send send = node.typeName.asSend();
|
| + return resolveTypeNameInternal(scope, typeName, send);
|
| + }
|
| +
|
| + Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) {
|
| if (send !== null) {
|
| typeName = send.selector;
|
| }
|
| if (typeName.source.stringValue === 'void') {
|
| return compiler.types.voidType.element;
|
| } else if (send !== null) {
|
| - Element e = context.lookup(send.receiver.asIdentifier().source);
|
| + Element e = scope.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;
|
| @@ -720,12 +727,14 @@ class TypeResolver {
|
| return null;
|
| }
|
| } else {
|
| - return context.lookup(typeName.source);
|
| + return scope.lookup(typeName.source);
|
| }
|
| }
|
|
|
| + // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean
|
| + // flags instead of closures.
|
| Type resolveTypeAnnotation(TypeAnnotation node,
|
| - [Scope inContext, ClassElement inClass,
|
| + [Scope inScope, ClassElement inClass,
|
| onFailure(Node, MessageKind, [List arguments]),
|
| whenResolved(Node, Type)]) {
|
| if (onFailure === null) {
|
| @@ -735,18 +744,18 @@ class TypeResolver {
|
| whenResolved = (n, t) {};
|
| }
|
| if (inClass !== null) {
|
| - inContext = new ClassScope(inClass, inClass.getLibrary());
|
| + inScope = inClass.buildScope();
|
| }
|
| - if (inContext === null) {
|
| + if (inScope === null) {
|
| compiler.internalError('resolveTypeAnnotation: no scope specified');
|
| }
|
| - return resolveTypeAnnotationInContext(inContext, node, onFailure,
|
| + return resolveTypeAnnotationInContext(inScope, node, onFailure,
|
| whenResolved);
|
| }
|
|
|
| - Type resolveTypeAnnotationInContext(Scope context, TypeAnnotation node,
|
| + Type resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node,
|
| onFailure, whenResolved) {
|
| - Element element = resolveTypeName(context, node);
|
| + Element element = resolveTypeName(scope, node);
|
| Type type;
|
| if (element === null) {
|
| onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
|
| @@ -769,7 +778,7 @@ class TypeResolver {
|
| onFailure(typeArguments.head,
|
| MessageKind.ADDITIONAL_TYPE_ARGUMENT);
|
| }
|
| - Type argType = resolveTypeAnnotationInContext(context,
|
| + Type argType = resolveTypeAnnotationInContext(scope,
|
| typeArguments.head,
|
| onFailure,
|
| whenResolved);
|
| @@ -804,7 +813,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| final Element enclosingElement;
|
| final TypeResolver typeResolver;
|
| bool inInstanceContext;
|
| - Scope context;
|
| + Scope scope;
|
| ClassElement currentClass;
|
| bool typeRequired = false;
|
| StatementScope statementScope;
|
| @@ -818,20 +827,14 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| this.currentClass = element.isMember() ? element.enclosingElement : null,
|
| this.statementScope = new StatementScope(),
|
| typeResolver = new TypeResolver(compiler),
|
| + scope = element.buildEnclosingScope(),
|
| super(compiler) {
|
| - LibraryElement library = element.getLibrary();
|
| - element = element.getEnclosingMember();
|
| - if (element !== null) {
|
| - context = new ClassScope(element.enclosingElement, library);
|
| - } else {
|
| - this.context = new TopScope(library);
|
| - }
|
| }
|
|
|
| Enqueuer get world() => compiler.enqueuer.resolution;
|
|
|
| Element lookup(Node node, SourceString name) {
|
| - Element result = context.lookup(name);
|
| + Element result = scope.lookup(name);
|
| if (!inInstanceContext && result != null && result.isInstanceMember()) {
|
| error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
|
| }
|
| @@ -899,7 +902,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| compiler.ensure(element !== null);
|
| mapping[node] = element;
|
| if (doAddToScope) {
|
| - Element existing = context.add(element);
|
| + Element existing = scope.add(element);
|
| if (existing != element) {
|
| error(node, MessageKind.DUPLICATE_DEFINITION, [node]);
|
| }
|
| @@ -940,7 +943,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| void setupFunction(FunctionExpression node, FunctionElement function) {
|
| - context = new MethodScope(context, function);
|
| + scope = new MethodScope(scope, function);
|
| // Put the parameters in scope.
|
| FunctionSignature functionParameters =
|
| function.computeSignature(compiler);
|
| @@ -976,10 +979,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| cancel(node, "shouldn't be called");
|
| }
|
|
|
| - visitIn(Node node, Scope scope) {
|
| - context = scope;
|
| + visitIn(Node node, Scope nestedScope) {
|
| + scope = nestedScope;
|
| Element element = visit(node);
|
| - context = context.parent;
|
| + scope = scope.parent;
|
| return element;
|
| }
|
|
|
| @@ -987,10 +990,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| * Introduces new default targets for break and continue
|
| * before visiting the body of the loop
|
| */
|
| - visitLoopBodyIn(Node loop, Node body, Scope scope) {
|
| + visitLoopBodyIn(Node loop, Node body, Scope bodyScope) {
|
| TargetElement element = getOrCreateTargetElement(loop);
|
| statementScope.enterLoop(element);
|
| - visitIn(body, scope);
|
| + visitIn(body, bodyScope);
|
| statementScope.exitLoop();
|
| if (!element.isTarget) {
|
| mapping.remove(loop);
|
| @@ -998,11 +1001,11 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| visitBlock(Block node) {
|
| - visitIn(node.statements, new BlockScope(context));
|
| + visitIn(node.statements, new BlockScope(scope));
|
| }
|
|
|
| visitDoWhile(DoWhile node) {
|
| - visitLoopBodyIn(node, node.body, new BlockScope(context));
|
| + visitLoopBodyIn(node, node.body, new BlockScope(scope));
|
| visit(node.condition);
|
| }
|
|
|
| @@ -1013,11 +1016,11 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| visitFor(For node) {
|
| - Scope scope = new BlockScope(context);
|
| - visitIn(node.initializer, scope);
|
| - visitIn(node.condition, scope);
|
| - visitIn(node.update, scope);
|
| - visitLoopBodyIn(node, node.body, scope);
|
| + Scope blockScope = new BlockScope(scope);
|
| + visitIn(node.initializer, blockScope);
|
| + visitIn(node.condition, blockScope);
|
| + visitIn(node.update, blockScope);
|
| + visitLoopBodyIn(node, node.body, blockScope);
|
| }
|
|
|
| visitFunctionDeclaration(FunctionDeclaration node) {
|
| @@ -1039,7 +1042,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
| FunctionElement enclosing = new FunctionElement.node(
|
| name, node, ElementKind.FUNCTION, new Modifiers.empty(),
|
| - context.element);
|
| + scope.element);
|
| setupFunction(node, enclosing);
|
| defineElement(node, enclosing, doAddToScope: node.name !== null);
|
|
|
| @@ -1049,7 +1052,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| visit(node.body);
|
| statementScope = oldScope;
|
|
|
| - context = context.parent;
|
| + scope = scope.parent;
|
| }
|
|
|
| visitIf(If node) {
|
| @@ -1319,7 +1322,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
|
|
| visitWhile(While node) {
|
| visit(node.condition);
|
| - visitLoopBodyIn(node, node.body, new BlockScope(context));
|
| + visitLoopBodyIn(node, node.body, new BlockScope(scope));
|
| }
|
|
|
| visitParenthesizedExpression(ParenthesizedExpression node) {
|
| @@ -1396,7 +1399,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
|
|
| Type resolveTypeAnnotation(TypeAnnotation node) {
|
| Function report = typeRequired ? error : warning;
|
| - return typeResolver.resolveTypeAnnotation(node, inContext: context,
|
| + return typeResolver.resolveTypeAnnotation(node, inScope: scope,
|
| onFailure: report,
|
| whenResolved: useType);
|
| }
|
| @@ -1481,10 +1484,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
|
|
| visitForIn(ForIn node) {
|
| visit(node.expression);
|
| - Scope scope = new BlockScope(context);
|
| + Scope blockScope = new BlockScope(scope);
|
| Node declaration = node.declaredIdentifier;
|
| - visitIn(declaration, scope);
|
| - visitLoopBodyIn(node, node.body, scope);
|
| + visitIn(declaration, blockScope);
|
| + visitLoopBodyIn(node, node.body, blockScope);
|
|
|
| // TODO(lrn): Also allow a single identifier.
|
| if ((declaration is !Send || declaration.asSend().selector is !Identifier)
|
| @@ -1604,7 +1607,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
|
|
| visitSwitchCase(SwitchCase node) {
|
| node.labelsAndCases.accept(this);
|
| - visitIn(node.statements, new BlockScope(context));
|
| + visitIn(node.statements, new BlockScope(scope));
|
| }
|
|
|
| visitCaseMatch(CaseMatch node) {
|
| @@ -1623,7 +1626,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| visitCatchBlock(CatchBlock node) {
|
| - Scope scope = new BlockScope(context);
|
| + Scope blockScope = new BlockScope(scope);
|
| if (node.formals.isEmpty()) {
|
| error(node, MessageKind.EMPTY_CATCH_DECLARATION);
|
| } else if (!node.formals.nodes.tail.isEmpty()
|
| @@ -1632,8 +1635,8 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| error(extra, MessageKind.EXTRA_CATCH_DECLARATION);
|
| }
|
| }
|
| - visitIn(node.formals, scope);
|
| - visitIn(node.block, scope);
|
| + visitIn(node.formals, blockScope);
|
| + visitIn(node.block, blockScope);
|
| }
|
|
|
| visitTypedef(Typedef node) {
|
| @@ -1642,13 +1645,14 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| }
|
|
|
| class ClassResolverVisitor extends CommonResolverVisitor<Type> {
|
| - Scope context;
|
| + Scope scope;
|
| ClassElement classElement;
|
|
|
| - ClassResolverVisitor(Compiler compiler, LibraryElement library,
|
| - ClassElement this.classElement)
|
| - : context = new TopScope(library),
|
| - super(compiler);
|
| + ClassResolverVisitor(Compiler compiler,
|
| + ClassElement classElement)
|
| + : this.classElement = classElement,
|
| + scope = classElement.buildEnclosingScope(),
|
| + super(compiler);
|
|
|
| Type visitClassNode(ClassNode node) {
|
| compiler.ensure(classElement !== null);
|
| @@ -1666,7 +1670,7 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
|
| variableType);
|
| variableType.element = variableElement;
|
| classElement.typeParameters[variableName] = variableElement;
|
| - context = new TypeVariablesScope(context, classElement);
|
| + scope = new TypeDeclarationScope(scope, classElement);
|
| }
|
| // Resolve the bounds of type variables.
|
| for (Link<Node> link = parameters; !link.isEmpty(); link = link.tail) {
|
| @@ -1733,7 +1737,7 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
|
| }
|
|
|
| Type visitIdentifier(Identifier node) {
|
| - Element element = context.lookup(node.source);
|
| + Element element = scope.lookup(node.source);
|
| if (element === null) {
|
| error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
|
| return null;
|
| @@ -1763,7 +1767,7 @@ class ClassResolverVisitor extends CommonResolverVisitor<Type> {
|
| error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
|
| return null;
|
| }
|
| - Element element = context.lookup(prefix.source);
|
| + Element element = scope.lookup(prefix.source);
|
| if (element === null || element.kind !== ElementKind.PREFIX) {
|
| error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
|
| return null;
|
| @@ -1876,7 +1880,7 @@ class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
|
| : super(compiler)
|
| {
|
| variables = new VariableListElement.node(
|
| - definitions, ElementKind.VARIABLE_LIST, resolver.context.element);
|
| + definitions, ElementKind.VARIABLE_LIST, resolver.scope.element);
|
| }
|
|
|
| SourceString visitSendSet(SendSet node) {
|
| @@ -1891,17 +1895,20 @@ class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
|
| for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
|
| SourceString name = visit(link.head);
|
| VariableElement element = new VariableElement(
|
| - name, variables, kind, resolver.context.element, node: link.head);
|
| + name, variables, kind, resolver.scope.element, node: link.head);
|
| resolver.defineElement(link.head, element);
|
| }
|
| }
|
| }
|
|
|
| +/**
|
| + * [SignatureResolver] resolves function signatures.
|
| + */
|
| class SignatureResolver extends CommonResolverVisitor<Element> {
|
| final Element enclosingElement;
|
| Link<Element> optionalParameters = const EmptyLink<Element>();
|
| int optionalParameterCount = 0;
|
| - Node currentDefinitions;
|
| + VariableDefinitions currentDefinitions;
|
|
|
| SignatureResolver(Compiler compiler, this.enclosingElement) : super(compiler);
|
|
|
| @@ -2029,6 +2036,9 @@ class SignatureResolver extends CommonResolverVisitor<Element> {
|
| return elements;
|
| }
|
|
|
| + /**
|
| + * Resolves formal parameters and return type to a [FunctionSignature].
|
| + */
|
| static FunctionSignature analyze(Compiler compiler,
|
| NodeList formalParameters,
|
| Node returnNode,
|
| @@ -2148,17 +2158,31 @@ class Scope {
|
| abstract Element lookup(SourceString name);
|
| }
|
|
|
| -class TypeVariablesScope extends Scope {
|
| - TypeVariablesScope(parent, ClassElement element) : super(parent, element);
|
| +/**
|
| + * [TypeDeclarationScope] defines the outer scope of a type declaration in
|
| + * which the declared type variables and the entities in the enclosing scope are
|
| + * available but where declared and inherited members are not available. This
|
| + * scope is only used for class/interface declarations during resolution of the
|
| + * class hierarchy. In all other cases [ClassScope] is used.
|
| + */
|
| +class TypeDeclarationScope extends Scope {
|
| + ClassElement get element() => super.element;
|
| +
|
| + TypeDeclarationScope(Scope parent, ClassElement element)
|
| + : super(parent, element);
|
| +
|
| Element add(Element newElement) {
|
| - throw "Cannot add element to TypeVariableScope";
|
| + throw "Cannot add element to TypeDeclarationScope";
|
| }
|
| +
|
| Element lookup(SourceString name) {
|
| - ClassElement cls = element;
|
| - Element result = cls.lookupTypeParameter(name);
|
| + Element result = element.lookupTypeParameter(name);
|
| if (result !== null) return result;
|
| if (parent !== null) return parent.lookup(name);
|
| }
|
| +
|
| + String toString() =>
|
| + '$element${element.typeParameters.getKeys()} > $parent';
|
| }
|
|
|
| class MethodScope extends Scope {
|
| @@ -2180,23 +2204,30 @@ class MethodScope extends Scope {
|
| elements[newElement.name] = newElement;
|
| return newElement;
|
| }
|
| +
|
| + String toString() => '$element${elements.getKeys()} > $parent';
|
| }
|
|
|
| class BlockScope extends MethodScope {
|
| BlockScope(Scope parent) : super(parent, parent.element);
|
| +
|
| + String toString() => 'block${elements.getKeys()} > $parent';
|
| }
|
|
|
| -class ClassScope extends Scope {
|
| - ClassScope(ClassElement element, LibraryElement library)
|
| - : super(new TopScope(library), element);
|
| +/**
|
| + * [ClassScope] defines the inner scope of a class/interface declaration in
|
| + * which declared members, declared type variables, entities in the enclosing
|
| + * scope and inherited members are available, in the given order.
|
| + */
|
| +class ClassScope extends TypeDeclarationScope {
|
| + ClassScope(Scope parentScope, ClassElement element)
|
| + : super(parentScope, element);
|
|
|
| Element lookup(SourceString name) {
|
| ClassElement cls = element;
|
| Element result = cls.lookupLocalMember(name);
|
| if (result !== null) return result;
|
| - result = cls.lookupTypeParameter(name);
|
| - if (result !== null) return result;
|
| - result = parent.lookup(name);
|
| + result = super.lookup(name);
|
| if (result != null) return result;
|
| return cls.lookupSuperMember(name);
|
| }
|
| @@ -2204,6 +2235,8 @@ class ClassScope extends Scope {
|
| Element add(Element newElement) {
|
| throw "Cannot add an element in a class scope";
|
| }
|
| +
|
| + String toString() => '$element > $parent';
|
| }
|
|
|
| class TopScope extends Scope {
|
| @@ -2217,4 +2250,5 @@ class TopScope extends Scope {
|
| Element add(Element newElement) {
|
| throw "Cannot add an element in the top scope";
|
| }
|
| + String toString() => '$element';
|
| }
|
|
|