// 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.

library analyzer.src.dart.element.builder;

import 'dart:collection';

import 'package:analyzer/dart/ast/ast.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/error/error.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';

/**
 * Instances of the class `ApiElementBuilder` traverse an AST structure and
 * build elements outside of function bodies and initializers.
 */
class ApiElementBuilder extends _BaseElementBuilder {
  /**
   * A table mapping field names to field elements for the fields defined in the current class, or
   * `null` if we are not in the scope of a class.
   */
  HashMap<String, FieldElement> _fieldMap;

  /**
   * Initialize a newly created element builder to build the elements for a
   * compilation unit. The [initialHolder] is the element holder to which the
   * children of the visited compilation unit node will be added.
   */
  ApiElementBuilder(ElementHolder initialHolder,
      CompilationUnitElementImpl compilationUnitElement)
      : super(initialHolder, compilationUnitElement);

  @override
  Object visitAnnotation(Annotation node) {
    // Although it isn't valid to do so because closures are not constant
    // expressions, it's possible for one of the arguments to the constructor to
    // contain a closure. Wrapping the processing of the annotation this way
    // prevents these closures from being added to the list of functions in the
    // annotated declaration.
    ElementHolder holder = new ElementHolder();
    ElementHolder previousHolder = _currentHolder;
    _currentHolder = holder;
    try {
      super.visitAnnotation(node);
    } finally {
      _currentHolder = previousHolder;
    }
    return null;
  }

  @override
  Object visitBlockFunctionBody(BlockFunctionBody node) {
    return null;
  }

  @override
  Object visitClassDeclaration(ClassDeclaration node) {
    ElementHolder holder = new ElementHolder();
    //
    // Process field declarations before constructors and methods so that field
    // formal parameters can be correctly resolved to their fields.
    //
    ElementHolder previousHolder = _currentHolder;
    _currentHolder = holder;
    try {
      List<ClassMember> nonFields = new List<ClassMember>();
      node.visitChildren(
          new _ElementBuilder_visitClassDeclaration(this, nonFields));
      _buildFieldMap(holder.fieldsWithoutFlushing);
      int count = nonFields.length;
      for (int i = 0; i < count; i++) {
        nonFields[i].accept(this);
      }
    } finally {
      _currentHolder = previousHolder;
    }
    SimpleIdentifier className = node.name;
    ClassElementImpl element = new ClassElementImpl.forNode(className);
    _setCodeRange(element, node);
    element.metadata = _createElementAnnotations(node.metadata);
    element.typeParameters = holder.typeParameters;
    setElementDocumentationComment(element, node);
    element.abstract = node.isAbstract;
    element.accessors = holder.accessors;
    List<ConstructorElement> constructors = holder.constructors;
    if (constructors.isEmpty) {
      constructors = _createDefaultConstructors(element);
    }
    element.constructors = constructors;
    element.fields = holder.fields;
    element.methods = holder.methods;
    _currentHolder.addType(element);
    className.staticElement = element;
    _fieldMap = null;
    holder.validate();
    return null;
  }

  @override
  Object visitClassTypeAlias(ClassTypeAlias node) {
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    SimpleIdentifier className = node.name;
    ClassElementImpl element = new ClassElementImpl.forNode(className);
    _setCodeRange(element, node);
    element.metadata = _createElementAnnotations(node.metadata);
    element.abstract = node.abstractKeyword != null;
    element.mixinApplication = true;
    element.typeParameters = holder.typeParameters;
    setElementDocumentationComment(element, node);
    _currentHolder.addType(element);
    className.staticElement = element;
    holder.validate();
    return null;
  }

  @override
  Object visitCompilationUnit(CompilationUnit node) {
    if (_unitElement is ElementImpl) {
      _setCodeRange(_unitElement, node);
    }
    return super.visitCompilationUnit(node);
  }

  @override
  Object visitConstructorDeclaration(ConstructorDeclaration node) {
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    FunctionBody body = node.body;
    SimpleIdentifier constructorName = node.name;
    ConstructorElementImpl element =
        new ConstructorElementImpl.forNode(constructorName);
    _setCodeRange(element, node);
    element.metadata = _createElementAnnotations(node.metadata);
    setElementDocumentationComment(element, node);
    if (node.externalKeyword != null) {
      element.external = true;
    }
    if (node.factoryKeyword != null) {
      element.factory = true;
    }
    element.functions = holder.functions;
    element.encloseElements(holder.labels);
    element.encloseElements(holder.localVariables);
    element.parameters = holder.parameters;
    element.isConst = node.constKeyword != null;
    element.isCycleFree = element.isConst;
    if (body.isAsynchronous) {
      element.asynchronous = true;
    }
    if (body.isGenerator) {
      element.generator = true;
    }
    _currentHolder.addConstructor(element);
    node.element = element;
    if (constructorName == null) {
      Identifier returnType = node.returnType;
      if (returnType != null) {
        element.nameOffset = returnType.offset;
        element.nameEnd = returnType.end;
      }
    } else {
      constructorName.staticElement = element;
      element.periodOffset = node.period.offset;
      element.nameEnd = constructorName.end;
    }
    holder.validate();
    return null;
  }

  @override
  Object visitEnumDeclaration(EnumDeclaration node) {
    SimpleIdentifier enumName = node.name;
    EnumElementImpl enumElement = new EnumElementImpl.forNode(enumName);
    _setCodeRange(enumElement, node);
    enumElement.metadata = _createElementAnnotations(node.metadata);
    setElementDocumentationComment(enumElement, node);
    InterfaceTypeImpl enumType = enumElement.type;
    //
    // Build the elements for the constants. These are minimal elements; the
    // rest of the constant elements (and elements for other fields) must be
    // built later after we can access the type provider.
    //
    List<FieldElement> fields = new List<FieldElement>();
    NodeList<EnumConstantDeclaration> constants = node.constants;
    for (EnumConstantDeclaration constant in constants) {
      SimpleIdentifier constantName = constant.name;
      FieldElementImpl constantField =
          new ConstFieldElementImpl.forNode(constantName);
      constantField.isStatic = true;
      constantField.isConst = true;
      constantField.type = enumType;
      setElementDocumentationComment(constantField, constant);
      fields.add(constantField);
      new PropertyAccessorElementImpl_ImplicitGetter(constantField);
      constantName.staticElement = constantField;
    }
    enumElement.fields = fields;

    _currentHolder.addEnum(enumElement);
    enumName.staticElement = enumElement;
    return super.visitEnumDeclaration(node);
  }

  @override
  Object visitExportDirective(ExportDirective node) {
    List<ElementAnnotation> annotations =
        _createElementAnnotations(node.metadata);
    _unitElement.setAnnotations(node.offset, annotations);
    return super.visitExportDirective(node);
  }

  @override
  Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
    return null;
  }

  @override
  Object visitFunctionDeclaration(FunctionDeclaration node) {
    FunctionExpression expression = node.functionExpression;
    if (expression != null) {
      ElementHolder holder = new ElementHolder();
      _visitChildren(holder, node);
      FunctionBody body = expression.body;
      Token property = node.propertyKeyword;
      if (property == null) {
        SimpleIdentifier functionName = node.name;
        FunctionElementImpl element =
            new FunctionElementImpl.forNode(functionName);
        _setCodeRange(element, node);
        element.metadata = _createElementAnnotations(node.metadata);
        setElementDocumentationComment(element, node);
        if (node.externalKeyword != null || body is NativeFunctionBody) {
          element.external = true;
        }
        element.functions = holder.functions;
        element.encloseElements(holder.labels);
        element.encloseElements(holder.localVariables);
        element.parameters = holder.parameters;
        element.typeParameters = holder.typeParameters;
        if (body.isAsynchronous) {
          element.asynchronous = true;
        }
        if (body.isGenerator) {
          element.generator = true;
        }
        if (node.returnType == null) {
          element.hasImplicitReturnType = true;
        }
        _currentHolder.addFunction(element);
        expression.element = element;
        functionName.staticElement = element;
      } else {
        SimpleIdentifier propertyNameNode = node.name;
        if (propertyNameNode == null) {
          // TODO(brianwilkerson) Report this internal error.
          return null;
        }
        String propertyName = propertyNameNode.name;
        TopLevelVariableElementImpl variable = _currentHolder
            .getTopLevelVariable(propertyName) as TopLevelVariableElementImpl;
        if (variable == null) {
          variable = new TopLevelVariableElementImpl(node.name.name, -1);
          variable.isFinal = true;
          variable.isSynthetic = true;
          _currentHolder.addTopLevelVariable(variable);
        }
        if (node.isGetter) {
          PropertyAccessorElementImpl getter =
              new PropertyAccessorElementImpl.forNode(propertyNameNode);
          _setCodeRange(getter, node);
          getter.metadata = _createElementAnnotations(node.metadata);
          setElementDocumentationComment(getter, node);
          if (node.externalKeyword != null || body is NativeFunctionBody) {
            getter.external = true;
          }
          getter.functions = holder.functions;
          getter.encloseElements(holder.labels);
          getter.encloseElements(holder.localVariables);
          if (body.isAsynchronous) {
            getter.asynchronous = true;
          }
          if (body.isGenerator) {
            getter.generator = true;
          }
          getter.variable = variable;
          getter.getter = true;
          getter.isStatic = true;
          variable.getter = getter;
          if (node.returnType == null) {
            getter.hasImplicitReturnType = true;
          }
          _currentHolder.addAccessor(getter);
          expression.element = getter;
          propertyNameNode.staticElement = getter;
        } else {
          PropertyAccessorElementImpl setter =
              new PropertyAccessorElementImpl.forNode(propertyNameNode);
          _setCodeRange(setter, node);
          setter.metadata = _createElementAnnotations(node.metadata);
          setElementDocumentationComment(setter, node);
          if (node.externalKeyword != null || body is NativeFunctionBody) {
            setter.external = true;
          }
          setter.functions = holder.functions;
          setter.encloseElements(holder.labels);
          setter.encloseElements(holder.localVariables);
          setter.parameters = holder.parameters;
          if (body.isAsynchronous) {
            setter.asynchronous = true;
          }
          if (body.isGenerator) {
            setter.generator = true;
          }
          setter.variable = variable;
          setter.setter = true;
          setter.isStatic = true;
          if (node.returnType == null) {
            setter.hasImplicitReturnType = true;
          }
          variable.setter = setter;
          variable.isFinal = false;
          _currentHolder.addAccessor(setter);
          expression.element = setter;
          propertyNameNode.staticElement = setter;
        }
      }
      holder.validate();
    }
    return null;
  }

  @override
  Object visitFunctionExpression(FunctionExpression node) {
    if (node.parent is FunctionDeclaration) {
      // visitFunctionDeclaration has already created the element for the
      // declaration.  We just need to visit children.
      return super.visitFunctionExpression(node);
    }
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    FunctionBody body = node.body;
    FunctionElementImpl element =
        new FunctionElementImpl.forOffset(node.beginToken.offset);
    _setCodeRange(element, node);
    element.functions = holder.functions;
    element.encloseElements(holder.labels);
    element.encloseElements(holder.localVariables);
    element.parameters = holder.parameters;
    element.typeParameters = holder.typeParameters;
    if (body.isAsynchronous) {
      element.asynchronous = true;
    }
    if (body.isGenerator) {
      element.generator = true;
    }
    element.type = new FunctionTypeImpl(element);
    element.hasImplicitReturnType = true;
    _currentHolder.addFunction(element);
    node.element = element;
    holder.validate();
    return null;
  }

  @override
  Object visitFunctionTypeAlias(FunctionTypeAlias node) {
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    SimpleIdentifier aliasName = node.name;
    List<ParameterElement> parameters = holder.parameters;
    List<TypeParameterElement> typeParameters = holder.typeParameters;
    FunctionTypeAliasElementImpl element =
        new FunctionTypeAliasElementImpl.forNode(aliasName);
    _setCodeRange(element, node);
    element.metadata = _createElementAnnotations(node.metadata);
    setElementDocumentationComment(element, node);
    element.parameters = parameters;
    element.typeParameters = typeParameters;
    _createTypeParameterTypes(typeParameters);
    element.type = new FunctionTypeImpl.forTypedef(element);
    _currentHolder.addTypeAlias(element);
    aliasName.staticElement = element;
    holder.validate();
    return null;
  }

  @override
  Object visitGenericTypeAlias(GenericTypeAlias node) {
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    SimpleIdentifier aliasName = node.name;
    List<TypeParameterElement> typeParameters = holder.typeParameters;
    GenericTypeAliasElementImpl element =
        new GenericTypeAliasElementImpl.forNode(aliasName);
    _setCodeRange(element, node);
    element.metadata = _createElementAnnotations(node.metadata);
    setElementDocumentationComment(element, node);
    element.typeParameters = typeParameters;
    _createTypeParameterTypes(typeParameters);
    element.type = new FunctionTypeImpl.forTypedef(element);
    element.function = node.functionType?.type?.element;
    _currentHolder.addTypeAlias(element);
    aliasName.staticElement = element;
    holder.validate();
    return null;
  }

  @override
  Object visitImportDirective(ImportDirective node) {
    List<ElementAnnotation> annotations =
        _createElementAnnotations(node.metadata);
    _unitElement.setAnnotations(node.offset, annotations);
    return super.visitImportDirective(node);
  }

  @override
  Object visitLibraryDirective(LibraryDirective node) {
    List<ElementAnnotation> annotations =
        _createElementAnnotations(node.metadata);
    _unitElement.setAnnotations(node.offset, annotations);
    return super.visitLibraryDirective(node);
  }

  @override
  Object visitMethodDeclaration(MethodDeclaration node) {
    try {
      ElementHolder holder = new ElementHolder();
      _visitChildren(holder, node);
      bool isStatic = node.isStatic;
      Token property = node.propertyKeyword;
      FunctionBody body = node.body;
      if (property == null) {
        SimpleIdentifier methodName = node.name;
        String nameOfMethod = methodName.name;
        if (nameOfMethod == TokenType.MINUS.lexeme &&
            node.parameters.parameters.length == 0) {
          nameOfMethod = "unary-";
        }
        MethodElementImpl element =
            new MethodElementImpl(nameOfMethod, methodName.offset);
        _setCodeRange(element, node);
        element.metadata = _createElementAnnotations(node.metadata);
        setElementDocumentationComment(element, node);
        element.abstract = node.isAbstract;
        if (node.externalKeyword != null || body is NativeFunctionBody) {
          element.external = true;
        }
        element.functions = holder.functions;
        element.encloseElements(holder.labels);
        element.encloseElements(holder.localVariables);
        element.parameters = holder.parameters;
        element.isStatic = isStatic;
        element.typeParameters = holder.typeParameters;
        if (body.isAsynchronous) {
          element.asynchronous = true;
        }
        if (body.isGenerator) {
          element.generator = true;
        }
        if (node.returnType == null) {
          element.hasImplicitReturnType = true;
        }
        _currentHolder.addMethod(element);
        methodName.staticElement = element;
      } else {
        SimpleIdentifier propertyNameNode = node.name;
        String propertyName = propertyNameNode.name;
        FieldElementImpl field = _currentHolder.getField(propertyName,
            synthetic: true) as FieldElementImpl;
        if (field == null) {
          field = new FieldElementImpl(node.name.name, -1);
          field.isFinal = true;
          field.isStatic = isStatic;
          field.isSynthetic = true;
          _currentHolder.addField(field);
        }
        if (node.isGetter) {
          PropertyAccessorElementImpl getter =
              new PropertyAccessorElementImpl.forNode(propertyNameNode);
          _setCodeRange(getter, node);
          getter.metadata = _createElementAnnotations(node.metadata);
          setElementDocumentationComment(getter, node);
          if (node.externalKeyword != null || body is NativeFunctionBody) {
            getter.external = true;
          }
          getter.functions = holder.functions;
          getter.encloseElements(holder.labels);
          getter.encloseElements(holder.localVariables);
          if (body.isAsynchronous) {
            getter.asynchronous = true;
          }
          if (body.isGenerator) {
            getter.generator = true;
          }
          getter.variable = field;
          getter.abstract = node.isAbstract;
          getter.getter = true;
          getter.isStatic = isStatic;
          field.getter = getter;
          if (node.returnType == null) {
            getter.hasImplicitReturnType = true;
          }
          _currentHolder.addAccessor(getter);
          propertyNameNode.staticElement = getter;
        } else {
          PropertyAccessorElementImpl setter =
              new PropertyAccessorElementImpl.forNode(propertyNameNode);
          _setCodeRange(setter, node);
          setter.metadata = _createElementAnnotations(node.metadata);
          setElementDocumentationComment(setter, node);
          if (node.externalKeyword != null || body is NativeFunctionBody) {
            setter.external = true;
          }
          setter.functions = holder.functions;
          setter.encloseElements(holder.labels);
          setter.encloseElements(holder.localVariables);
          setter.parameters = holder.parameters;
          if (body.isAsynchronous) {
            setter.asynchronous = true;
          }
          if (body.isGenerator) {
            setter.generator = true;
          }
          setter.variable = field;
          setter.abstract = node.isAbstract;
          setter.setter = true;
          setter.isStatic = isStatic;
          if (node.returnType == null) {
            setter.hasImplicitReturnType = true;
          }
          field.setter = setter;
          field.isFinal = false;
          _currentHolder.addAccessor(setter);
          propertyNameNode.staticElement = setter;
        }
      }
      holder.validate();
    } catch (exception, stackTrace) {
      if (node.name.staticElement == null) {
        ClassDeclaration classNode =
            node.getAncestor((node) => node is ClassDeclaration);
        StringBuffer buffer = new StringBuffer();
        buffer.write("The element for the method ");
        buffer.write(node.name);
        buffer.write(" in ");
        buffer.write(classNode.name);
        buffer.write(" was not set while trying to build the element model.");
        AnalysisEngine.instance.logger.logError(
            buffer.toString(), new CaughtException(exception, stackTrace));
      } else {
        String message =
            "Exception caught in ElementBuilder.visitMethodDeclaration()";
        AnalysisEngine.instance.logger
            .logError(message, new CaughtException(exception, stackTrace));
      }
    } finally {
      if (node.name.staticElement == null) {
        ClassDeclaration classNode =
            node.getAncestor((node) => node is ClassDeclaration);
        StringBuffer buffer = new StringBuffer();
        buffer.write("The element for the method ");
        buffer.write(node.name);
        buffer.write(" in ");
        buffer.write(classNode.name);
        buffer.write(" was not set while trying to resolve types.");
        AnalysisEngine.instance.logger.logError(
            buffer.toString(),
            new CaughtException(
                new AnalysisException(buffer.toString()), null));
      }
    }
    return null;
  }

  @override
  Object visitPartDirective(PartDirective node) {
    List<ElementAnnotation> annotations =
        _createElementAnnotations(node.metadata);
    _unitElement.setAnnotations(node.offset, annotations);
    return super.visitPartDirective(node);
  }

  @override
  Object visitVariableDeclaration(VariableDeclaration node) {
    bool isConst = node.isConst;
    bool isFinal = node.isFinal;
    Expression initializerNode = node.initializer;
    bool hasInitializer = initializerNode != null;
    VariableDeclarationList varList = node.parent;
    FieldDeclaration fieldNode =
        varList.parent is FieldDeclaration ? varList.parent : null;
    VariableElementImpl element;
    if (fieldNode != null) {
      SimpleIdentifier fieldName = node.name;
      FieldElementImpl field;
      if ((isConst || isFinal && !fieldNode.isStatic) && hasInitializer) {
        field = new ConstFieldElementImpl.forNode(fieldName);
      } else {
        field = new FieldElementImpl.forNode(fieldName);
      }
      element = field;
      field.isCovariant = fieldNode.covariantKeyword != null;
      field.isStatic = fieldNode.isStatic;
      _setCodeRange(element, node);
      setElementDocumentationComment(element, fieldNode);
      field.hasImplicitType = varList.type == null;
      _currentHolder.addField(field);
      fieldName.staticElement = field;
    } else {
      SimpleIdentifier variableName = node.name;
      TopLevelVariableElementImpl variable;
      if (isConst && hasInitializer) {
        variable = new ConstTopLevelVariableElementImpl.forNode(variableName);
      } else {
        variable = new TopLevelVariableElementImpl.forNode(variableName);
      }
      element = variable;
      _setCodeRange(element, node);
      if (varList.parent is TopLevelVariableDeclaration) {
        setElementDocumentationComment(element, varList.parent);
      }
      variable.hasImplicitType = varList.type == null;
      _currentHolder.addTopLevelVariable(variable);
      variableName.staticElement = element;
    }
    element.isConst = isConst;
    element.isFinal = isFinal;
    if (element is PropertyInducingElementImpl) {
      PropertyAccessorElementImpl_ImplicitGetter getter =
          new PropertyAccessorElementImpl_ImplicitGetter(element);
      _currentHolder.addAccessor(getter);
      if (!isConst && !isFinal) {
        PropertyAccessorElementImpl_ImplicitSetter setter =
            new PropertyAccessorElementImpl_ImplicitSetter(element);
        if (fieldNode != null) {
          (setter.parameters[0] as ParameterElementImpl).isExplicitlyCovariant =
              fieldNode.covariantKeyword != null;
        }
        _currentHolder.addAccessor(setter);
      }
    }
    return null;
  }

  @override
  Object visitVariableDeclarationList(VariableDeclarationList node) {
    super.visitVariableDeclarationList(node);
    AstNode parent = node.parent;
    List<ElementAnnotation> elementAnnotations;
    if (parent is FieldDeclaration) {
      elementAnnotations = _createElementAnnotations(parent.metadata);
    } else if (parent is TopLevelVariableDeclaration) {
      elementAnnotations = _createElementAnnotations(parent.metadata);
    } else {
      // Local variable declaration
      elementAnnotations = _createElementAnnotations(node.metadata);
    }
    _setVariableDeclarationListAnnotations(node, elementAnnotations);
    return null;
  }

  /**
   * Build the table mapping field names to field elements for the [fields]
   * defined in the current class.
   */
  void _buildFieldMap(List<FieldElement> fields) {
    _fieldMap = new HashMap<String, FieldElement>();
    int count = fields.length;
    for (int i = 0; i < count; i++) {
      FieldElement field = fields[i];
      _fieldMap[field.name] ??= field;
    }
  }

  /**
   * Creates the [ConstructorElement]s array with the single default constructor element.
   *
   * @param interfaceType the interface type for which to create a default constructor
   * @return the [ConstructorElement]s array with the single default constructor element
   */
  List<ConstructorElement> _createDefaultConstructors(
      ClassElementImpl definingClass) {
    ConstructorElementImpl constructor =
        new ConstructorElementImpl.forNode(null);
    constructor.isSynthetic = true;
    constructor.enclosingElement = definingClass;
    return <ConstructorElement>[constructor];
  }

  /**
   * Create the types associated with the given type parameters, setting the type of each type
   * parameter, and return an array of types corresponding to the given parameters.
   *
   * @param typeParameters the type parameters for which types are to be created
   * @return an array of types corresponding to the given parameters
   */
  List<DartType> _createTypeParameterTypes(
      List<TypeParameterElement> typeParameters) {
    int typeParameterCount = typeParameters.length;
    List<DartType> typeArguments = new List<DartType>(typeParameterCount);
    for (int i = 0; i < typeParameterCount; i++) {
      TypeParameterElementImpl typeParameter =
          typeParameters[i] as TypeParameterElementImpl;
      TypeParameterTypeImpl typeParameterType =
          new TypeParameterTypeImpl(typeParameter);
      typeParameter.type = typeParameterType;
      typeArguments[i] = typeParameterType;
    }
    return typeArguments;
  }

  @override
  void _setFieldParameterField(
      FormalParameter node, FieldFormalParameterElementImpl element) {
    if (node.parent?.parent is ConstructorDeclaration) {
      FieldElement field = _fieldMap == null ? null : _fieldMap[element.name];
      if (field != null) {
        element.field = field;
      }
    }
  }
}

/**
 * A `CompilationUnitBuilder` builds an element model for a single compilation
 * unit.
 */
class CompilationUnitBuilder {
  /**
   * Build the compilation unit element for the given [source] based on the
   * compilation [unit] associated with the source. Throw an AnalysisException
   * if the element could not be built.  [librarySource] is the source for the
   * containing library.
   */
  CompilationUnitElementImpl buildCompilationUnit(
      Source source, CompilationUnit unit, Source librarySource) {
    return PerformanceStatistics.resolve.makeCurrentWhile(() {
      if (unit == null) {
        return null;
      }
      ElementHolder holder = new ElementHolder();
      CompilationUnitElementImpl element =
          new CompilationUnitElementImpl(source.shortName);
      ElementBuilder builder = new ElementBuilder(holder, element);
      unit.accept(builder);
      element.accessors = holder.accessors;
      element.enums = holder.enums;
      element.functions = holder.functions;
      element.source = source;
      element.librarySource = librarySource;
      element.typeAliases = holder.typeAliases;
      element.types = holder.types;
      element.topLevelVariables = holder.topLevelVariables;
      unit.element = element;
      holder.validate();
      return element;
    });
  }
}

/**
 * Instances of the class `DirectiveElementBuilder` build elements for top
 * level library directives.
 */
class DirectiveElementBuilder extends SimpleAstVisitor<Object> {
  /**
   * The analysis context within which directive elements are being built.
   */
  final AnalysisContext context;

  /**
   * The library element for which directive elements are being built.
   */
  final LibraryElementImpl libraryElement;

  /**
   * Map from sources referenced by this library to their modification times.
   */
  final Map<Source, int> sourceModificationTimeMap;

  /**
   * Map from sources imported by this library to their corresponding library
   * elements.
   */
  final Map<Source, LibraryElement> importLibraryMap;

  /**
   * Map from sources imported by this library to their corresponding source
   * kinds.
   */
  final Map<Source, SourceKind> importSourceKindMap;

  /**
   * Map from sources exported by this library to their corresponding library
   * elements.
   */
  final Map<Source, LibraryElement> exportLibraryMap;

  /**
   * Map from sources exported by this library to their corresponding source
   * kinds.
   */
  final Map<Source, SourceKind> exportSourceKindMap;

  /**
   * The [ImportElement]s created so far.
   */
  final List<ImportElement> imports = <ImportElement>[];

  /**
   * The [ExportElement]s created so far.
   */
  final List<ExportElement> exports = <ExportElement>[];

  /**
   * The errors found while building directive elements.
   */
  final List<AnalysisError> errors = <AnalysisError>[];

  /**
   * Map from prefix names to their corresponding elements.
   */
  final HashMap<String, PrefixElementImpl> nameToPrefixMap =
      new HashMap<String, PrefixElementImpl>();

  /**
   * Indicates whether an explicit import of `dart:core` has been found.
   */
  bool explicitlyImportsCore = false;

  DirectiveElementBuilder(
      this.context,
      this.libraryElement,
      this.sourceModificationTimeMap,
      this.importLibraryMap,
      this.importSourceKindMap,
      this.exportLibraryMap,
      this.exportSourceKindMap);

  @override
  Object visitCompilationUnit(CompilationUnit node) {
    //
    // Resolve directives.
    //
    for (Directive directive in node.directives) {
      directive.accept(this);
    }
    //
    // Ensure "dart:core" import.
    //
    Source librarySource = libraryElement.source;
    Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
    if (!explicitlyImportsCore && coreLibrarySource != librarySource) {
      ImportElementImpl importElement = new ImportElementImpl(-1);
      importElement.importedLibrary = importLibraryMap[coreLibrarySource];
      importElement.isSynthetic = true;
      imports.add(importElement);
    }
    //
    // Populate the library element.
    //
    libraryElement.imports = imports;
    libraryElement.exports = exports;
    return null;
  }

  @override
  Object visitExportDirective(ExportDirective node) {
    // Remove previous element. (It will remain null if the target is missing.)
    node.element = null;
    Source exportedSource = node.selectedSource;
    int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
    // The exported source will be null if the URI in the export
    // directive was invalid.
    LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
    if (exportedLibrary != null) {
      ExportElementImpl exportElement = new ExportElementImpl(node.offset);
      exportElement.metadata = _getElementAnnotations(node.metadata);
      StringLiteral uriLiteral = node.uri;
      if (uriLiteral != null) {
        exportElement.uriOffset = uriLiteral.offset;
        exportElement.uriEnd = uriLiteral.end;
      }
      exportElement.uri = node.selectedUriContent;
      exportElement.combinators = _buildCombinators(node);
      exportElement.exportedLibrary = exportedLibrary;
      setElementDocumentationComment(exportElement, node);
      node.element = exportElement;
      exports.add(exportElement);
      if (exportedTime >= 0 &&
          exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
        int offset = node.offset;
        int length = node.length;
        if (uriLiteral != null) {
          offset = uriLiteral.offset;
          length = uriLiteral.length;
        }
        errors.add(new AnalysisError(
            libraryElement.source,
            offset,
            length,
            CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
            [uriLiteral.toSource()]));
      }
    }
    return null;
  }

  @override
  Object visitImportDirective(ImportDirective node) {
    // Remove previous element. (It will remain null if the target is missing.)
    node.element = null;
    Source importedSource = node.selectedSource;
    int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
    // The imported source will be null if the URI in the import
    // directive was invalid.
    LibraryElement importedLibrary = importLibraryMap[importedSource];
    if (importedLibrary != null) {
      if (importedLibrary.isDartCore) {
        explicitlyImportsCore = true;
      }
      ImportElementImpl importElement = new ImportElementImpl(node.offset);
      importElement.metadata = _getElementAnnotations(node.metadata);
      StringLiteral uriLiteral = node.uri;
      if (uriLiteral != null) {
        importElement.uriOffset = uriLiteral.offset;
        importElement.uriEnd = uriLiteral.end;
      }
      importElement.uri = node.selectedUriContent;
      importElement.deferred = node.deferredKeyword != null;
      importElement.combinators = _buildCombinators(node);
      importElement.importedLibrary = importedLibrary;
      setElementDocumentationComment(importElement, node);
      SimpleIdentifier prefixNode = node.prefix;
      if (prefixNode != null) {
        importElement.prefixOffset = prefixNode.offset;
        String prefixName = prefixNode.name;
        PrefixElementImpl prefix = nameToPrefixMap[prefixName];
        if (prefix == null) {
          prefix = new PrefixElementImpl.forNode(prefixNode);
          nameToPrefixMap[prefixName] = prefix;
        }
        importElement.prefix = prefix;
        prefixNode.staticElement = prefix;
      }
      node.element = importElement;
      imports.add(importElement);
      if (importedTime >= 0 &&
          importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
        int offset = node.offset;
        int length = node.length;
        if (uriLiteral != null) {
          offset = uriLiteral.offset;
          length = uriLiteral.length;
        }
        ErrorCode errorCode = importElement.isDeferred
            ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
            : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
        errors.add(new AnalysisError(libraryElement.source, offset, length,
            errorCode, [uriLiteral.toSource()]));
      }
    }
    return null;
  }

  @override
  Object visitLibraryDirective(LibraryDirective node) {
    (node.element as LibraryElementImpl)?.metadata =
        _getElementAnnotations(node.metadata);
    return null;
  }

  @override
  Object visitPartDirective(PartDirective node) {
    (node.element as CompilationUnitElementImpl)?.metadata =
        _getElementAnnotations(node.metadata);
    return null;
  }

  /**
   * Gather a list of the [ElementAnnotation]s referred to by the [Annotation]s
   * in [metadata].
   */
  List<ElementAnnotation> _getElementAnnotations(
      NodeList<Annotation> metadata) {
    if (metadata.isEmpty) {
      return ElementAnnotation.EMPTY_LIST;
    }
    return metadata.map((Annotation a) => a.elementAnnotation).toList();
  }

  /**
   * Build the element model representing the combinators declared by
   * the given [directive].
   */
  static List<NamespaceCombinator> _buildCombinators(
      NamespaceDirective directive) {
    _NamespaceCombinatorBuilder namespaceCombinatorBuilder =
        new _NamespaceCombinatorBuilder();
    for (Combinator combinator in directive.combinators) {
      combinator.accept(namespaceCombinatorBuilder);
    }
    return namespaceCombinatorBuilder.combinators;
  }
}

/**
 * Instances of the class `ElementBuilder` traverse an AST structure and build the element
 * model representing the AST structure.
 */
class ElementBuilder extends ApiElementBuilder {
  /**
   * Initialize a newly created element builder to build the elements for a
   * compilation unit. The [initialHolder] is the element holder to which the
   * children of the visited compilation unit node will be added.
   */
  ElementBuilder(ElementHolder initialHolder,
      CompilationUnitElement compilationUnitElement)
      : super(initialHolder, compilationUnitElement);

  @override
  Object visitBlockFunctionBody(BlockFunctionBody node) {
    _buildLocal(node);
    return null;
  }

  @override
  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
    super.visitDefaultFormalParameter(node);
    buildParameterInitializer(
        node.element as ParameterElementImpl, node.defaultValue);
    return null;
  }

  @override
  Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
    _buildLocal(node);
    return null;
  }

  @override
  Object visitVariableDeclaration(VariableDeclaration node) {
    super.visitVariableDeclaration(node);
    VariableElementImpl element = node.element as VariableElementImpl;
    buildVariableInitializer(element, node.initializer);
    return null;
  }

  void _buildLocal(AstNode node) {
    node.accept(new LocalElementBuilder(_currentHolder, _unitElement));
  }
}

/**
 * Traverse a [FunctionBody] and build elements for AST structures.
 */
class LocalElementBuilder extends _BaseElementBuilder {
  /**
   * Initialize a newly created element builder to build the elements for a
   * compilation unit. The [initialHolder] is the element holder to which the
   * children of the visited compilation unit node will be added.
   */
  LocalElementBuilder(ElementHolder initialHolder,
      CompilationUnitElementImpl compilationUnitElement)
      : super(initialHolder, compilationUnitElement);

  /**
   * Builds the variable elements associated with [node] and stores them in
   * the element holder.
   */
  void buildCatchVariableElements(CatchClause node) {
    SimpleIdentifier exceptionParameter = node.exceptionParameter;
    if (exceptionParameter != null) {
      // exception
      LocalVariableElementImpl exception =
          new LocalVariableElementImpl.forNode(exceptionParameter);
      if (node.exceptionType == null) {
        exception.hasImplicitType = true;
      }
      exception.setVisibleRange(node.offset, node.length);
      _currentHolder.addLocalVariable(exception);
      exceptionParameter.staticElement = exception;
      // stack trace
      SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
      if (stackTraceParameter != null) {
        LocalVariableElementImpl stackTrace =
            new LocalVariableElementImpl.forNode(stackTraceParameter);
        _setCodeRange(stackTrace, stackTraceParameter);
        stackTrace.setVisibleRange(node.offset, node.length);
        _currentHolder.addLocalVariable(stackTrace);
        stackTraceParameter.staticElement = stackTrace;
      }
    }
  }

  /**
   * Builds the label elements associated with [labels] and stores them in the
   * element holder.
   */
  void buildLabelElements(
      NodeList<Label> labels, bool onSwitchStatement, bool onSwitchMember) {
    for (Label label in labels) {
      SimpleIdentifier labelName = label.label;
      LabelElementImpl element = new LabelElementImpl.forNode(
          labelName, onSwitchStatement, onSwitchMember);
      labelName.staticElement = element;
      _currentHolder.addLabel(element);
    }
  }

  @override
  Object visitCatchClause(CatchClause node) {
    buildCatchVariableElements(node);
    return super.visitCatchClause(node);
  }

  @override
  Object visitDeclaredIdentifier(DeclaredIdentifier node) {
    SimpleIdentifier variableName = node.identifier;
    LocalVariableElementImpl element =
        new LocalVariableElementImpl.forNode(variableName);
    _setCodeRange(element, node);
    element.metadata = _createElementAnnotations(node.metadata);
    ForEachStatement statement = node.parent as ForEachStatement;
    element.setVisibleRange(statement.offset, statement.length);
    element.isConst = node.isConst;
    element.isFinal = node.isFinal;
    if (node.type == null) {
      element.hasImplicitType = true;
    }
    _currentHolder.addLocalVariable(element);
    variableName.staticElement = element;
    return null;
  }

  @override
  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
    super.visitDefaultFormalParameter(node);
    buildParameterInitializer(
        node.element as ParameterElementImpl, node.defaultValue);
    return null;
  }

  @override
  Object visitFunctionDeclaration(FunctionDeclaration node) {
    FunctionExpression expression = node.functionExpression;
    if (expression == null) {
      return null;
    }

    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);

    FunctionElementImpl element = new FunctionElementImpl.forNode(node.name);
    _setCodeRange(element, node);
    setElementDocumentationComment(element, node);
    element.metadata = _createElementAnnotations(node.metadata);
    FunctionBody body = expression.body;
    if (node.externalKeyword != null || body is NativeFunctionBody) {
      element.external = true;
    }
    element.functions = holder.functions;
    element.encloseElements(holder.labels);
    element.encloseElements(holder.localVariables);
    element.parameters = holder.parameters;
    element.typeParameters = holder.typeParameters;

    if (body.isAsynchronous) {
      element.asynchronous = body.isAsynchronous;
    }
    if (body.isGenerator) {
      element.generator = true;
    }

    {
      Block enclosingBlock = node.getAncestor((node) => node is Block);
      if (enclosingBlock != null) {
        element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
      }
    }

    if (node.returnType == null) {
      element.hasImplicitReturnType = true;
    }

    _currentHolder.addFunction(element);
    expression.element = element;
    node.name.staticElement = element;
    holder.validate();
    return null;
  }

  @override
  Object visitFunctionExpression(FunctionExpression node) {
    if (node.parent is FunctionDeclaration) {
      // visitFunctionDeclaration has already created the element for the
      // declaration.  We just need to visit children.
      return super.visitFunctionExpression(node);
    }

    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    FunctionElementImpl element =
        new FunctionElementImpl.forOffset(node.beginToken.offset);
    _setCodeRange(element, node);
    element.functions = holder.functions;
    element.encloseElements(holder.labels);
    element.encloseElements(holder.localVariables);
    element.parameters = holder.parameters;
    element.typeParameters = holder.typeParameters;

    FunctionBody body = node.body;
    if (body.isAsynchronous) {
      element.asynchronous = true;
    }
    if (body.isGenerator) {
      element.generator = true;
    }

    {
      Block enclosingBlock = node.getAncestor((node) => node is Block);
      if (enclosingBlock != null) {
        element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
      }
    }

    element.type = new FunctionTypeImpl(element);
    element.hasImplicitReturnType = true;
    _currentHolder.addFunction(element);
    node.element = element;
    holder.validate();
    return null;
  }

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

  @override
  Object visitSwitchCase(SwitchCase node) {
    buildLabelElements(node.labels, false, true);
    return super.visitSwitchCase(node);
  }

  @override
  Object visitSwitchDefault(SwitchDefault node) {
    buildLabelElements(node.labels, false, true);
    return super.visitSwitchDefault(node);
  }

  @override
  Object visitVariableDeclaration(VariableDeclaration node) {
    bool isConst = node.isConst;
    bool isFinal = node.isFinal;
    Expression initializerNode = node.initializer;
    VariableDeclarationList varList = node.parent;
    SimpleIdentifier variableName = node.name;
    LocalVariableElementImpl element;
    if (isConst && initializerNode != null) {
      element = new ConstLocalVariableElementImpl.forNode(variableName);
    } else {
      element = new LocalVariableElementImpl.forNode(variableName);
    }
    _setCodeRange(element, node);
    _setVariableVisibleRange(element, node);
    element.hasImplicitType = varList.type == null;
    _currentHolder.addLocalVariable(element);
    variableName.staticElement = element;
    element.isConst = isConst;
    element.isFinal = isFinal;
    buildVariableInitializer(element, initializerNode);
    return null;
  }

  @override
  Object visitVariableDeclarationList(VariableDeclarationList node) {
    super.visitVariableDeclarationList(node);
    List<ElementAnnotation> elementAnnotations =
        _createElementAnnotations(node.metadata);
    _setVariableDeclarationListAnnotations(node, elementAnnotations);
    return null;
  }

  void _setVariableVisibleRange(
      LocalVariableElementImpl element, VariableDeclaration node) {
    AstNode scopeNode;
    AstNode parent2 = node.parent.parent;
    if (parent2 is ForStatement) {
      scopeNode = parent2;
    } else {
      scopeNode = node.getAncestor((node) => node is Block);
    }
    element.setVisibleRange(scopeNode.offset, scopeNode.length);
  }
}

/**
 * Base class for API and local element builders.
 */
abstract class _BaseElementBuilder extends RecursiveAstVisitor<Object> {
  /**
   * The compilation unit element into which the elements being built will be
   * stored.
   */
  final CompilationUnitElementImpl _unitElement;

  /**
   * The element holder associated with the element that is currently being built.
   */
  ElementHolder _currentHolder;

  _BaseElementBuilder(this._currentHolder, this._unitElement);

  /**
   * If the [defaultValue] is not `null`, build the [FunctionElementImpl]
   * that corresponds it, and set it as the initializer for the [parameter].
   */
  void buildParameterInitializer(
      ParameterElementImpl parameter, Expression defaultValue) {
    if (defaultValue != null) {
      ElementHolder holder = new ElementHolder();
      _visit(holder, defaultValue);
      FunctionElementImpl initializer =
          new FunctionElementImpl.forOffset(defaultValue.beginToken.offset);
      initializer.hasImplicitReturnType = true;
      initializer.functions = holder.functions;
      initializer.encloseElements(holder.labels);
      initializer.encloseElements(holder.localVariables);
      initializer.parameters = holder.parameters;
      initializer.isSynthetic = true;
      initializer.type = new FunctionTypeImpl(initializer);
      parameter.initializer = initializer;
      parameter.defaultValueCode = defaultValue.toSource();
      holder.validate();
    }
  }

  /**
   * If the [initializer] is not `null`, build the [FunctionElementImpl] that
   * corresponds it, and set it as the initializer for the [variable].
   */
  void buildVariableInitializer(
      VariableElementImpl variable, Expression initializer) {
    if (initializer != null) {
      ElementHolder holder = new ElementHolder();
      _visit(holder, initializer);
      FunctionElementImpl initializerElement =
          new FunctionElementImpl.forOffset(initializer.beginToken.offset);
      initializerElement.hasImplicitReturnType = true;
      initializerElement.functions = holder.functions;
      initializerElement.encloseElements(holder.labels);
      initializerElement.encloseElements(holder.localVariables);
      initializerElement.isSynthetic = true;
      initializerElement.type = new FunctionTypeImpl(initializerElement);
      variable.initializer = initializerElement;
      holder.validate();
    }
  }

  @override
  Object visitDefaultFormalParameter(DefaultFormalParameter node) {
    NormalFormalParameter normalParameter = node.parameter;
    SimpleIdentifier parameterName = normalParameter.identifier;
    ParameterElementImpl parameter;
    if (normalParameter is FieldFormalParameter) {
      DefaultFieldFormalParameterElementImpl fieldParameter =
          new DefaultFieldFormalParameterElementImpl.forNode(parameterName);
      _setFieldParameterField(node, fieldParameter);
      parameter = fieldParameter;
    } else {
      parameter = new DefaultParameterElementImpl.forNode(parameterName);
    }
    _setCodeRange(parameter, node);
    parameter.isConst = node.isConst;
    parameter.isExplicitlyCovariant = node.parameter.covariantKeyword != null;
    parameter.isFinal = node.isFinal;
    parameter.parameterKind = node.kind;
    // visible range
    _setParameterVisibleRange(node, parameter);
    if (normalParameter is SimpleFormalParameter &&
        normalParameter.type == null) {
      parameter.hasImplicitType = true;
    }
    _currentHolder.addParameter(parameter);
    if (normalParameter is SimpleFormalParameterImpl) {
      normalParameter.element = parameter;
    }
    parameterName?.staticElement = parameter;
    normalParameter.accept(this);
    return null;
  }

  @override
  Object visitFieldFormalParameter(FieldFormalParameter node) {
    if (node.parent is! DefaultFormalParameter) {
      SimpleIdentifier parameterName = node.identifier;
      FieldFormalParameterElementImpl parameter =
          new FieldFormalParameterElementImpl.forNode(parameterName);
      _setCodeRange(parameter, node);
      _setFieldParameterField(node, parameter);
      parameter.isConst = node.isConst;
      parameter.isExplicitlyCovariant = node.covariantKeyword != null;
      parameter.isFinal = node.isFinal;
      parameter.parameterKind = node.kind;
      _currentHolder.addParameter(parameter);
      parameterName.staticElement = parameter;
    }
    //
    // The children of this parameter include any parameters defined on the type
    // of this parameter.
    //
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    ParameterElementImpl element = node.element;
    element.metadata = _createElementAnnotations(node.metadata);
    element.parameters = holder.parameters;
    element.typeParameters = holder.typeParameters;
    holder.validate();
    return null;
  }

  @override
  Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    if (node.parent is! DefaultFormalParameter) {
      SimpleIdentifier parameterName = node.identifier;
      ParameterElementImpl parameter =
          new ParameterElementImpl.forNode(parameterName);
      _setCodeRange(parameter, node);
      parameter.isConst = node.isConst;
      parameter.isExplicitlyCovariant = node.covariantKeyword != null;
      parameter.isFinal = node.isFinal;
      parameter.parameterKind = node.kind;
      _setParameterVisibleRange(node, parameter);
      _currentHolder.addParameter(parameter);
      parameterName.staticElement = parameter;
    }
    //
    // The children of this parameter include any parameters defined on the type
    //of this parameter.
    //
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    ParameterElementImpl element = node.element;
    element.metadata = _createElementAnnotations(node.metadata);
    element.parameters = holder.parameters;
    element.typeParameters = holder.typeParameters;
    holder.validate();
    return null;
  }

  @override
  Object visitGenericFunctionType(GenericFunctionType node) {
    ElementHolder holder = new ElementHolder();
    _visitChildren(holder, node);
    GenericFunctionTypeElementImpl element =
        new GenericFunctionTypeElementImpl.forOffset(node.beginToken.offset);
    _setCodeRange(element, node);
    element.parameters = holder.parameters;
    element.typeParameters = holder.typeParameters;
    FunctionType type = new FunctionTypeImpl(element);
    element.type = type;
    (node as GenericFunctionTypeImpl).type = type;
    holder.validate();
    return null;
  }

  @override
  Object visitSimpleFormalParameter(SimpleFormalParameter node) {
    ParameterElementImpl parameter;
    if (node.parent is! DefaultFormalParameter) {
      SimpleIdentifier parameterName = node.identifier;
      parameter = new ParameterElementImpl.forNode(parameterName);
      _setCodeRange(parameter, node);
      parameter.isConst = node.isConst;
      parameter.isExplicitlyCovariant = node.covariantKeyword != null;
      parameter.isFinal = node.isFinal;
      parameter.parameterKind = node.kind;
      _setParameterVisibleRange(node, parameter);
      if (node.type == null) {
        parameter.hasImplicitType = true;
      }
      _currentHolder.addParameter(parameter);
      (node as SimpleFormalParameterImpl).element = parameter;
      parameterName?.staticElement = parameter;
    }
    super.visitSimpleFormalParameter(node);
    parameter ??= node.element;
    parameter?.metadata = _createElementAnnotations(node.metadata);
    return null;
  }

  @override
  Object visitTypeParameter(TypeParameter node) {
    SimpleIdentifier parameterName = node.name;
    TypeParameterElementImpl typeParameter =
        new TypeParameterElementImpl.forNode(parameterName);
    _setCodeRange(typeParameter, node);
    typeParameter.metadata = _createElementAnnotations(node.metadata);
    TypeParameterTypeImpl typeParameterType =
        new TypeParameterTypeImpl(typeParameter);
    typeParameter.type = typeParameterType;
    _currentHolder.addTypeParameter(typeParameter);
    parameterName.staticElement = typeParameter;
    return super.visitTypeParameter(node);
  }

  /**
   * For each [Annotation] found in [annotations], create a new
   * [ElementAnnotation] object and set the [Annotation] to point to it.
   */
  List<ElementAnnotation> _createElementAnnotations(
      NodeList<Annotation> annotations) {
    if (annotations.isEmpty) {
      return ElementAnnotation.EMPTY_LIST;
    }
    return annotations.map((Annotation a) {
      ElementAnnotationImpl elementAnnotation =
          new ElementAnnotationImpl(_unitElement);
      a.elementAnnotation = elementAnnotation;
      return elementAnnotation;
    }).toList();
  }

  /**
   * Return the body of the function that contains the given [parameter], or
   * `null` if no function body could be found.
   */
  FunctionBody _getFunctionBody(FormalParameter parameter) {
    AstNode parent = parameter?.parent?.parent;
    if (parent is ConstructorDeclaration) {
      return parent.body;
    } else if (parent is FunctionExpression) {
      return parent.body;
    } else if (parent is MethodDeclaration) {
      return parent.body;
    }
    return null;
  }

  void _setCodeRange(ElementImpl element, AstNode node) {
    element.setCodeRange(node.offset, node.length);
  }

  void _setFieldParameterField(
      FormalParameter node, FieldFormalParameterElementImpl element) {}

  /**
   * Sets the visible source range for formal parameter.
   */
  void _setParameterVisibleRange(
      FormalParameter node, ParameterElementImpl element) {
    FunctionBody body = _getFunctionBody(node);
    if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
      element.setVisibleRange(body.offset, body.length);
    }
  }

  void _setVariableDeclarationListAnnotations(VariableDeclarationList node,
      List<ElementAnnotation> elementAnnotations) {
    for (VariableDeclaration variableDeclaration in node.variables) {
      ElementImpl element = variableDeclaration.element as ElementImpl;
      _setCodeRange(element, node.parent);
      element.metadata = elementAnnotations;
    }
  }

  /**
   * Make the given holder be the current holder while visiting the given node.
   *
   * @param holder the holder that will gather elements that are built while visiting the children
   * @param node the node to be visited
   */
  void _visit(ElementHolder holder, AstNode node) {
    if (node != null) {
      ElementHolder previousHolder = _currentHolder;
      _currentHolder = holder;
      try {
        node.accept(this);
      } finally {
        _currentHolder = previousHolder;
      }
    }
  }

  /**
   * Make the given holder be the current holder while visiting the children of the given node.
   *
   * @param holder the holder that will gather elements that are built while visiting the children
   * @param node the node whose children are to be visited
   */
  void _visitChildren(ElementHolder holder, AstNode node) {
    if (node != null) {
      ElementHolder previousHolder = _currentHolder;
      _currentHolder = holder;
      try {
        node.visitChildren(this);
      } finally {
        _currentHolder = previousHolder;
      }
    }
  }
}

class _ElementBuilder_visitClassDeclaration extends UnifyingAstVisitor<Object> {
  final ApiElementBuilder builder;

  List<ClassMember> nonFields;

  _ElementBuilder_visitClassDeclaration(this.builder, this.nonFields) : super();

  @override
  Object visitConstructorDeclaration(ConstructorDeclaration node) {
    nonFields.add(node);
    return null;
  }

  @override
  Object visitMethodDeclaration(MethodDeclaration node) {
    nonFields.add(node);
    return null;
  }

  @override
  Object visitNode(AstNode node) => node.accept(builder);
}

/**
 * Instances of the class [_NamespaceCombinatorBuilder] can be used to visit
 * [Combinator] AST nodes and generate [NamespaceCombinator] elements.
 */
class _NamespaceCombinatorBuilder extends SimpleAstVisitor<Object> {
  /**
   * Elements generated so far.
   */
  final List<NamespaceCombinator> combinators = <NamespaceCombinator>[];

  @override
  Object visitHideCombinator(HideCombinator node) {
    HideElementCombinatorImpl hide = new HideElementCombinatorImpl();
    hide.hiddenNames = _getIdentifiers(node.hiddenNames);
    combinators.add(hide);
    return null;
  }

  @override
  Object visitShowCombinator(ShowCombinator node) {
    ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
    show.offset = node.offset;
    show.end = node.end;
    show.shownNames = _getIdentifiers(node.shownNames);
    combinators.add(show);
    return null;
  }

  /**
   * Return the lexical identifiers associated with the given [identifiers].
   */
  static List<String> _getIdentifiers(NodeList<SimpleIdentifier> identifiers) {
    return identifiers.map((identifier) => identifier.name).toList();
  }
}
