// Copyright (c) 2014, 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.

import 'dart:collection';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart';

/// The scope defined by a block.
class BlockScope extends EnclosedScope {
  /// Initialize a newly created scope, enclosed within the [enclosingScope],
  /// based on the given [block].
  BlockScope(Scope enclosingScope, Block block) : super(enclosingScope) {
    if (block == null) {
      throw ArgumentError("block cannot be null");
    }
    _defineElements(block);
  }

  void _defineElements(Block block) {
    for (Element element in elementsInBlock(block)) {
      define(element);
    }
  }

  /// Return the elements that are declared directly in the given [block]. This
  /// does not include elements declared in nested blocks.
  static Iterable<Element> elementsInBlock(Block block) sync* {
    NodeList<Statement> statements = block.statements;
    int statementCount = statements.length;
    for (int i = 0; i < statementCount; i++) {
      Statement statement = statements[i];
      if (statement is VariableDeclarationStatement) {
        NodeList<VariableDeclaration> variables = statement.variables.variables;
        int variableCount = variables.length;
        for (int j = 0; j < variableCount; j++) {
          yield variables[j].declaredElement;
        }
      } else if (statement is FunctionDeclarationStatement) {
        yield statement.functionDeclaration.declaredElement;
      }
    }
  }
}

/// The scope defined by a class.
class ClassScope extends EnclosedScope {
  /// Initialize a newly created scope, enclosed within the [enclosingScope],
  /// based on the given [classElement].
  ClassScope(Scope enclosingScope, ClassElement classElement)
      : super(enclosingScope) {
    if (classElement == null) {
      throw ArgumentError("class element cannot be null");
    }
    _defineMembers(classElement);
  }

  /// Define the instance members defined by the given [classElement].
  void _defineMembers(ClassElement classElement) {
    List<PropertyAccessorElement> accessors = classElement.accessors;
    int accessorLength = accessors.length;
    for (int i = 0; i < accessorLength; i++) {
      define(accessors[i]);
    }
    List<MethodElement> methods = classElement.methods;
    int methodLength = methods.length;
    for (int i = 0; i < methodLength; i++) {
      define(methods[i]);
    }
  }
}

/// The scope defined for the initializers in a constructor.
class ConstructorInitializerScope extends EnclosedScope {
  /// Initialize a newly created scope, enclosed within the [enclosingScope].
  ConstructorInitializerScope(Scope enclosingScope, ConstructorElement element)
      : super(enclosingScope) {
    _initializeFieldFormalParameters(element);
  }

  /// Initialize the local scope with all of the field formal parameters.
  void _initializeFieldFormalParameters(ConstructorElement element) {
    for (ParameterElement parameter in element.parameters) {
      if (parameter is FieldFormalParameterElement) {
        define(parameter);
      }
    }
  }
}

/// A scope that is lexically enclosed in another scope.
class EnclosedScope extends Scope {
  /// The scope in which this scope is lexically enclosed.
  @override
  final Scope enclosingScope;

  /// Initialize a newly created scope, enclosed within the [enclosingScope].
  EnclosedScope(this.enclosingScope);

  @override
  Element internalLookup(String name) {
    Element element = localLookup(name);
    if (element != null) {
      return element;
    }
    // Check enclosing scope.
    return enclosingScope.internalLookup(name);
  }

  @override
  Element _internalLookupPrefixed(String prefix, String name) {
    return enclosingScope._internalLookupPrefixed(prefix, name);
  }
}

/// The scope defined by an extension.
class ExtensionScope extends EnclosedScope {
  /// Initialize a newly created scope, enclosed within the [enclosingScope],
  /// that represents the given [_extensionElement].
  ExtensionScope(Scope enclosingScope, ExtensionElement extensionElement)
      : super(enclosingScope) {
    _defineMembers(extensionElement);
  }

  /// Define the static members defined by the given [extensionElement]. The
  /// instance members should only be found if they would be found by normal
  /// lookup on `this`.
  void _defineMembers(ExtensionElement extensionElement) {
    List<PropertyAccessorElement> accessors = extensionElement.accessors;
    int accessorLength = accessors.length;
    for (int i = 0; i < accessorLength; i++) {
      define(accessors[i]);
    }
    List<MethodElement> methods = extensionElement.methods;
    int methodLength = methods.length;
    for (int i = 0; i < methodLength; i++) {
      define(methods[i]);
    }
  }
}

/// The scope defined by a function.
class FunctionScope extends EnclosedScope {
  /// The element representing the function that defines this scope.
  final FunctionTypedElement _functionElement;

  /// A flag indicating whether the parameters have already been defined, used
  /// to prevent the parameters from being defined multiple times.
  bool _parametersDefined = false;

  /// Initialize a newly created scope, enclosed within the [enclosingScope],
  /// that represents the given [_functionElement].
  FunctionScope(Scope enclosingScope, this._functionElement)
      : super(EnclosedScope(EnclosedScope(enclosingScope))) {
    if (_functionElement == null) {
      throw ArgumentError("function element cannot be null");
    }
    _defineTypeParameters();
  }

  /// Define the parameters for the given function in the scope that encloses
  /// this function.
  void defineParameters() {
    if (_parametersDefined) {
      return;
    }
    _parametersDefined = true;
    Scope parameterScope = enclosingScope;
    List<ParameterElement> parameters = _functionElement.parameters;
    int length = parameters.length;
    for (int i = 0; i < length; i++) {
      ParameterElement parameter = parameters[i];
      if (!parameter.isInitializingFormal) {
        parameterScope.define(parameter);
      }
    }
  }

  /// Define the type parameters for the function.
  void _defineTypeParameters() {
    Scope typeParameterScope = enclosingScope.enclosingScope;
    List<TypeParameterElement> typeParameters = _functionElement.typeParameters;
    int length = typeParameters.length;
    for (int i = 0; i < length; i++) {
      TypeParameterElement typeParameter = typeParameters[i];
      typeParameterScope.define(typeParameter);
    }
  }
}

/// The scope defined by a function type alias.
class FunctionTypeScope extends EnclosedScope {
  final FunctionTypeAliasElement _typeElement;

  bool _parametersDefined = false;

  /// Initialize a newly created scope, enclosed within the [enclosingScope],
  /// that represents the given [_typeElement].
  FunctionTypeScope(Scope enclosingScope, this._typeElement)
      : super(EnclosedScope(enclosingScope)) {
    _defineTypeParameters();
  }

  /// Define the parameters for the function type alias.
  void defineParameters() {
    if (_parametersDefined) {
      return;
    }
    _parametersDefined = true;
    for (ParameterElement parameter in _typeElement.function.parameters) {
      define(parameter);
    }
  }

  /// Define the type parameters for the function type alias.
  void _defineTypeParameters() {
    Scope typeParameterScope = enclosingScope;
    for (TypeParameterElement typeParameter in _typeElement.typeParameters) {
      typeParameterScope.define(typeParameter);
    }
  }
}

/// The scope statements that can be the target of unlabeled `break` and
/// `continue` statements.
class ImplicitLabelScope {
  /// The implicit label scope associated with the top level of a function.
  static const ImplicitLabelScope ROOT = ImplicitLabelScope._(null, null);

  /// The implicit label scope enclosing this implicit label scope.
  final ImplicitLabelScope outerScope;

  /// The statement that acts as a target for break and/or continue statements
  /// at this scoping level.
  final Statement statement;

  /// Initialize a newly created scope, enclosed within the [outerScope],
  /// representing the given [statement].
  const ImplicitLabelScope._(this.outerScope, this.statement);

  /// Return the statement which should be the target of an unlabeled `break` or
  /// `continue` statement, or `null` if there is no appropriate target.
  Statement getTarget(bool isContinue) {
    if (outerScope == null) {
      // This scope represents the toplevel of a function body, so it doesn't
      // match either break or continue.
      return null;
    }
    if (isContinue && statement is SwitchStatement) {
      return outerScope.getTarget(isContinue);
    }
    return statement;
  }

  /// Initialize a newly created scope to represent a switch statement or loop
  /// nested within the current scope.  [statement] is the statement associated
  /// with the newly created scope.
  ImplicitLabelScope nest(Statement statement) =>
      ImplicitLabelScope._(this, statement);
}

/// A scope in which a single label is defined.
class LabelScope {
  /// The label scope enclosing this label scope.
  final LabelScope _outerScope;

  /// The label defined in this scope.
  final String _label;

  /// The element to which the label resolves.
  final LabelElement element;

  /// The AST node to which the label resolves.
  final AstNode node;

  /// Initialize a newly created scope, enclosed within the [_outerScope],
  /// representing the label [_label]. The [node] is the AST node the label
  /// resolves to. The [element] is the element the label resolves to.
  LabelScope(this._outerScope, this._label, this.node, this.element);

  /// Return the LabelScope which defines [targetLabel], or `null` if it is not
  /// defined in this scope.
  LabelScope lookup(String targetLabel) {
    if (_label == targetLabel) {
      return this;
    }
    return _outerScope?.lookup(targetLabel);
  }
}

/// The scope containing all of the names available from imported libraries.
class LibraryImportScope extends Scope {
  /// The element representing the library in which this scope is enclosed.
  final LibraryElement _definingLibrary;

  /// A list of the namespaces representing the names that are available in this
  /// scope from imported libraries.
  List<Namespace> _importedNamespaces;

  /// A table mapping prefixes that have been referenced to a map from the names
  /// that have been referenced to the element associated with the prefixed
  /// name.
  Map<String, Map<String, Element>> _definedPrefixedNames;

  /// Cache of public extensions defined in this library's imported namespaces.
  List<ExtensionElement> _extensions;

  /// Initialize a newly created scope representing the names imported into the
  /// [_definingLibrary].
  LibraryImportScope(this._definingLibrary) {
    _createImportedNamespaces();
  }

  @override
  List<ExtensionElement> get extensions {
    if (_extensions == null) {
      _extensions = [];
      List<ImportElement> imports = _definingLibrary.imports;
      int count = imports.length;
      for (int i = 0; i < count; i++) {
        for (var element in imports[i].namespace.definedNames.values) {
          if (element is ExtensionElement && !_extensions.contains(element)) {
            _extensions.add(element);
          }
        }
      }
    }
    return _extensions;
  }

  @override
  void define(Element element) {
    if (!Scope.isPrivateName(element.displayName)) {
      super.define(element);
    }
  }

  @override
  Element internalLookup(String name) {
    return localLookup(name);
  }

  @override
  Element localLookup(String name) {
    var element = super.localLookup(name);
    if (element != null) {
      return element;
    }

    element = _lookupInImportedNamespaces((namespace) {
      return namespace.get(name);
    });
    if (element != null) {
      defineNameWithoutChecking(name, element);
    }

    return element;
  }

  @override
  bool shouldIgnoreUndefined(Identifier node) {
    Iterable<NamespaceCombinator> getShowCombinators(
        ImportElement importElement) {
      return importElement.combinators.whereType<ShowElementCombinator>();
    }

    if (node is PrefixedIdentifier) {
      String prefix = node.prefix.name;
      String name = node.identifier.name;
      List<ImportElement> imports = _definingLibrary.imports;
      int count = imports.length;
      for (int i = 0; i < count; i++) {
        ImportElement importElement = imports[i];
        if (importElement.prefix?.name == prefix &&
            importElement.importedLibrary?.isSynthetic != false) {
          Iterable<NamespaceCombinator> showCombinators =
              getShowCombinators(importElement);
          if (showCombinators.isEmpty) {
            return true;
          }
          for (ShowElementCombinator combinator in showCombinators) {
            if (combinator.shownNames.contains(name)) {
              return true;
            }
          }
        }
      }
    } else if (node is SimpleIdentifier) {
      String name = node.name;
      List<ImportElement> imports = _definingLibrary.imports;
      int count = imports.length;
      for (int i = 0; i < count; i++) {
        ImportElement importElement = imports[i];
        if (importElement.prefix == null &&
            importElement.importedLibrary?.isSynthetic != false) {
          for (ShowElementCombinator combinator
              in getShowCombinators(importElement)) {
            if (combinator.shownNames.contains(name)) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }

  /// Create all of the namespaces associated with the libraries imported into
  /// this library. The names are not added to this scope, but are stored for
  /// later reference.
  void _createImportedNamespaces() {
    List<ImportElement> imports = _definingLibrary.imports;
    int count = imports.length;
    _importedNamespaces = List<Namespace>(count);
    for (int i = 0; i < count; i++) {
      _importedNamespaces[i] = imports[i].namespace;
    }
  }

  /// Add the given [element] to this scope without checking for duplication or
  /// hiding.
  void _definePrefixedNameWithoutChecking(
      String prefix, String name, Element element) {
    _definedPrefixedNames ??= HashMap<String, Map<String, Element>>();
    Map<String, Element> unprefixedNames = _definedPrefixedNames.putIfAbsent(
        prefix, () => HashMap<String, Element>());
    unprefixedNames[name] = element;
  }

  @override
  Element _internalLookupPrefixed(String prefix, String name) {
    Element element = _localPrefixedLookup(prefix, name);
    if (element != null) {
      return element;
    }
    element = _lookupInImportedNamespaces(
        (Namespace namespace) => namespace.getPrefixed(prefix, name));
    if (element != null) {
      _definePrefixedNameWithoutChecking(prefix, name, element);
    }
    return element;
  }

  /// Return the element with which the given [prefix] and [name] are
  /// associated, or `null` if the name is not defined within this scope.
  Element _localPrefixedLookup(String prefix, String name) {
    if (_definedPrefixedNames != null) {
      Map<String, Element> unprefixedNames = _definedPrefixedNames[prefix];
      if (unprefixedNames != null) {
        return unprefixedNames[name];
      }
    }
    return null;
  }

  Element _lookupInImportedNamespaces(
      Element Function(Namespace namespace) lookup) {
    Element result;

    bool hasPotentialConflict = false;
    for (int i = 0; i < _importedNamespaces.length; i++) {
      Element element = lookup(_importedNamespaces[i]);
      if (element != null) {
        if (result == null || result == element) {
          result = element;
        } else {
          hasPotentialConflict = true;
        }
      }
    }

    if (hasPotentialConflict) {
      var sdkElements = <Element>{};
      var nonSdkElements = <Element>{};
      for (int i = 0; i < _importedNamespaces.length; i++) {
        Element element = lookup(_importedNamespaces[i]);
        if (element != null) {
          if (element is NeverElementImpl || element.library.isInSdk) {
            sdkElements.add(element);
          } else {
            nonSdkElements.add(element);
          }
        }
      }
      if (sdkElements.length > 1 || nonSdkElements.length > 1) {
        var conflictingElements = <Element>[
          ...sdkElements,
          ...nonSdkElements,
        ];
        return MultiplyDefinedElementImpl(
            _definingLibrary.context,
            _definingLibrary.session,
            conflictingElements.first.name,
            conflictingElements);
      }
      if (nonSdkElements.isNotEmpty) {
        result = nonSdkElements.first;
      } else if (sdkElements.isNotEmpty) {
        result = sdkElements.first;
      }
    }

    return result;
  }
}

/// A scope containing all of the names defined in a given library.
class LibraryScope extends EnclosedScope {
  final List<ExtensionElement> _extensions = <ExtensionElement>[];

  /// Initialize a newly created scope representing the names defined in the
  /// [definingLibrary].
  LibraryScope(LibraryElement definingLibrary)
      : super(LibraryImportScope(definingLibrary)) {
    _defineTopLevelNames(definingLibrary);

    // For `dart:core` to be able to pass analysis, it has to have `dynamic`
    // added to its library scope. Note that this is not true of, for instance,
    // `Object`, because `Object` has a source definition which is not possible
    // for `dynamic`.
    if (definingLibrary.isDartCore) {
      define(DynamicElementImpl.instance);
    }
  }

  @override
  List<ExtensionElement> get extensions =>
      enclosingScope.extensions.toList()..addAll(_extensions);

  /// Add to this scope all of the public top-level names that are defined in
  /// the given [compilationUnit].
  void _defineLocalNames(CompilationUnitElement compilationUnit) {
    for (PropertyAccessorElement element in compilationUnit.accessors) {
      define(element);
    }
    for (ClassElement element in compilationUnit.enums) {
      define(element);
    }
    for (ExtensionElement element in compilationUnit.extensions) {
      define(element);
      _extensions.add(element);
    }
    for (FunctionElement element in compilationUnit.functions) {
      define(element);
    }
    for (FunctionTypeAliasElement element
        in compilationUnit.functionTypeAliases) {
      define(element);
    }
    for (ClassElement element in compilationUnit.mixins) {
      define(element);
    }
    for (ClassElement element in compilationUnit.types) {
      define(element);
    }
  }

  /// Add to this scope all of the names that are explicitly defined in the
  /// [definingLibrary].
  void _defineTopLevelNames(LibraryElement definingLibrary) {
    for (PrefixElement prefix in definingLibrary.prefixes) {
      define(prefix);
    }
    _defineLocalNames(definingLibrary.definingCompilationUnit);
    for (CompilationUnitElement compilationUnit in definingLibrary.parts) {
      _defineLocalNames(compilationUnit);
    }
  }
}

/// A mapping of identifiers to the elements represented by those identifiers.
/// Namespaces are the building blocks for scopes.
class Namespace {
  /// An empty namespace.
  static Namespace EMPTY = Namespace(HashMap<String, Element>());

  /// A table mapping names that are defined in this namespace to the element
  /// representing the thing declared with that name.
  final Map<String, Element> _definedNames;

  /// Initialize a newly created namespace to have the [_definedNames].
  Namespace(this._definedNames);

  /// Return a table containing the same mappings as those defined by this
  /// namespace.
  Map<String, Element> get definedNames => _definedNames;

  /// Return the element in this namespace that is available to the containing
  /// scope using the given name, or `null` if there is no such element.
  Element get(String name) => _definedNames[name];

  /// Return the element in this namespace whose name is the result of combining
  /// the [prefix] and the [name], separated by a period, or `null` if there is
  /// no such element.
  Element getPrefixed(String prefix, String name) => null;
}

/// The builder used to build a namespace. Namespace builders are thread-safe
/// and re-usable.
class NamespaceBuilder {
  /// Create a namespace representing the export namespace of the given
  /// [element].
  Namespace createExportNamespaceForDirective(ExportElement element) {
    LibraryElement exportedLibrary = element.exportedLibrary;
    if (exportedLibrary == null) {
      //
      // The exported library will be null if the URI does not reference a valid
      // library.
      //
      return Namespace.EMPTY;
    }
    Map<String, Element> exportedNames = _getExportMapping(exportedLibrary);
    exportedNames = _applyCombinators(exportedNames, element.combinators);
    return Namespace(exportedNames);
  }

  /// Create a namespace representing the export namespace of the given
  /// [library].
  Namespace createExportNamespaceForLibrary(LibraryElement library) {
    Map<String, Element> exportedNames = _getExportMapping(library);
    return Namespace(exportedNames);
  }

  /// Create a namespace representing the import namespace of the given
  /// [element].
  Namespace createImportNamespaceForDirective(ImportElement element) {
    LibraryElement importedLibrary = element.importedLibrary;
    if (importedLibrary == null) {
      //
      // The imported library will be null if the URI does not reference a valid
      // library.
      //
      return Namespace.EMPTY;
    }
    Map<String, Element> exportedNames = _getExportMapping(importedLibrary);
    exportedNames = _applyCombinators(exportedNames, element.combinators);
    PrefixElement prefix = element.prefix;
    if (prefix != null) {
      return PrefixedNamespace(prefix.name, exportedNames);
    }
    return Namespace(exportedNames);
  }

  /// Create a namespace representing the public namespace of the given
  /// [library].
  Namespace createPublicNamespaceForLibrary(LibraryElement library) {
    Map<String, Element> definedNames = HashMap<String, Element>();
    _addPublicNames(definedNames, library.definingCompilationUnit);
    for (CompilationUnitElement compilationUnit in library.parts) {
      _addPublicNames(definedNames, compilationUnit);
    }

    // For libraries that import `dart:core` with a prefix, we have to add
    // `dynamic` to the `dart:core` [Namespace] specially. Note that this is not
    // true of, for instance, `Object`, because `Object` has a source definition
    // which is not possible for `dynamic`.
    if (library.isDartCore) {
      definedNames['dynamic'] = DynamicElementImpl.instance;
      definedNames['Never'] = NeverTypeImpl.instance.element;
    }

    return Namespace(definedNames);
  }

  /// Add all of the names in the given [namespace] to the table of
  /// [definedNames].
  void _addAllFromNamespace(
      Map<String, Element> definedNames, Namespace namespace) {
    if (namespace != null) {
      definedNames.addAll(namespace.definedNames);
    }
  }

  /// Add the given [element] to the table of [definedNames] if it has a
  /// publicly visible name.
  void _addIfPublic(Map<String, Element> definedNames, Element element) {
    String name = element.name;
    if (name != null && name.isNotEmpty && !Scope.isPrivateName(name)) {
      definedNames[name] = element;
    }
  }

  /// Add to the table of [definedNames] all of the public top-level names that
  /// are defined in the given [compilationUnit].
  ///          namespace
  void _addPublicNames(Map<String, Element> definedNames,
      CompilationUnitElement compilationUnit) {
    for (PropertyAccessorElement element in compilationUnit.accessors) {
      _addIfPublic(definedNames, element);
    }
    for (ClassElement element in compilationUnit.enums) {
      _addIfPublic(definedNames, element);
    }
    for (ExtensionElement element in compilationUnit.extensions) {
      _addIfPublic(definedNames, element);
    }
    for (FunctionElement element in compilationUnit.functions) {
      _addIfPublic(definedNames, element);
    }
    for (FunctionTypeAliasElement element
        in compilationUnit.functionTypeAliases) {
      _addIfPublic(definedNames, element);
    }
    for (ClassElement element in compilationUnit.mixins) {
      _addIfPublic(definedNames, element);
    }
    for (ClassElement element in compilationUnit.types) {
      _addIfPublic(definedNames, element);
    }
  }

  /// Apply the given [combinators] to all of the names in the given table of
  /// [definedNames].
  Map<String, Element> _applyCombinators(Map<String, Element> definedNames,
      List<NamespaceCombinator> combinators) {
    for (NamespaceCombinator combinator in combinators) {
      if (combinator is HideElementCombinator) {
        definedNames = _hide(definedNames, combinator.hiddenNames);
      } else if (combinator is ShowElementCombinator) {
        definedNames = _show(definedNames, combinator.shownNames);
      } else {
        // Internal error.
        AnalysisEngine.instance.instrumentationService
            .logError("Unknown type of combinator: ${combinator.runtimeType}");
      }
    }
    return definedNames;
  }

  /// Create a mapping table representing the export namespace of the given
  /// [library]. The set of [visitedElements] contains the libraries that do not
  /// need to be visited when processing the export directives of the given
  /// library because all of the names defined by them will be added by another
  /// library.
  Map<String, Element> _computeExportMapping(
      LibraryElement library, HashSet<LibraryElement> visitedElements) {
    visitedElements.add(library);
    try {
      Map<String, Element> definedNames = HashMap<String, Element>();
      for (ExportElement element in library.exports) {
        LibraryElement exportedLibrary = element.exportedLibrary;
        if (exportedLibrary != null &&
            !visitedElements.contains(exportedLibrary)) {
          //
          // The exported library will be null if the URI does not reference a
          // valid library.
          //
          Map<String, Element> exportedNames =
              _computeExportMapping(exportedLibrary, visitedElements);
          exportedNames = _applyCombinators(exportedNames, element.combinators);
          definedNames.addAll(exportedNames);
        }
      }
      _addAllFromNamespace(
        definedNames,
        createPublicNamespaceForLibrary(library),
      );
      return definedNames;
    } finally {
      visitedElements.remove(library);
    }
  }

  Map<String, Element> _getExportMapping(LibraryElement library) {
    if (library.exportNamespace != null) {
      return library.exportNamespace.definedNames;
    }
    if (library is LibraryElementImpl) {
      Map<String, Element> exportMapping =
          _computeExportMapping(library, HashSet<LibraryElement>());
      library.exportNamespace = Namespace(exportMapping);
      return exportMapping;
    }
    return _computeExportMapping(library, HashSet<LibraryElement>());
  }

  /// Return a new map of names which has all the names from [definedNames]
  /// with exception of [hiddenNames].
  Map<String, Element> _hide(
      Map<String, Element> definedNames, List<String> hiddenNames) {
    Map<String, Element> newNames = HashMap<String, Element>.from(definedNames);
    for (String name in hiddenNames) {
      newNames.remove(name);
      newNames.remove("$name=");
    }
    return newNames;
  }

  /// Return a new map of names which has only [shownNames] from [definedNames].
  Map<String, Element> _show(
      Map<String, Element> definedNames, List<String> shownNames) {
    Map<String, Element> newNames = HashMap<String, Element>();
    for (String name in shownNames) {
      Element element = definedNames[name];
      if (element != null) {
        newNames[name] = element;
      }
      String setterName = "$name=";
      element = definedNames[setterName];
      if (element != null) {
        newNames[setterName] = element;
      }
    }
    return newNames;
  }
}

/// A mapping of identifiers to the elements represented by those identifiers.
/// Namespaces are the building blocks for scopes.
class PrefixedNamespace implements Namespace {
  /// The prefix that is prepended to each of the defined names.
  final String _prefix;

  /// The length of the prefix.
  final int _length;

  /// A table mapping names that are defined in this namespace to the element
  /// representing the thing declared with that name.
  @override
  final Map<String, Element> _definedNames;

  /// Initialize a newly created namespace to have the names resulting from
  /// prefixing each of the [_definedNames] with the given [_prefix] (and a
  /// period).
  PrefixedNamespace(String prefix, this._definedNames)
      : _prefix = prefix,
        _length = prefix.length;

  @override
  Map<String, Element> get definedNames {
    Map<String, Element> definedNames = <String, Element>{};
    _definedNames.forEach((String name, Element element) {
      definedNames["$_prefix.$name"] = element;
    });
    return definedNames;
  }

  @override
  Element get(String name) {
    if (name.length > _length && name.startsWith(_prefix)) {
      if (name.codeUnitAt(_length) == '.'.codeUnitAt(0)) {
        return _definedNames[name.substring(_length + 1)];
      }
    }
    return null;
  }

  @override
  Element getPrefixed(String prefix, String name) {
    if (prefix == _prefix) {
      return _definedNames[name];
    }
    return null;
  }
}

/// A name scope used by the resolver to determine which names are visible at
/// any given point in the code.
abstract class Scope {
  /// The prefix used to mark an identifier as being private to its library.
  static int PRIVATE_NAME_PREFIX = 0x5F;

  /// The suffix added to the declared name of a setter when looking up the
  /// setter. Used to disambiguate between a getter and a setter that have the
  /// same name.
  static String SETTER_SUFFIX = "=";

  /// The name used to look up the method used to implement the unary minus
  /// operator. Used to disambiguate between the unary and binary operators.
  static String UNARY_MINUS = "unary-";

  /// A table mapping names that are defined in this scope to the element
  /// representing the thing declared with that name.
  Map<String, Element> _definedNames;

  /// Return the scope in which this scope is lexically enclosed.
  Scope get enclosingScope => null;

  /// The list of extensions defined in this scope.
  List<ExtensionElement> get extensions =>
      enclosingScope == null ? <ExtensionElement>[] : enclosingScope.extensions;

  /// Add the given [element] to this scope. If there is already an element with
  /// the given name defined in this scope, then the original element will
  /// continue to be mapped to the name.
  void define(Element element) {
    String name = _getName(element);
    if (name != null && name.isNotEmpty) {
      _definedNames ??= HashMap<String, Element>();
      _definedNames.putIfAbsent(name, () => element);
    }
  }

  /// Add the given [element] to this scope without checking for duplication or
  /// hiding.
  void defineNameWithoutChecking(String name, Element element) {
    _definedNames ??= HashMap<String, Element>();
    _definedNames[name] = element;
  }

  /// Add the given [element] to this scope without checking for duplication or
  /// hiding.
  void defineWithoutChecking(Element element) {
    _definedNames ??= HashMap<String, Element>();
    _definedNames[_getName(element)] = element;
  }

  /// Return the element with which the given [name] is associated, or `null` if
  /// the name is not defined within this scope.
  Element internalLookup(String name);

  /// Return the element with which the given [name] is associated, or `null` if
  /// the name is not defined within this scope. This method only returns
  /// elements that are directly defined within this scope, not elements that
  /// are defined in an enclosing scope.
  Element localLookup(String name) {
    if (_definedNames != null) {
      return _definedNames[name];
    }
    return null;
  }

  /// Return the element with which the given [identifier] is associated, or
  /// `null` if the name is not defined within this scope. The
  /// [referencingLibrary] is the library that contains the reference to the
  /// name, used to implement library-level privacy.
  Element lookup(Identifier identifier, LibraryElement referencingLibrary) {
    if (identifier is PrefixedIdentifier) {
      return _internalLookupPrefixed(
          identifier.prefix.name, identifier.identifier.name);
    }
    return internalLookup(identifier.name);
  }

  /// Return `true` if the fact that the given [node] is not defined should be
  /// ignored (from the perspective of error reporting). This will be the case
  /// if there is at least one import that defines the node's prefix, and if
  /// that import either has no show combinators or has a show combinator that
  /// explicitly lists the node's name.
  bool shouldIgnoreUndefined(Identifier node) {
    if (enclosingScope != null) {
      return enclosingScope.shouldIgnoreUndefined(node);
    }
    return false;
  }

  /// Return the name that will be used to look up the given [element].
  String _getName(Element element) {
    if (element is MethodElement) {
      MethodElement method = element;
      if (method.name == "-" && method.parameters.isEmpty) {
        return UNARY_MINUS;
      }
    }
    return element.name;
  }

  /// Return the element with which the given [prefix] and [name] are
  /// associated, or `null` if the name is not defined within this scope.
  Element _internalLookupPrefixed(String prefix, String name);

  /// Return `true` if the given [name] is a library-private name.
  static bool isPrivateName(String name) =>
      name != null && name.startsWith('_');
}

/// The scope defined by the type parameters in an element that defines type
/// parameters.
class TypeParameterScope extends EnclosedScope {
  /// Initialize a newly created scope, enclosed within the [enclosingScope],
  /// that defines the type parameters from the given [element].
  TypeParameterScope(Scope enclosingScope, TypeParameterizedElement element)
      : super(enclosingScope) {
    if (element == null) {
      throw ArgumentError("element cannot be null");
    }
    _defineTypeParameters(element);
  }

  /// Define the type parameters declared by the [element].
  void _defineTypeParameters(TypeParameterizedElement element) {
    for (TypeParameterElement typeParameter in element.typeParameters) {
      define(typeParameter);
    }
  }
}
