| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of resolution; |
| |
| abstract class Scope { |
| /** |
| * Adds [element] to this scope. This operation is only allowed on mutable |
| * scopes such as [MethodScope] and [BlockScope]. |
| */ |
| Element add(Element element); |
| |
| /** |
| * Looks up the [Element] for [name] in this scope. |
| */ |
| Element lookup(SourceString name); |
| |
| static Scope buildEnclosingScope(Element element) { |
| return element.enclosingElement != null |
| ? element.enclosingElement.buildScope() : element.buildScope(); |
| } |
| } |
| |
| abstract class NestedScope extends Scope { |
| final Scope parent; |
| |
| NestedScope(this.parent); |
| |
| Element lookup(SourceString name) { |
| Element result = localLookup(name); |
| if (result != null) return result; |
| return parent.lookup(name); |
| } |
| |
| Element localLookup(SourceString name); |
| |
| static Scope buildEnclosingScope(Element element) { |
| return element.enclosingElement != null |
| ? element.enclosingElement.buildScope() : element.buildScope(); |
| } |
| } |
| |
| /** |
| * [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 NestedScope { |
| final TypeDeclarationElement element; |
| |
| TypeDeclarationScope(parent, this.element) |
| : super(parent) { |
| assert(parent != null); |
| } |
| |
| Element add(Element newElement) { |
| throw "Cannot add element to TypeDeclarationScope"; |
| } |
| |
| Element lookupTypeVariable(SourceString name) { |
| Link<DartType> typeVariableLink = element.typeVariables; |
| while (!typeVariableLink.isEmpty) { |
| TypeVariableType typeVariable = typeVariableLink.head; |
| if (typeVariable.name == name) { |
| return typeVariable.element; |
| } |
| typeVariableLink = typeVariableLink.tail; |
| } |
| return null; |
| } |
| |
| Element localLookup(SourceString name) => lookupTypeVariable(name); |
| |
| String toString() => |
| 'TypeDeclarationScope($element)'; |
| } |
| |
| abstract class MutableScope extends NestedScope { |
| final Map<SourceString, Element> elements; |
| |
| MutableScope(Scope parent) |
| : super(parent), |
| this.elements = new Map<SourceString, Element>() { |
| assert(parent != null); |
| } |
| |
| Element add(Element newElement) { |
| if (elements.containsKey(newElement.name)) { |
| return elements[newElement.name]; |
| } |
| elements[newElement.name] = newElement; |
| return newElement; |
| } |
| |
| Element localLookup(SourceString name) => elements[name]; |
| } |
| |
| class MethodScope extends MutableScope { |
| final Element element; |
| |
| MethodScope(Scope parent, this.element) |
| : super(parent); |
| |
| String toString() => 'MethodScope($element${elements.keys.toList()})'; |
| } |
| |
| class BlockScope extends MutableScope { |
| BlockScope(Scope parent) : super(parent); |
| |
| String toString() => 'BlockScope(${elements.keys.toList()})'; |
| } |
| |
| /** |
| * [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 { |
| ClassElement get element => super.element; |
| |
| ClassScope(Scope parentScope, ClassElement element) |
| : super(parentScope, element) { |
| assert(parent != null); |
| } |
| |
| Element localLookup(SourceString name) { |
| Element result = element.lookupLocalMember(name); |
| if (result != null) return result; |
| return super.localLookup(name); |
| } |
| |
| Element lookup(SourceString name) { |
| Element result = localLookup(name); |
| if (result != null) return result; |
| result = parent.lookup(name); |
| if (result != null) return result; |
| return element.lookupSuperMember(name); |
| } |
| |
| Element add(Element newElement) { |
| throw "Cannot add an element in a class scope"; |
| } |
| |
| String toString() => 'ClassScope($element)'; |
| } |
| |
| class LibraryScope implements Scope { |
| final LibraryElement library; |
| |
| LibraryScope(LibraryElement this.library); |
| |
| Element localLookup(SourceString name) => library.find(name); |
| Element lookup(SourceString name) => localLookup(name); |
| |
| Element add(Element newElement) { |
| throw "Cannot add an element to a library scope"; |
| } |
| |
| String toString() => 'LibraryScope($library)'; |
| } |