// Copyright (c) 2016, 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';

/// A visitor that resolves declarations in an AST structure to already built
/// elements.
///
/// The resulting AST must have everything resolved that would have been
/// resolved by a [CompilationUnitBuilder] (that is, must be a valid
/// [RESOLVED_UNIT1]). This class must not assume that the
/// [CompilationUnitElement] passed to it is any more complete than a
/// [COMPILATION_UNIT_ELEMENT].
class DeclarationResolver extends RecursiveAstVisitor<void> {
  /// The compilation unit containing the AST nodes being visited.
  CompilationUnitElementImpl _enclosingUnit;

  /// The type provider used to access the known types.
  TypeProvider _typeProvider;

  /// The [ElementWalker] we are using to keep track of progress through the
  /// element model.
  ElementWalker _walker;

  DeclarationResolver();

  /// Resolve the declarations within the given compilation [unit] to the
  /// elements rooted at the given [element]. Throw an
  /// [ElementMismatchException] if the element model and compilation unit do
  /// not match each other.
  void resolve(CompilationUnit unit, CompilationUnitElement element) {
    _enclosingUnit = element;
    _typeProvider = _enclosingUnit.context?.typeProvider;
    _walker = new ElementWalker.forCompilationUnit(element);
    unit.element = element;
    try {
      unit.accept(this);
      _walker.validate();
    } on Error catch (e, st) {
      throw new _ElementMismatchException(
          element, _walker.element, new CaughtException(e, st));
    }
  }

  @override
  void visitAnnotation(Annotation node) {
    // Annotations can only contain elements in certain erroneous situations,
    // in which case the elements are disconnected from the rest of the element
    // model, thus we can't reconnect to them.  To avoid crashes, just create
    // fresh elements.
    ElementHolder elementHolder = new ElementHolder();
    new ElementBuilder(elementHolder, _enclosingUnit).visitAnnotation(node);
  }

  @override
  void visitBlockFunctionBody(BlockFunctionBody node) {
    if (_isBodyToCreateElementsFor(node)) {
      _walker.consumeLocalElements();
      node.accept(_walker.elementBuilder);
    } else {
      super.visitBlockFunctionBody(node);
    }
  }

  @override
  void visitCatchClause(CatchClause node) {
    _walker.elementBuilder.buildCatchVariableElements(node);
    super.visitCatchClause(node);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    ClassElement element = _match(node.name, _walker.getClass());
    _walk(new ElementWalker.forClass(element), () {
      super.visitClassDeclaration(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    ClassElement element = _match(node.name, _walker.getClass());
    _walk(new ElementWalker.forClass(element), () {
      super.visitClassTypeAlias(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    ConstructorElement element = _match(node.name, _walker.getConstructor(),
        offset: node.name?.offset ?? node.returnType.offset);
    _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
      (node as ConstructorDeclarationImpl).declaredElement = element;
      super.visitConstructorDeclaration(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitDeclaredIdentifier(DeclaredIdentifier node) {
    // Declared identifiers can only occur inside executable elements.
    _walker.elementBuilder.visitDeclaredIdentifier(node);
  }

  @override
  void visitDefaultFormalParameter(DefaultFormalParameter node) {
    NormalFormalParameter normalParameter = node.parameter;
    ParameterElement element =
        _match(normalParameter.identifier, _walker.getParameter());
    if (normalParameter is SimpleFormalParameterImpl) {
      normalParameter.declaredElement = element;
      _setGenericFunctionType(normalParameter.type, element.type);
    }
    if (normalParameter is FieldFormalParameterImpl) {
      _setGenericFunctionType(normalParameter.type, element.type);
    }

    Expression defaultValue = node.defaultValue;
    if (defaultValue != null) {
      _walk(
          new ElementWalker.forExecutable(element.initializer, _enclosingUnit),
          () {
        defaultValue.accept(this);
      });
    }

    _walk(new ElementWalker.forParameter(element), () {
      normalParameter.accept(this);
    });

    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    ClassElement element = _match(node.name, _walker.getEnum());
    resolveMetadata(node, node.metadata, element);
    _walk(new ElementWalker.forClass(element), () {
      for (EnumConstantDeclaration constant in node.constants) {
        VariableElement field = _match(constant.name, _walker.getVariable());
        resolveMetadata(node, constant.metadata, field);
        constant.name.staticElement = field;
        constant.name.staticType = field.type;
      }
      _walker.getFunction(); // toString()
      super.visitEnumDeclaration(node);
    });
  }

  @override
  void visitExportDirective(ExportDirective node) {
    super.visitExportDirective(node);
    List<ElementAnnotation> annotations =
        _enclosingUnit.getAnnotations(node.offset);
    if (annotations.isEmpty && node.metadata.isNotEmpty) {
      int index = (node.parent as CompilationUnit)
          .directives
          .where((directive) => directive is ExportDirective)
          .toList()
          .indexOf(node);
      annotations = _walker.element.library.exports[index].metadata;
    }
    resolveAnnotations(node, node.metadata, annotations);
  }

  @override
  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
    if (_isBodyToCreateElementsFor(node)) {
      _walker.consumeLocalElements();
      node.accept(_walker.elementBuilder);
    } else {
      super.visitExpressionFunctionBody(node);
    }
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    super.visitFieldDeclaration(node);
    FieldElement firstFieldElement = node.fields.variables[0].declaredElement;
    resolveMetadata(node, node.metadata, firstFieldElement);
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    if (node.parent is! DefaultFormalParameter) {
      ParameterElement element =
          _match(node.identifier, _walker.getParameter());
      _walk(new ElementWalker.forParameter(element), () {
        super.visitFieldFormalParameter(node);
      });
      resolveMetadata(node, node.metadata, element);
      _setGenericFunctionType(node.type, element.type);
    } else {
      super.visitFieldFormalParameter(node);
    }
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    SimpleIdentifier functionName = node.name;
    Token property = node.propertyKeyword;
    ExecutableElement element;
    if (property == null) {
      element = _match(functionName, _walker.getFunction());
    } else {
      if (_walker.element is ExecutableElement) {
        element = _match(functionName, _walker.getFunction());
      } else if (property.keyword == Keyword.GET) {
        element = _match(functionName, _walker.getAccessor());
      } else {
        assert(property.keyword == Keyword.SET);
        element = _match(functionName, _walker.getAccessor(),
            elementName: functionName.name + '=');
      }
    }
    _setGenericFunctionType(node.returnType, element.returnType);
    (node.functionExpression as FunctionExpressionImpl).declaredElement =
        element;
    _walker._elementHolder?.addFunction(element);
    _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
      super.visitFunctionDeclaration(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    if (node.parent is! FunctionDeclaration) {
      node.accept(_walker.elementBuilder);
    } else {
      super.visitFunctionExpression(node);
    }
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    FunctionTypeAliasElement element = _match(node.name, _walker.getTypedef());
    _walk(new ElementWalker.forTypedef(element), () {
      super.visitFunctionTypeAlias(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    if (node.parent is! DefaultFormalParameter) {
      ParameterElement element =
          _match(node.identifier, _walker.getParameter());
      _walk(new ElementWalker.forParameter(element), () {
        super.visitFunctionTypedFormalParameter(node);
      });
      resolveMetadata(node, node.metadata, element);
    } else {
      super.visitFunctionTypedFormalParameter(node);
    }
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    if (_walker.elementBuilder != null) {
      _walker.elementBuilder.visitGenericFunctionType(node);
    } else {
      DartType type = node.type;
      if (type != null) {
        Element element = type.element;
        if (element is GenericFunctionTypeElement) {
          _setGenericFunctionType(node.returnType, element.returnType);
          _walk(new ElementWalker.forGenericFunctionType(element), () {
            super.visitGenericFunctionType(node);
          });
        }
      }
    }
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    GenericTypeAliasElementImpl element =
        _match(node.name, _walker.getTypedef());
    _setGenericFunctionType(node.functionType, element.function?.type);
    _walk(new ElementWalker.forGenericTypeAlias(element), () {
      super.visitGenericTypeAlias(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    super.visitImportDirective(node);
    List<ElementAnnotation> annotations =
        _enclosingUnit.getAnnotations(node.offset);
    if (annotations.isEmpty && node.metadata.isNotEmpty) {
      int index = (node.parent as CompilationUnit)
          .directives
          .where((directive) => directive is ImportDirective)
          .toList()
          .indexOf(node);
      annotations = _walker.element.library.imports[index].metadata;
    }
    resolveAnnotations(node, node.metadata, annotations);
  }

  @override
  void visitLabeledStatement(LabeledStatement node) {
    bool onSwitchStatement = node.statement is SwitchStatement;
    _walker.elementBuilder
        .buildLabelElements(node.labels, onSwitchStatement, false);
    super.visitLabeledStatement(node);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    super.visitLibraryDirective(node);
    List<ElementAnnotation> annotations =
        _enclosingUnit.getAnnotations(node.offset);
    if (annotations.isEmpty && node.metadata.isNotEmpty) {
      annotations = _walker.element.library.metadata;
    }
    resolveAnnotations(node, node.metadata, annotations);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    Token property = node.propertyKeyword;
    SimpleIdentifier methodName = node.name;
    String nameOfMethod = methodName.name;
    ExecutableElement element;
    if (property == null) {
      String elementName = nameOfMethod == '-' &&
              node.parameters != null &&
              node.parameters.parameters.isEmpty
          ? 'unary-'
          : nameOfMethod;
      element =
          _match(methodName, _walker.getFunction(), elementName: elementName);
    } else {
      if (property.keyword == Keyword.GET) {
        element = _match(methodName, _walker.getAccessor());
      } else {
        assert(property.keyword == Keyword.SET);
        element = _match(methodName, _walker.getAccessor(),
            elementName: nameOfMethod + '=');
      }
    }
    _setGenericFunctionType(node.returnType, element.returnType);
    _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
      super.visitMethodDeclaration(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    ClassElement element = _match(node.name, _walker.getMixin());
    _walk(new ElementWalker.forClass(element), () {
      super.visitMixinDeclaration(node);
    });
    resolveMetadata(node, node.metadata, element);
  }

  @override
  void visitPartDirective(PartDirective node) {
    super.visitPartDirective(node);
    List<ElementAnnotation> annotations =
        _enclosingUnit.getAnnotations(node.offset);
    if (annotations.isEmpty && node.metadata.isNotEmpty) {
      int index = (node.parent as CompilationUnit)
          .directives
          .where((directive) => directive is PartDirective)
          .toList()
          .indexOf(node);
      annotations = _walker.element.library.parts[index].metadata;
    }
    resolveAnnotations(node, node.metadata, annotations);
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    node.element = _enclosingUnit.library;
    super.visitPartOfDirective(node);
  }

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    if (node.parent is! DefaultFormalParameter) {
      ParameterElement element =
          _match(node.identifier, _walker.getParameter());
      (node as SimpleFormalParameterImpl).declaredElement = element;
      _setGenericFunctionType(node.type, element.type);
      _walk(new ElementWalker.forParameter(element), () {
        super.visitSimpleFormalParameter(node);
      });
      resolveMetadata(node, node.metadata, element);
    } else {
      super.visitSimpleFormalParameter(node);
    }
  }

  @override
  void visitSwitchCase(SwitchCase node) {
    _walker.elementBuilder.buildLabelElements(node.labels, false, true);
    super.visitSwitchCase(node);
  }

  @override
  void visitSwitchDefault(SwitchDefault node) {
    _walker.elementBuilder.buildLabelElements(node.labels, false, true);
    super.visitSwitchDefault(node);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    super.visitTopLevelVariableDeclaration(node);
    VariableElement firstElement = node.variables.variables[0].declaredElement;
    resolveMetadata(node, node.metadata, firstElement);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    if (node.parent.parent is FunctionTypedFormalParameter) {
      // Work around dartbug.com/28515.
      // TODO(paulberry): remove this once dartbug.com/28515 is fixed.
      var element = new TypeParameterElementImpl.forNode(node.name);
      element.type = new TypeParameterTypeImpl(element);
      node.name?.staticElement = element;
    } else {
      TypeParameterElement element =
          _match(node.name, _walker.getTypeParameter());
      _setGenericFunctionType(node.bound, element.bound);
      super.visitTypeParameter(node);
      resolveMetadata(node, node.metadata, element);
    }
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    VariableElement element = _match(node.name, _walker.getVariable());
    Expression initializer = node.initializer;
    if (initializer != null) {
      _walk(
          new ElementWalker.forExecutable(element.initializer, _enclosingUnit),
          () {
        super.visitVariableDeclaration(node);
      });
    } else {
      super.visitVariableDeclaration(node);
    }
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    if (_walker.elementBuilder != null) {
      _walker.elementBuilder.visitVariableDeclarationList(node);
    } else {
      node.variables.accept(this);
      VariableElement firstVariable = node.variables[0].declaredElement;
      _setGenericFunctionType(node.type, firstVariable.type);
      node.type?.accept(this);
      if (node.parent is! FieldDeclaration &&
          node.parent is! TopLevelVariableDeclaration) {
        resolveMetadata(node, node.metadata, firstVariable);
      }
    }
  }

  /// Updates [identifier] to point to [element], after ensuring that the
  /// element has the expected name.
  ///
  /// If no [elementName] is given, it defaults to the name of the [identifier]
  /// (or the empty string if [identifier] is `null`).
  ///
  /// If [identifier] is `null`, nothing is updated, but the element name is
  /// still checked.
  E _match<E extends Element>(SimpleIdentifier identifier, E element,
      {String elementName, int offset}) {
    elementName ??= identifier?.name ?? '';
    offset ??= identifier?.offset ?? -1;
    if (element.name != elementName) {
      throw new StateError(
          'Expected an element matching `$elementName`, got `${element.name}`');
    }
    identifier?.staticElement = element;
    _matchOffset(element, offset);
    return element;
  }

  void _matchOffset(Element element, int offset) {
    if (element.nameOffset > 0 && element.nameOffset != offset) {
      throw new StateError('Element offset mismatch');
    } else {
      (element as ElementImpl).nameOffset = offset;
    }
  }

  /// If the given [typeNode] is a [GenericFunctionType], set its [type].
  void _setGenericFunctionType(TypeAnnotation typeNode, DartType type) {
    if (typeNode is GenericFunctionTypeImpl) {
      typeNode.type = type;
      typeNode.declaredElement = type.element;
    } else if (typeNode is NamedType) {
      typeNode.type = type;
      if (type is ParameterizedType) {
        List<TypeAnnotation> nodes =
            typeNode.typeArguments?.arguments ?? const [];
        List<DartType> types = type.typeArguments;
        if (nodes.length == types.length) {
          for (int i = 0; i < nodes.length; i++) {
            _setGenericFunctionType(nodes[i], types[i]);
          }
        }
      }
    }
  }

  /// Recurses through the element model and AST, verifying that all elements
  /// are matched.
  ///
  /// Executes [callback] with [_walker] pointing to the given [walker] (which
  /// should be a new instance of [ElementWalker]).  Once [callback] returns,
  /// uses [ElementWalker.validate] to verify that all expected elements have
  /// been matched.
  void _walk(ElementWalker walker, void callback()) {
    ElementWalker outerWalker = _walker;
    _walker = walker;
    callback();
    walker.validate();
    _walker = outerWalker;
  }

  /// Apply the [type] that is created by the [constructorName] and the
  /// [constructorElement] it references.
  static void applyConstructorElement(
      LibraryElement enclosingLibraryElement,
      PrefixElement prefixElement,
      ConstructorElement constructorElement,
      DartType type,
      ConstructorName constructorName) {
    constructorName.staticElement = constructorElement;

    ClassElement classElement = constructorElement?.enclosingElement;

    Identifier typeIdentifier = constructorName.type.name;
    if (prefixElement != null) {
      PrefixedIdentifier prefixedTypeIdentifier = typeIdentifier;
      prefixedTypeIdentifier.staticType = type;

      prefixedTypeIdentifier.prefix.staticElement = prefixElement;

      SimpleIdentifier classNode = prefixedTypeIdentifier.identifier;
      classNode.staticElement = classElement;
      classNode.staticType = type;
    } else {
      if (typeIdentifier is SimpleIdentifier) {
        typeIdentifier.staticElement = classElement;
        typeIdentifier.staticType = type;
      } else if (typeIdentifier is PrefixedIdentifier) {
        constructorName.type = astFactory.typeName(typeIdentifier.prefix, null);
        constructorName.period = typeIdentifier.period;
        constructorName.name = typeIdentifier.identifier;
      }
    }

    constructorName.name?.staticElement = constructorElement;

    DeclarationResolver.applyToTypeAnnotation(
        enclosingLibraryElement, type, constructorName.type);
  }

  /// Apply the types of the [parameterElements] to the [parameterList] that
  /// have an explicit type annotation.
  static void applyParameters(
      LibraryElement enclosingLibraryElement,
      List<ParameterElement> parameterElements,
      FormalParameterList parameterList) {
    List<FormalParameter> parameters = parameterList.parameters;

    int length = parameterElements.length;
    if (parameters.length != length) {
      throw new StateError('Parameter counts do not match');
    }
    for (int i = 0; i < length; i++) {
      ParameterElementImpl element = parameterElements[i];
      FormalParameter parameter = parameters[i];

      DeclarationResolver.resolveMetadata(
          parameter, parameter.metadata, element);

      NormalFormalParameter normalParameter;
      if (parameter is NormalFormalParameter) {
        normalParameter = parameter;
      } else if (parameter is DefaultFormalParameter) {
        normalParameter = parameter.parameter;
      }
      assert(normalParameter != null);

      if (normalParameter is SimpleFormalParameterImpl) {
        normalParameter.declaredElement = element;
      }

      if (normalParameter.identifier != null) {
        element.nameOffset = normalParameter.identifier.offset;
        normalParameter.identifier.staticElement = element;
        normalParameter.identifier.staticType = element.type;
      }

      // Apply the type or the return type, if a function typed parameter.
      TypeAnnotation functionReturnType;
      FormalParameterList functionParameterList;
      if (normalParameter is SimpleFormalParameter) {
        applyToTypeAnnotation(
            enclosingLibraryElement, element.type, normalParameter.type);
      } else if (normalParameter is FunctionTypedFormalParameter) {
        functionReturnType = normalParameter.returnType;
        functionParameterList = normalParameter.parameters;
      } else if (normalParameter is FieldFormalParameter) {
        if (normalParameter.parameters == null) {
          applyToTypeAnnotation(
              enclosingLibraryElement, element.type, normalParameter.type);
        } else {
          functionReturnType = normalParameter.type;
          functionParameterList = normalParameter.parameters;
        }
      }

      if (functionParameterList != null) {
        FunctionType elementType = element.type;
        if (functionReturnType != null) {
          applyToTypeAnnotation(enclosingLibraryElement, elementType.returnType,
              functionReturnType);
        }
        applyParameters(enclosingLibraryElement, elementType.parameters,
            functionParameterList);
      }
    }
  }

  /// Apply the [type] to the [typeAnnotation] by setting the type of the
  /// [typeAnnotation] to the [type] and recursively applying each of the type
  /// arguments of the [type] to the corresponding type arguments of the
  /// [typeAnnotation].
  static void applyToTypeAnnotation(LibraryElement enclosingLibraryElement,
      DartType type, TypeAnnotation typeAnnotation) {
    if (typeAnnotation is GenericFunctionTypeImpl) {
      if (type is! FunctionType) {
        throw new StateError('Non-function type ($type) '
            'for generic function annotation ($typeAnnotation)');
      }
      FunctionType functionType = type;
      typeAnnotation.type = type;
      applyToTypeAnnotation(enclosingLibraryElement, functionType.returnType,
          typeAnnotation.returnType);
      applyParameters(enclosingLibraryElement, functionType.parameters,
          typeAnnotation.parameters);
    } else if (typeAnnotation is TypeNameImpl) {
      typeAnnotation.type = type;

      Identifier typeIdentifier = typeAnnotation.name;
      SimpleIdentifier typeName;
      if (typeIdentifier is PrefixedIdentifier) {
        if (enclosingLibraryElement != null) {
          String prefixName = typeIdentifier.prefix.name;
          for (var import in enclosingLibraryElement.imports) {
            if (import.prefix?.name == prefixName) {
              typeIdentifier.prefix.staticElement = import.prefix;
              break;
            }
          }
        }
        typeName = typeIdentifier.identifier;
      } else {
        typeName = typeIdentifier;
      }

      Element typeElement = type.element;
      if (typeElement is GenericFunctionTypeElement &&
          typeElement.enclosingElement is GenericTypeAliasElement) {
        typeElement = typeElement.enclosingElement;
      }

      typeName.staticElement = typeElement;
      typeName.staticType = type;
    }
    if (typeAnnotation is NamedType) {
      TypeArgumentList typeArguments = typeAnnotation.typeArguments;
      if (typeArguments != null) {
        _applyTypeArgumentsToList(
            enclosingLibraryElement, type, typeArguments.arguments);
      }
    }
  }

  /// Associate each of the annotation [nodes] with the corresponding
  /// [ElementAnnotation] in [annotations]. If there is a problem, report it
  /// against the given [parent] node.
  static void resolveAnnotations(AstNode parent, NodeList<Annotation> nodes,
      List<ElementAnnotation> annotations) {
    int nodeCount = nodes.length;
    if (nodeCount != annotations.length) {
      throw new StateError('Found $nodeCount annotation nodes and '
          '${annotations.length} element annotations');
    }
    for (int i = 0; i < nodeCount; i++) {
      nodes[i].elementAnnotation = annotations[i];
    }
  }

  /// If [element] is not `null`, associate each of the annotation [nodes] with
  /// the corresponding [ElementAnnotation] in [element.metadata]. If there is a
  /// problem, report it against the given [parent] node.
  ///
  /// If [element] is `null`, do nothing--this allows us to be robust in the
  /// case where we are operating on an element model that hasn't been fully
  /// built.
  static void resolveMetadata(
      AstNode parent, NodeList<Annotation> nodes, Element element) {
    if (element != null) {
      resolveAnnotations(parent, nodes, element.metadata);
    }
  }

  /// Recursively apply each of the type arguments of the [type] to the
  /// corresponding type arguments of the [typeArguments].
  static void _applyTypeArgumentsToList(LibraryElement enclosingLibraryElement,
      DartType type, List<TypeAnnotation> typeArguments) {
    if (type != null && type.isDynamic) {
      for (TypeAnnotation argument in typeArguments) {
        applyToTypeAnnotation(enclosingLibraryElement, type, argument);
      }
    } else if (type is ParameterizedType) {
      List<DartType> argumentTypes = type.typeArguments;
      int argumentCount = argumentTypes.length;
      if (argumentCount != typeArguments.length) {
        throw new StateError('Found $argumentCount argument types '
            'for ${typeArguments.length} type arguments');
      }
      for (int i = 0; i < argumentCount; i++) {
        applyToTypeAnnotation(
            enclosingLibraryElement, argumentTypes[i], typeArguments[i]);
      }
    } else {
      throw new StateError('Attempting to apply a non-parameterized type '
          '(${type.runtimeType}) to type arguments');
    }
  }

  static bool _isBodyToCreateElementsFor(FunctionBody node) {
    AstNode parent = node.parent;
    return parent is ConstructorDeclaration ||
        parent is MethodDeclaration ||
        parent.parent is FunctionDeclaration &&
            parent.parent.parent is CompilationUnit;
  }
}

/// Keeps track of the set of non-synthetic child elements of an element,
/// yielding them one at a time in response to "get" method calls.
class ElementWalker {
  /// The element whose child elements are being walked.
  final Element element;

  /// If [element] is an executable element, an element builder which is
  /// accumulating the executable element's local variables and labels.
  /// Otherwise `null`.
  LocalElementBuilder elementBuilder;

  /// If [element] is an executable element, the element holder associated with
  /// [elementBuilder].  Otherwise `null`.
  ElementHolder _elementHolder;

  List<PropertyAccessorElement> _accessors;
  int _accessorIndex = 0;
  List<ClassElement> _classes;
  int _classIndex = 0;
  List<ConstructorElement> _constructors;
  int _constructorIndex = 0;
  List<ClassElement> _enums;
  int _enumIndex = 0;
  List<ExecutableElement> _functions;
  int _functionIndex = 0;
  List<ClassElement> _mixins;
  int _mixinIndex = 0;
  List<ParameterElement> _parameters;
  int _parameterIndex = 0;
  List<FunctionTypeAliasElement> _typedefs;
  int _typedefIndex = 0;
  List<TypeParameterElement> _typeParameters;
  int _typeParameterIndex = 0;
  List<VariableElement> _variables;
  int _variableIndex = 0;

  /// Creates an [ElementWalker] which walks the child elements of a class
  /// element.
  ElementWalker.forClass(ClassElement element)
      : element = element,
        _accessors = element.accessors.where(_isNotSynthetic).toList(),
        _constructors = element.isMixinApplication
            ? null
            : element.constructors.where(_isNotSynthetic).toList(),
        _functions = element.methods,
        _typeParameters = element.typeParameters,
        _variables = element.fields.where(_isNotSynthetic).toList();

  /// Creates an [ElementWalker] which walks the child elements of a compilation
  /// unit element.
  ElementWalker.forCompilationUnit(CompilationUnitElement compilationUnit)
      : element = compilationUnit,
        _accessors = compilationUnit.accessors.where(_isNotSynthetic).toList(),
        _classes = compilationUnit.types,
        _enums = compilationUnit.enums,
        _functions = compilationUnit.functions,
        _mixins = compilationUnit.mixins,
        _typedefs = compilationUnit.functionTypeAliases,
        _variables =
            compilationUnit.topLevelVariables.where(_isNotSynthetic).toList();

  /// Creates an [ElementWalker] which walks the child elements of a compilation
  /// unit element.
  ElementWalker.forExecutable(
      ExecutableElement element, CompilationUnitElement compilationUnit)
      : this._forExecutable(element, compilationUnit, new ElementHolder());

  /// Creates an [ElementWalker] which walks the child elements of a typedef
  /// element.
  ElementWalker.forGenericFunctionType(GenericFunctionTypeElement element)
      : element = element,
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  /// Creates an [ElementWalker] which walks the child elements of a typedef
  /// element defined using a generic function type.
  ElementWalker.forGenericTypeAlias(FunctionTypeAliasElement element)
      : element = element,
        _typeParameters = element.typeParameters;

  /// Creates an [ElementWalker] which walks the child elements of a parameter
  /// element.
  ElementWalker.forParameter(ParameterElement element)
      : element = element,
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  /// Creates an [ElementWalker] which walks the child elements of a typedef
  /// element.
  ElementWalker.forTypedef(GenericTypeAliasElementImpl element)
      : element = element,
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  ElementWalker._forExecutable(ExecutableElement element,
      CompilationUnitElement compilationUnit, ElementHolder elementHolder)
      : element = element,
        elementBuilder =
            new LocalElementBuilder(elementHolder, compilationUnit),
        _elementHolder = elementHolder,
        _functions = const <ExecutableElement>[],
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  void consumeLocalElements() {
    _functionIndex = _functions.length;
  }

  void consumeParameters() {
    _parameterIndex = _parameters.length;
  }

  /// Returns the next non-synthetic child of [element] which is an accessor;
  /// throws an [IndexError] if there are no more.
  PropertyAccessorElement getAccessor() => _accessors[_accessorIndex++];

  /// Returns the next non-synthetic child of [element] which is a class; throws
  /// an [IndexError] if there are no more.
  ClassElement getClass() => _classes[_classIndex++];

  /// Returns the next non-synthetic child of [element] which is a constructor;
  /// throws an [IndexError] if there are no more.
  ConstructorElement getConstructor() => _constructors[_constructorIndex++];

  /// Returns the next non-synthetic child of [element] which is an enum; throws
  /// an [IndexError] if there are no more.
  ClassElement getEnum() => _enums[_enumIndex++];

  /// Returns the next non-synthetic child of [element] which is a top level
  /// function, method, or local function; throws an [IndexError] if there are
  /// no more.
  ExecutableElement getFunction() => _functions[_functionIndex++];

  /// Returns the next non-synthetic child of [element] which is a mixin; throws
  /// an [IndexError] if there are no more.
  ClassElement getMixin() => _mixins[_mixinIndex++];

  /// Returns the next non-synthetic child of [element] which is a parameter;
  /// throws an [IndexError] if there are no more.
  ParameterElement getParameter() => _parameters[_parameterIndex++];

  /// Returns the next non-synthetic child of [element] which is a typedef;
  /// throws an [IndexError] if there are no more.
  FunctionTypeAliasElement getTypedef() => _typedefs[_typedefIndex++];

  /// Returns the next non-synthetic child of [element] which is a type
  /// parameter; throws an [IndexError] if there are no more.
  TypeParameterElement getTypeParameter() =>
      _typeParameters[_typeParameterIndex++];

  /// Returns the next non-synthetic child of [element] which is a top level
  /// variable, field, or local variable; throws an [IndexError] if there are no
  /// more.
  VariableElement getVariable() => _variables[_variableIndex++];

  /// Verifies that all non-synthetic children of [element] have been obtained
  /// from their corresponding "get" method calls; if not, throws a
  /// [StateError].
  void validate() {
    void check(List<Element> elements, int index) {
      if (elements != null && elements.length != index) {
        throw new StateError(
            'Unmatched ${elements[index].runtimeType} ${elements[index]}');
      }
    }

    check(_accessors, _accessorIndex);
    check(_classes, _classIndex);
    check(_constructors, _constructorIndex);
    check(_enums, _enumIndex);
    check(_functions, _functionIndex);
    check(_parameters, _parameterIndex);
    check(_typedefs, _typedefIndex);
    check(_typeParameters, _typeParameterIndex);
    check(_variables, _variableIndex);
    Element element = this.element;
    if (element is ExecutableElementImpl) {
      element.encloseElements(_elementHolder.functions);
      element.encloseElements(_elementHolder.labels);
      element.encloseElements(_elementHolder.localVariables);
    }
  }

  static bool _isNotSynthetic(Element e) => !e.isSynthetic;
}

class _ElementMismatchException extends AnalysisException {
  /// Creates an exception to refer to the given [compilationUnit], [element],
  /// and [cause].
  _ElementMismatchException(
      CompilationUnitElement compilationUnit, Element element,
      [CaughtException cause = null])
      : super('Element mismatch in $compilationUnit at $element', cause);
}
