// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:math';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.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/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/exception/exception.dart';
import 'package:analyzer/src/summary2/ast_binary_flags.dart';
import 'package:analyzer/src/summary2/ast_binary_tag.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
import 'package:analyzer/src/summary2/linked_unit_context.dart';
import 'package:analyzer/src/task/inference_error.dart';

class ApplyResolutionVisitor extends ThrowingAstVisitor<void> {
  final LinkedUnitContext _unitContext;
  final LinkedResolutionReader _resolution;

  /// The stack of [TypeParameterElement]s and [ParameterElement] that are
  /// available in the scope of [_nextElement] and [_nextType].
  ///
  /// This stack is shared with [_resolution].
  final List<Element> _localElements;

  final List<ElementImpl> _enclosingElements = [];

  ApplyResolutionVisitor(
    this._unitContext,
    this._localElements,
    this._resolution,
  ) {
    _enclosingElements.add(_unitContext.element);
  }

  /// TODO(scheglov) make private
  void addParentTypeParameters(AstNode node) {
    var enclosing = node.parent;
    if (enclosing is ClassOrMixinDeclaration) {
      var typeParameterList = enclosing.typeParameters;
      if (typeParameterList == null) return;

      for (var typeParameter in typeParameterList.typeParameters) {
        var element = typeParameter.declaredElement;
        _localElements.add(element);
      }
    } else if (enclosing is ExtensionDeclaration) {
      var typeParameterList = enclosing.typeParameters;
      if (typeParameterList == null) return;

      for (var typeParameter in typeParameterList.typeParameters) {
        var element = typeParameter.declaredElement;
        _localElements.add(element);
      }
    } else if (enclosing is VariableDeclarationList) {
      var enclosing2 = enclosing.parent;
      if (enclosing2 is FieldDeclaration) {
        return addParentTypeParameters(enclosing2);
      } else if (enclosing2 is TopLevelVariableDeclaration) {
        return;
      } else {
        throw UnimplementedError('${enclosing2.runtimeType}');
      }
    } else {
      throw UnimplementedError('${enclosing.runtimeType}');
    }
  }

  @override
  void visitAdjacentStrings(AdjacentStrings node) {
    node.strings.accept(this);
    // TODO(scheglov) type?
  }

  @override
  void visitAnnotation(Annotation node) {
    _expectMarker(MarkerTag.Annotation_name);
    node.name.accept(this);
    _expectMarker(MarkerTag.Annotation_constructorName);
    node.constructorName?.accept(this);
    _expectMarker(MarkerTag.Annotation_arguments);
    node.arguments?.accept(this);
    _expectMarker(MarkerTag.Annotation_element);
    node.element = _nextElement();
  }

  @override
  void visitArgumentList(ArgumentList node) {
    _expectMarker(MarkerTag.ArgumentList_arguments);
    node.arguments.accept(this);
    _expectMarker(MarkerTag.ArgumentList_end);
  }

  @override
  void visitAsExpression(AsExpression node) {
    _expectMarker(MarkerTag.AsExpression_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.AsExpression_type);
    node.type.accept(this);
    _expectMarker(MarkerTag.AsExpression_expression2);
    _expression(node);
    _expectMarker(MarkerTag.AsExpression_end);
  }

  @override
  void visitAssertInitializer(AssertInitializer node) {
    _expectMarker(MarkerTag.AssertInitializer_condition);
    node.condition.accept(this);
    _expectMarker(MarkerTag.AssertInitializer_message);
    node.message?.accept(this);
    _expectMarker(MarkerTag.AssertInitializer_end);
  }

  @override
  void visitAssignmentExpression(AssignmentExpression node) {
    var nodeImpl = node as AssignmentExpressionImpl;
    _expectMarker(MarkerTag.AssignmentExpression_leftHandSide);
    node.leftHandSide.accept(this);
    _expectMarker(MarkerTag.AssignmentExpression_rightHandSide);
    node.rightHandSide.accept(this);
    _expectMarker(MarkerTag.AssignmentExpression_staticElement);
    node.staticElement = _nextElement();
    _expectMarker(MarkerTag.AssignmentExpression_readElement);
    nodeImpl.readElement = _nextElement();
    _expectMarker(MarkerTag.AssignmentExpression_readType);
    nodeImpl.readType = _nextType();
    _expectMarker(MarkerTag.AssignmentExpression_writeElement);
    nodeImpl.writeElement = _nextElement();
    _expectMarker(MarkerTag.AssignmentExpression_writeType);
    nodeImpl.writeType = _nextType();
    _expectMarker(MarkerTag.AssignmentExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.AssignmentExpression_end);
  }

  @override
  void visitBinaryExpression(BinaryExpression node) {
    _expectMarker(MarkerTag.BinaryExpression_leftOperand);
    node.leftOperand.accept(this);
    _expectMarker(MarkerTag.BinaryExpression_rightOperand);
    node.rightOperand.accept(this);

    _expectMarker(MarkerTag.BinaryExpression_staticElement);
    node.staticElement = _nextElement();

    _expectMarker(MarkerTag.BinaryExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.BinaryExpression_end);
  }

  @override
  void visitBooleanLiteral(BooleanLiteral node) {
    _expression(node);
  }

  @override
  void visitCascadeExpression(CascadeExpression node) {
    _expectMarker(MarkerTag.CascadeExpression_target);
    node.target.accept(this);
    _expectMarker(MarkerTag.CascadeExpression_cascadeSections);
    node.cascadeSections.accept(this);
    _expectMarker(MarkerTag.CascadeExpression_end);
    node.staticType = node.target.staticType;
  }

  @override
  visitClassDeclaration(ClassDeclaration node) {
    _assertNoLocalElements();

    var element = node.declaredElement as ClassElementImpl;
    element.isSimplyBounded = _resolution.readByte() != 0;
    _enclosingElements.add(element);

    try {
      _expectMarker(MarkerTag.ClassDeclaration_typeParameters);
      node.typeParameters?.accept(this);
      _expectMarker(MarkerTag.ClassDeclaration_extendsClause);
      node.extendsClause?.accept(this);
      _expectMarker(MarkerTag.ClassDeclaration_withClause);
      node.withClause?.accept(this);
      _expectMarker(MarkerTag.ClassDeclaration_implementsClause);
      node.implementsClause?.accept(this);
      _expectMarker(MarkerTag.ClassDeclaration_nativeClause);
      node.nativeClause?.accept(this);
      _expectMarker(MarkerTag.ClassDeclaration_namedCompilationUnitMember);
      _namedCompilationUnitMember(node);
      _expectMarker(MarkerTag.ClassDeclaration_end);
    } catch (e, stackTrace) {
      // TODO(scheglov) Remove after fixing http://dartbug.com/44449
      var headerStr = _astCodeBeforeMarkerOrMaxLength(node, '{', 1000);
      throw CaughtExceptionWithFiles(e, stackTrace, {
        'state': '''
element: ${element.reference}
header: $headerStr
resolution.bytes.length: ${_resolution.bytes.length}
resolution.byteOffset: ${_resolution.byteOffset}
''',
      });
    }

    _enclosingElements.removeLast();
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    _assertNoLocalElements();
    var element = node.declaredElement as ClassElementImpl;
    _enclosingElements.add(element);

    element.isSimplyBounded = _resolution.readByte() != 0;
    _expectMarker(MarkerTag.ClassTypeAlias_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.ClassTypeAlias_superclass);
    node.superclass?.accept(this);
    _expectMarker(MarkerTag.ClassTypeAlias_withClause);
    node.withClause?.accept(this);
    _expectMarker(MarkerTag.ClassTypeAlias_implementsClause);
    node.implementsClause?.accept(this);
    _expectMarker(MarkerTag.ClassTypeAlias_typeAlias);
    _typeAlias(node);
    _expectMarker(MarkerTag.ClassTypeAlias_end);

    _enclosingElements.removeLast();
  }

  @override
  void visitConditionalExpression(ConditionalExpression node) {
    _expectMarker(MarkerTag.ConditionalExpression_condition);
    node.condition.accept(this);
    _expectMarker(MarkerTag.ConditionalExpression_thenExpression);
    node.thenExpression.accept(this);
    _expectMarker(MarkerTag.ConditionalExpression_elseExpression);
    node.elseExpression.accept(this);
    _expression(node);
  }

  @override
  void visitConfiguration(Configuration node) {
    _expectMarker(MarkerTag.Configuration_name);
    node.name?.accept(this);
    _expectMarker(MarkerTag.Configuration_value);
    node.value?.accept(this);
    _expectMarker(MarkerTag.Configuration_uri);
    node.uri?.accept(this);
    _expectMarker(MarkerTag.Configuration_end);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    _assertNoLocalElements();
    _pushEnclosingClassTypeParameters(node);

    var element = node.declaredElement as ConstructorElementImpl;
    _enclosingElements.add(element.enclosingElement);
    _enclosingElements.add(element);

    _expectMarker(MarkerTag.ConstructorDeclaration_returnType);
    node.returnType?.accept(this);
    _expectMarker(MarkerTag.ConstructorDeclaration_parameters);
    node.parameters?.accept(this);

    for (var parameter in node.parameters.parameters) {
      _localElements.add(parameter.declaredElement);
    }

    _expectMarker(MarkerTag.ConstructorDeclaration_initializers);
    node.initializers?.accept(this);
    _expectMarker(MarkerTag.ConstructorDeclaration_redirectedConstructor);
    node.redirectedConstructor?.accept(this);
    _expectMarker(MarkerTag.ConstructorDeclaration_classMember);
    _classMember(node);
    _expectMarker(MarkerTag.ConstructorDeclaration_end);

    _enclosingElements.removeLast();
    _enclosingElements.removeLast();
  }

  @override
  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
    _expectMarker(MarkerTag.ConstructorFieldInitializer_fieldName);
    node.fieldName.accept(this);
    _expectMarker(MarkerTag.ConstructorFieldInitializer_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.ConstructorFieldInitializer_end);
  }

  @override
  void visitConstructorName(ConstructorName node) {
    // Rewrite:
    //   ConstructorName
    //     type: TypeName
    //       name: PrefixedIdentifier
    //     name: null
    // into:
    //    ConstructorName
    //      type: TypeName
    //        name: SimpleIdentifier
    //      name: SimpleIdentifier
    var hasName = _resolution.readByte() != 0;
    if (hasName && node.name == null) {
      var typeName = node.type.name as PrefixedIdentifier;
      NodeReplacer.replace(
        node.type,
        astFactory.typeName(typeName.prefix, null),
      );
      node.name = typeName.identifier;
    }

    _expectMarker(MarkerTag.ConstructorName_type);
    node.type.accept(this);
    _expectMarker(MarkerTag.ConstructorName_name);
    node.name?.accept(this);
    _expectMarker(MarkerTag.ConstructorName_staticElement);
    node.staticElement = _nextElement();
    _expectMarker(MarkerTag.ConstructorName_end);
  }

  @override
  void visitDeclaredIdentifier(DeclaredIdentifier node) {
    _expectMarker(MarkerTag.DeclaredIdentifier_type);
    node.type?.accept(this);
    _expectMarker(MarkerTag.DeclaredIdentifier_identifier);
    // node.identifier.accept(this);
    _expectMarker(MarkerTag.DeclaredIdentifier_declaration);
    _declaration(node);
    _expectMarker(MarkerTag.DeclaredIdentifier_end);
  }

  @override
  visitDefaultFormalParameter(DefaultFormalParameter node) {
    var nodeImpl = node as DefaultFormalParameterImpl;

    var enclosing = _enclosingElements.last;
    var name = node.identifier?.name ?? '';
    var reference = node.isNamed && enclosing.reference != null
        ? enclosing.reference.getChild('@parameter').getChild(name)
        : null;
    ParameterElementImpl element;
    if (node.parameter is FieldFormalParameter) {
      element = DefaultFieldFormalParameterElementImpl.forLinkedNode(
          enclosing, reference, node);
    } else {
      element =
          DefaultParameterElementImpl.forLinkedNode(enclosing, reference, node);
    }

    var summaryData = nodeImpl.summaryData as SummaryDataForFormalParameter;
    element.setCodeRange(summaryData.codeOffset, summaryData.codeLength);

    _expectMarker(MarkerTag.DefaultFormalParameter_parameter);
    node.parameter.accept(this);
    _expectMarker(MarkerTag.DefaultFormalParameter_defaultValue);
    node.defaultValue?.accept(this);
    _expectMarker(MarkerTag.DefaultFormalParameter_end);
  }

  @override
  void visitDottedName(DottedName node) {
    node.components.accept(this);
  }

  @override
  void visitDoubleLiteral(DoubleLiteral node) {
    // TODO(scheglov) type?
  }

  @override
  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
    _expectMarker(MarkerTag.EnumConstantDeclaration_name);
    _expectMarker(MarkerTag.EnumConstantDeclaration_declaration);
    _declaration(node);
    _expectMarker(MarkerTag.EnumConstantDeclaration_end);
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    _expectMarker(MarkerTag.EnumDeclaration_constants);
    node.constants.accept(this);
    _expectMarker(MarkerTag.EnumDeclaration_namedCompilationUnitMember);
    _namedCompilationUnitMember(node);
    _expectMarker(MarkerTag.EnumDeclaration_end);
  }

  @override
  void visitExportDirective(ExportDirective node) {
    _expectMarker(MarkerTag.ExportDirective_namespaceDirective);
    _namespaceDirective(node);
    _expectMarker(MarkerTag.ExportDirective_exportedLibrary);
    (node.element as ExportElementImpl).exportedLibrary = _nextElement();
    _expectMarker(MarkerTag.ExportDirective_end);
  }

  @override
  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
    node.expression.accept(this);
  }

  @override
  visitExtendsClause(ExtendsClause node) {
    _expectMarker(MarkerTag.ExtendsClause_superclass);
    node.superclass.accept(this);
    _expectMarker(MarkerTag.ExtendsClause_end);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    _assertNoLocalElements();

    var element = node.declaredElement as ExtensionElementImpl;
    _enclosingElements.add(element);

    _expectMarker(MarkerTag.ExtensionDeclaration_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.ExtensionDeclaration_extendedType);
    node.extendedType?.accept(this);
    _expectMarker(MarkerTag.ExtensionDeclaration_compilationUnitMember);
    _compilationUnitMember(node);
    _expectMarker(MarkerTag.ExtensionDeclaration_end);

    _enclosingElements.removeLast();
  }

  @override
  void visitExtensionOverride(
    ExtensionOverride node, {
    bool readRewrite = true,
  }) {
    // Read possible rewrite of `MethodInvocation`.
    // If we are here, we don't need it.
    if (readRewrite) {
      _resolution.readByte();
    }

    _expectMarker(MarkerTag.ExtensionOverride_extensionName);
    node.extensionName.accept(this);
    _expectMarker(MarkerTag.ExtensionOverride_typeArguments);
    node.typeArguments?.accept(this);
    _expectMarker(MarkerTag.ExtensionOverride_argumentList);
    node.argumentList.accept(this);
    _expectMarker(MarkerTag.ExtensionOverride_extendedType);
    (node as ExtensionOverrideImpl).extendedType = _nextType();
    _expectMarker(MarkerTag.ExtensionOverride_end);
    // TODO(scheglov) typeArgumentTypes?
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    _assertNoLocalElements();
    _pushEnclosingClassTypeParameters(node);

    _expectMarker(MarkerTag.FieldDeclaration_fields);
    node.fields.accept(this);
    _expectMarker(MarkerTag.FieldDeclaration_classMember);
    _classMember(node);
    _expectMarker(MarkerTag.FieldDeclaration_end);
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    ParameterElement element;
    if (node.parent is! DefaultFormalParameter) {
      var enclosing = _enclosingElements.last;
      element =
          FieldFormalParameterElementImpl.forLinkedNode(enclosing, null, node);
    }

    var localElementsLength = _localElements.length;

    _expectMarker(MarkerTag.FieldFormalParameter_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.FieldFormalParameter_type);
    node.type?.accept(this);
    _expectMarker(MarkerTag.FieldFormalParameter_parameters);
    node.parameters?.accept(this);
    _expectMarker(MarkerTag.FieldFormalParameter_normalFormalParameter);
    _normalFormalParameter(node, element);
    _expectMarker(MarkerTag.FieldFormalParameter_end);

    _localElements.length = localElementsLength;
  }

  @override
  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
    _expectMarker(MarkerTag.ForEachPartsWithDeclaration_loopVariable);
    node.loopVariable.accept(this);
    _expectMarker(MarkerTag.ForEachPartsWithDeclaration_forEachParts);
    _forEachParts(node);
    _expectMarker(MarkerTag.ForEachPartsWithDeclaration_end);
  }

  @override
  void visitForElement(ForElement node) {
    _expectMarker(MarkerTag.ForElement_body);
    node.body.accept(this);
    _expectMarker(MarkerTag.ForElement_forMixin);
    _forMixin(node as ForElementImpl);
    _expectMarker(MarkerTag.ForElement_end);
  }

  @override
  visitFormalParameterList(FormalParameterList node) {
    _expectMarker(MarkerTag.FormalParameterList_parameters);
    node.parameters.accept(this);
    _expectMarker(MarkerTag.FormalParameterList_end);
  }

  @override
  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
    for (var variable in node.variables.variables) {
      var nameNode = variable.name;
      nameNode.staticElement = LocalVariableElementImpl(
        nameNode.name,
        nameNode.offset,
      );
    }
    _expectMarker(MarkerTag.ForPartsWithDeclarations_variables);
    node.variables.accept(this);
    _expectMarker(MarkerTag.ForPartsWithDeclarations_forParts);
    _forParts(node);
    _expectMarker(MarkerTag.ForPartsWithDeclarations_end);
  }

  @override
  void visitForPartsWithExpression(ForPartsWithExpression node) {
    _expectMarker(MarkerTag.ForPartsWithExpression_initialization);
    node.initialization?.accept(this);
    _expectMarker(MarkerTag.ForPartsWithExpression_forParts);
    _forParts(node);
    _expectMarker(MarkerTag.ForPartsWithExpression_end);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    _assertNoLocalElements();

    var element = node.declaredElement as ExecutableElementImpl;
    assert(element != null);

    _enclosingElements.add(element);

    _expectMarker(MarkerTag.FunctionDeclaration_functionExpression);
    node.functionExpression.accept(this);
    _expectMarker(MarkerTag.FunctionDeclaration_returnType);
    node.returnType?.accept(this);

    _expectMarker(MarkerTag.FunctionDeclaration_namedCompilationUnitMember);
    _namedCompilationUnitMember(node);
    _expectMarker(MarkerTag.FunctionDeclaration_returnTypeType);
    element.returnType = _nextType();
    _expectMarker(MarkerTag.FunctionDeclaration_end);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    _expectMarker(MarkerTag.FunctionExpression_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.FunctionExpression_parameters);
    node.parameters?.accept(this);
    _expectMarker(MarkerTag.FunctionExpression_end);
  }

  @override
  void visitFunctionExpressionInvocation(
    FunctionExpressionInvocation node, {
    bool readRewrite = true,
  }) {
    // Read possible rewrite of `MethodInvocation`.
    // If we are here, we don't need it.
    if (readRewrite) {
      _resolution.readByte();
    }

    _expectMarker(MarkerTag.FunctionExpressionInvocation_function);
    node.function.accept(this);
    _expectMarker(MarkerTag.FunctionExpressionInvocation_invocationExpression);
    _invocationExpression(node);
    _expectMarker(MarkerTag.FunctionExpressionInvocation_end);
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    _assertNoLocalElements();

    var element = node.declaredElement as FunctionTypeAliasElementImpl;
    _enclosingElements.add(element);

    _expectMarker(MarkerTag.FunctionTypeAlias_typeParameters);
    node.typeParameters?.accept(this);

    _enclosingElements.add(element.function);
    _expectMarker(MarkerTag.FunctionTypeAlias_returnType);
    node.returnType?.accept(this);
    _expectMarker(MarkerTag.FunctionTypeAlias_parameters);
    node.parameters?.accept(this);
    _enclosingElements.removeLast();

    _expectMarker(MarkerTag.FunctionTypeAlias_typeAlias);
    _typeAlias(node);

    _expectMarker(MarkerTag.FunctionTypeAlias_returnTypeType);
    element.function.returnType = _nextType();
    _expectMarker(MarkerTag.FunctionTypeAlias_flags);
    element.isSimplyBounded = _resolution.readByte() != 0;
    element.hasSelfReference = _resolution.readByte() != 0;
    _expectMarker(MarkerTag.FunctionTypeAlias_end);

    _enclosingElements.removeLast();
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    var element = node.declaredElement;
    if (node.parent is! DefaultFormalParameter) {
      var enclosing = _enclosingElements.last;
      element =
          ParameterElementImpl.forLinkedNodeFactory(enclosing, null, node);
    }

    var localElementsLength = _localElements.length;

    _expectMarker(MarkerTag.FunctionTypedFormalParameter_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.FunctionTypedFormalParameter_returnType);
    node.returnType?.accept(this);
    _expectMarker(MarkerTag.FunctionTypedFormalParameter_parameters);
    node.parameters?.accept(this);
    _expectMarker(MarkerTag.FunctionTypedFormalParameter_normalFormalParameter);
    _normalFormalParameter(node, element);
    _expectMarker(MarkerTag.FunctionTypedFormalParameter_end);

    _localElements.length = localElementsLength;
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    var nodeImpl = node as GenericFunctionTypeImpl;
    var localElementsLength = _localElements.length;

    var element = nodeImpl.declaredElement as GenericFunctionTypeElementImpl;
    element ??= GenericFunctionTypeElementImpl.forLinkedNode(
        _enclosingElements.last, null, node);
    _enclosingElements.add(element);

    _expectMarker(MarkerTag.GenericFunctionType_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.GenericFunctionType_returnType);
    node.returnType?.accept(this);
    _expectMarker(MarkerTag.GenericFunctionType_parameters);
    node.parameters?.accept(this);
    _expectMarker(MarkerTag.GenericFunctionType_type);
    nodeImpl.type = _nextType();
    _expectMarker(MarkerTag.GenericFunctionType_end);

    _localElements.length = localElementsLength;
    _enclosingElements.removeLast();
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    _assertNoLocalElements();

    var element = node.declaredElement as TypeAliasElementImpl;
    assert(element != null);

    _enclosingElements.add(element);

    _expectMarker(MarkerTag.GenericTypeAlias_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.GenericTypeAlias_type);
    node.type?.accept(this);
    _expectMarker(MarkerTag.GenericTypeAlias_typeAlias);
    _typeAlias(node);
    _expectMarker(MarkerTag.GenericTypeAlias_flags);
    element.isSimplyBounded = _resolution.readByte() != 0;
    element.hasSelfReference = _resolution.readByte() != 0;
    _expectMarker(MarkerTag.GenericTypeAlias_end);

    _enclosingElements.removeLast();
  }

  @override
  void visitHideCombinator(HideCombinator node) {
    node.hiddenNames.accept(this);
  }

  @override
  void visitIfElement(IfElement node) {
    _expectMarker(MarkerTag.IfElement_condition);
    node.condition.accept(this);
    _expectMarker(MarkerTag.IfElement_thenElement);
    node.thenElement.accept(this);
    _expectMarker(MarkerTag.IfElement_elseElement);
    node.elseElement?.accept(this);
    _expectMarker(MarkerTag.IfElement_end);
  }

  @override
  visitImplementsClause(ImplementsClause node) {
    _expectMarker(MarkerTag.ImplementsClause_interfaces);
    node.interfaces.accept(this);
    _expectMarker(MarkerTag.ImplementsClause_end);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    _expectMarker(MarkerTag.ImportDirective_namespaceDirective);
    _namespaceDirective(node);

    var element = node.element as ImportElementImpl;
    _expectMarker(MarkerTag.ImportDirective_importedLibrary);
    element.importedLibrary = _nextElement();

    _expectMarker(MarkerTag.ImportDirective_end);
  }

  @override
  void visitIndexExpression(IndexExpression node) {
    _expectMarker(MarkerTag.IndexExpression_target);
    node.target?.accept(this);
    _expectMarker(MarkerTag.IndexExpression_index);
    node.index.accept(this);
    _expectMarker(MarkerTag.IndexExpression_staticElement);
    node.staticElement = _nextElement();
    _expectMarker(MarkerTag.IndexExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.IndexExpression_end);
  }

  @override
  void visitInstanceCreationExpression(
    InstanceCreationExpression node, {
    bool readRewrite = true,
  }) {
    // Read possible rewrite of `MethodInvocation`.
    // If we are here, we don't need it.
    if (readRewrite) {
      _resolution.readByte();
    }

    _expectMarker(MarkerTag.InstanceCreationExpression_constructorName);
    node.constructorName.accept(this);
    _expectMarker(MarkerTag.InstanceCreationExpression_argumentList);
    node.argumentList.accept(this);
    _expectMarker(MarkerTag.InstanceCreationExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.InstanceCreationExpression_end);
    _resolveNamedExpressions(
      node.constructorName.staticElement,
      node.argumentList,
    );
  }

  @override
  void visitIntegerLiteral(IntegerLiteral node) {
    _expression(node);
  }

  @override
  void visitInterpolationExpression(InterpolationExpression node) {
    node.expression.accept(this);
  }

  @override
  void visitInterpolationString(InterpolationString node) {
    // TODO(scheglov) type?
  }

  @override
  void visitIsExpression(IsExpression node) {
    _expectMarker(MarkerTag.IsExpression_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.IsExpression_type);
    node.type.accept(this);
    _expectMarker(MarkerTag.IsExpression_expression2);
    _expression(node);
    _expectMarker(MarkerTag.IsExpression_end);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    node.name.accept(this);
    _directive(node);
  }

  @override
  void visitLibraryIdentifier(LibraryIdentifier node) {
    node.components.accept(this);
  }

  @override
  void visitListLiteral(ListLiteral node) {
    _expectMarker(MarkerTag.ListLiteral_typeArguments);
    node.typeArguments?.accept(this);
    _expectMarker(MarkerTag.ListLiteral_elements);
    node.elements.accept(this);
    _expectMarker(MarkerTag.ListLiteral_expression);
    _expression(node);
    _expectMarker(MarkerTag.ListLiteral_end);
  }

  @override
  void visitMapLiteralEntry(MapLiteralEntry node) {
    _expectMarker(MarkerTag.MapLiteralEntry_key);
    node.key.accept(this);
    _expectMarker(MarkerTag.MapLiteralEntry_value);
    node.value.accept(this);
  }

  @override
  visitMethodDeclaration(MethodDeclaration node) {
    _assertNoLocalElements();
    _pushEnclosingClassTypeParameters(node);

    var element = node.declaredElement as ExecutableElementImpl;
    _enclosingElements.add(element.enclosingElement);
    _enclosingElements.add(element);

    try {
      _expectMarker(MarkerTag.MethodDeclaration_typeParameters);
      node.typeParameters?.accept(this);
      _expectMarker(MarkerTag.MethodDeclaration_returnType);
      node.returnType?.accept(this);
      _expectMarker(MarkerTag.MethodDeclaration_parameters);
      node.parameters?.accept(this);
      _expectMarker(MarkerTag.MethodDeclaration_classMember);
      _classMember(node);

      _expectMarker(MarkerTag.MethodDeclaration_returnTypeType);
      element.returnType = _nextType();
      _expectMarker(MarkerTag.MethodDeclaration_inferenceError);
      _setTopLevelInferenceError(element);
      if (element is MethodElementImpl) {
        _expectMarker(MarkerTag.MethodDeclaration_flags);
        element.isOperatorEqualWithParameterTypeFromObject =
            _resolution.readByte() != 0;
      }
      _expectMarker(MarkerTag.MethodDeclaration_end);
    } catch (e, stackTrace) {
      // TODO(scheglov) Remove after fixing http://dartbug.com/44449
      var headerStr = _astCodeBeforeMarkerOrMaxLength(node, '{', 1000);
      throw CaughtExceptionWithFiles(e, stackTrace, {
        'state': '''
element: ${element.reference}
header: $headerStr
resolution.bytes.length: ${_resolution.bytes.length}
resolution.byteOffset: ${_resolution.byteOffset}
''',
      });
    }

    _enclosingElements.removeLast();
    _enclosingElements.removeLast();
  }

  @override
  void visitMethodInvocation(MethodInvocation node) {
    var rewriteTag = _resolution.readByte();
    if (rewriteTag == MethodInvocationRewriteTag.none) {
      // No rewrite necessary.
    } else if (rewriteTag == MethodInvocationRewriteTag.extensionOverride) {
      Identifier identifier;
      if (node.target == null) {
        identifier = node.methodName;
      } else {
        identifier = astFactory.prefixedIdentifier(
          node.target as SimpleIdentifier,
          node.operator,
          node.methodName,
        );
      }
      var replacement = astFactory.extensionOverride(
        extensionName: identifier,
        typeArguments: node.typeArguments,
        argumentList: node.argumentList,
      );
      NodeReplacer.replace(node, replacement);
      visitExtensionOverride(replacement, readRewrite: false);
      return;
    } else if (rewriteTag ==
        MethodInvocationRewriteTag.functionExpressionInvocation) {
      var target = node.target;
      Expression expression;
      if (target == null) {
        expression = node.methodName;
      } else {
        expression = astFactory.propertyAccess(
          target,
          node.operator,
          node.methodName,
        );
      }
      var replacement = astFactory.functionExpressionInvocation(
        expression,
        node.typeArguments,
        node.argumentList,
      );
      NodeReplacer.replace(node, replacement);
      visitFunctionExpressionInvocation(replacement, readRewrite: false);
      return;
    } else if (rewriteTag ==
        MethodInvocationRewriteTag.instanceCreationExpression_withName) {
      var replacement = astFactory.instanceCreationExpression(
        null,
        astFactory.constructorName(
          astFactory.typeName(node.target as Identifier, null),
          node.operator,
          node.methodName,
        ),
        node.argumentList,
      );
      NodeReplacer.replace(node, replacement);
      visitInstanceCreationExpression(replacement, readRewrite: false);
      return;
    } else if (rewriteTag ==
        MethodInvocationRewriteTag.instanceCreationExpression_withoutName) {
      var typeNameName = node.target == null
          ? node.methodName
          : astFactory.prefixedIdentifier(
              node.target as SimpleIdentifier,
              node.operator,
              node.methodName,
            );
      var replacement = astFactory.instanceCreationExpression(
        null,
        astFactory.constructorName(
          astFactory.typeName(typeNameName, node.typeArguments),
          null,
          null,
        ),
        node.argumentList,
      );
      NodeReplacer.replace(node, replacement);
      visitInstanceCreationExpression(replacement, readRewrite: false);
      return;
    } else {
      throw StateError('[rewriteTag: $rewriteTag][node: $node]');
    }

    _expectMarker(MarkerTag.MethodInvocation_target);
    node.target?.accept(this);
    _expectMarker(MarkerTag.MethodInvocation_methodName);
    node.methodName.accept(this);
    _expectMarker(MarkerTag.MethodInvocation_invocationExpression);
    _invocationExpression(node);
    _expectMarker(MarkerTag.MethodInvocation_end);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    _assertNoLocalElements();
    var element = node.declaredElement as MixinElementImpl;
    element.isSimplyBounded = _resolution.readByte() != 0;
    element.superInvokedNames = _resolution.readStringList();
    _enclosingElements.add(element);

    _expectMarker(MarkerTag.MixinDeclaration_typeParameters);
    node.typeParameters?.accept(this);
    _expectMarker(MarkerTag.MixinDeclaration_onClause);
    node.onClause?.accept(this);
    _expectMarker(MarkerTag.MixinDeclaration_implementsClause);
    node.implementsClause?.accept(this);
    _expectMarker(MarkerTag.MixinDeclaration_namedCompilationUnitMember);
    _namedCompilationUnitMember(node);
    _expectMarker(MarkerTag.MixinDeclaration_end);

    _enclosingElements.removeLast();
  }

  @override
  void visitNamedExpression(NamedExpression node) {
    _expectMarker(MarkerTag.NamedExpression_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.NamedExpression_end);
  }

  @override
  void visitNativeClause(NativeClause node) {
    _expectMarker(MarkerTag.NativeClause_name);
    node.name.accept(this);
    _expectMarker(MarkerTag.NativeClause_end);
  }

  @override
  void visitNullLiteral(NullLiteral node) {
    // TODO(scheglov) type?
  }

  @override
  void visitOnClause(OnClause node) {
    _expectMarker(MarkerTag.OnClause_superclassConstraints);
    node.superclassConstraints.accept(this);
    _expectMarker(MarkerTag.OnClause_end);
  }

  @override
  void visitParenthesizedExpression(ParenthesizedExpression node) {
    _expectMarker(MarkerTag.ParenthesizedExpression_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.ParenthesizedExpression_expression2);
    _expression(node);
    _expectMarker(MarkerTag.ParenthesizedExpression_end);
  }

  @override
  void visitPartDirective(PartDirective node) {
    _uriBasedDirective(node);
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    _expectMarker(MarkerTag.PartOfDirective_libraryName);
    node.libraryName?.accept(this);
    _expectMarker(MarkerTag.PartOfDirective_uri);
    node.uri?.accept(this);
    _expectMarker(MarkerTag.PartOfDirective_directive);
    _directive(node);
    _expectMarker(MarkerTag.PartOfDirective_end);
  }

  @override
  void visitPostfixExpression(PostfixExpression node) {
    var nodeImpl = node as PostfixExpressionImpl;
    _expectMarker(MarkerTag.PostfixExpression_operand);
    node.operand.accept(this);
    _expectMarker(MarkerTag.PostfixExpression_staticElement);
    node.staticElement = _nextElement();
    if (node.operator.type.isIncrementOperator) {
      _expectMarker(MarkerTag.PostfixExpression_readElement);
      nodeImpl.readElement = _nextElement();
      _expectMarker(MarkerTag.PostfixExpression_readType);
      nodeImpl.readType = _nextType();
      _expectMarker(MarkerTag.PostfixExpression_writeElement);
      nodeImpl.writeElement = _nextElement();
      _expectMarker(MarkerTag.PostfixExpression_writeType);
      nodeImpl.writeType = _nextType();
    }
    _expectMarker(MarkerTag.PostfixExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.PostfixExpression_end);
  }

  @override
  void visitPrefixedIdentifier(PrefixedIdentifier node) {
    _expectMarker(MarkerTag.PrefixedIdentifier_prefix);
    node.prefix.accept(this);
    _expectMarker(MarkerTag.PrefixedIdentifier_identifier);
    node.identifier.accept(this);
    _expectMarker(MarkerTag.PrefixedIdentifier_expression);
    _expression(node);
    _expectMarker(MarkerTag.PrefixedIdentifier_end);
  }

  @override
  void visitPrefixExpression(PrefixExpression node) {
    var nodeImpl = node as PrefixExpressionImpl;
    _expectMarker(MarkerTag.PrefixExpression_operand);
    node.operand.accept(this);
    _expectMarker(MarkerTag.PrefixExpression_staticElement);
    node.staticElement = _nextElement();
    if (node.operator.type.isIncrementOperator) {
      _expectMarker(MarkerTag.PrefixExpression_readElement);
      nodeImpl.readElement = _nextElement();
      _expectMarker(MarkerTag.PrefixExpression_readType);
      nodeImpl.readType = _nextType();
      _expectMarker(MarkerTag.PrefixExpression_writeElement);
      nodeImpl.writeElement = _nextElement();
      _expectMarker(MarkerTag.PrefixExpression_writeType);
      nodeImpl.writeType = _nextType();
    }
    _expectMarker(MarkerTag.PrefixExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.PrefixExpression_end);
  }

  @override
  void visitPropertyAccess(PropertyAccess node) {
    _expectMarker(MarkerTag.PropertyAccess_target);
    node.target?.accept(this);
    _expectMarker(MarkerTag.PropertyAccess_propertyName);
    node.propertyName.accept(this);

    _expectMarker(MarkerTag.PropertyAccess_expression);
    _expression(node);
    _expectMarker(MarkerTag.PropertyAccess_end);
  }

  @override
  void visitRedirectingConstructorInvocation(
      RedirectingConstructorInvocation node) {
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_constructorName);
    node.constructorName?.accept(this);
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_argumentList);
    node.argumentList.accept(this);
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_staticElement);
    node.staticElement = _nextElement();
    _resolveNamedExpressions(node.staticElement, node.argumentList);
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_end);
  }

  @override
  void visitSetOrMapLiteral(SetOrMapLiteral node) {
    _expectMarker(MarkerTag.SetOrMapLiteral_flags);
    var mapOrSetBits = _resolution.readByte();
    if ((mapOrSetBits & 0x01) != 0) {
      (node as SetOrMapLiteralImpl).becomeMap();
    } else if ((mapOrSetBits & 0x02) != 0) {
      (node as SetOrMapLiteralImpl).becomeSet();
    }

    _expectMarker(MarkerTag.SetOrMapLiteral_typeArguments);
    node.typeArguments?.accept(this);
    _expectMarker(MarkerTag.SetOrMapLiteral_elements);
    node.elements.accept(this);
    _expectMarker(MarkerTag.SetOrMapLiteral_expression);
    _expression(node);
    _expectMarker(MarkerTag.SetOrMapLiteral_end);
  }

  @override
  void visitShowCombinator(ShowCombinator node) {
    node.shownNames.accept(this);
  }

  @override
  visitSimpleFormalParameter(SimpleFormalParameter node) {
    var element = node.declaredElement as ParameterElementImpl;
    if (node.parent is! DefaultFormalParameter) {
      var enclosing = _enclosingElements.last;
      element =
          ParameterElementImpl.forLinkedNodeFactory(enclosing, null, node);
    }

    _expectMarker(MarkerTag.SimpleFormalParameter_type);
    node.type?.accept(this);
    _expectMarker(MarkerTag.SimpleFormalParameter_normalFormalParameter);
    _normalFormalParameter(node, element);

    _expectMarker(MarkerTag.SimpleFormalParameter_flags);
    element.inheritsCovariant = _resolution.readByte() != 0;
    _expectMarker(MarkerTag.SimpleFormalParameter_end);
  }

  @override
  visitSimpleIdentifier(SimpleIdentifier node) {
    _expectMarker(MarkerTag.SimpleIdentifier_staticElement);
    node.staticElement = _nextElement();
    _expectMarker(MarkerTag.SimpleIdentifier_expression);
    _expression(node);
    _expectMarker(MarkerTag.SimpleIdentifier_end);
  }

  @override
  void visitSimpleStringLiteral(SimpleStringLiteral node) {
    // TODO(scheglov) type?
  }

  @override
  void visitSpreadElement(SpreadElement node) {
    _expectMarker(MarkerTag.SpreadElement_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.SpreadElement_end);
  }

  @override
  void visitStringInterpolation(StringInterpolation node) {
    _expectMarker(MarkerTag.StringInterpolation_elements);
    node.elements.accept(this);
    _expectMarker(MarkerTag.StringInterpolation_end);
    // TODO(scheglov) type?
  }

  @override
  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    _expectMarker(MarkerTag.SuperConstructorInvocation_constructorName);
    node.constructorName?.accept(this);
    _expectMarker(MarkerTag.SuperConstructorInvocation_argumentList);
    node.argumentList.accept(this);
    _expectMarker(MarkerTag.SuperConstructorInvocation_staticElement);
    node.staticElement = _nextElement();
    _resolveNamedExpressions(node.staticElement, node.argumentList);
    _expectMarker(MarkerTag.SuperConstructorInvocation_end);
  }

  @override
  void visitSuperExpression(SuperExpression node) {
    _expectMarker(MarkerTag.SuperExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.SuperExpression_end);
  }

  @override
  void visitSymbolLiteral(SymbolLiteral node) {
    _expression(node);
  }

  @override
  void visitThisExpression(ThisExpression node) {
    _expectMarker(MarkerTag.ThisExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.ThisExpression_end);
  }

  @override
  void visitThrowExpression(ThrowExpression node) {
    _expectMarker(MarkerTag.ThrowExpression_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.ThrowExpression_expression2);
    _expression(node);
    _expectMarker(MarkerTag.ThrowExpression_end);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    _expectMarker(MarkerTag.TopLevelVariableDeclaration_variables);
    node.variables.accept(this);
    _expectMarker(MarkerTag.TopLevelVariableDeclaration_compilationUnitMember);
    _compilationUnitMember(node);
    _expectMarker(MarkerTag.TopLevelVariableDeclaration_end);
  }

  @override
  visitTypeArgumentList(TypeArgumentList node) {
    _expectMarker(MarkerTag.TypeArgumentList_arguments);
    node.arguments?.accept(this);
    _expectMarker(MarkerTag.TypeArgumentList_end);
  }

  @override
  visitTypeName(TypeName node) {
    _expectMarker(MarkerTag.TypeName_name);
    node.name.accept(this);
    _expectMarker(MarkerTag.TypeName_typeArguments);
    node.typeArguments?.accept(this);

    _expectMarker(MarkerTag.TypeName_type);
    node.type = _nextType();

    _expectMarker(MarkerTag.TypeName_end);
  }

  @override
  visitTypeParameterList(TypeParameterList node) {
    for (var typeParameter in node.typeParameters) {
      var element = TypeParameterElementImpl.forLinkedNode(
        _enclosingElements.last,
        typeParameter,
      );
      _localElements.add(element);
    }

    _expectMarker(MarkerTag.TypeParameterList_typeParameters);
    for (var node in node.typeParameters) {
      var nodeImpl = node as TypeParameterImpl;
      var element = node.declaredElement as TypeParameterElementImpl;

      var summaryData = nodeImpl.summaryData as SummaryDataForTypeParameter;
      element.setCodeRange(summaryData.codeOffset, summaryData.codeLength);

      _expectMarker(MarkerTag.TypeParameter_bound);
      node.bound?.accept(this);
      element.bound = node.bound?.type;

      _expectMarker(MarkerTag.TypeParameter_declaration);
      _declaration(node);
      element.metadata = _buildAnnotations(
        _unitContext.element,
        node.metadata,
      );

      _expectMarker(MarkerTag.TypeParameter_variance);
      element.variance = _decodeVariance(_resolution.readByte());
      _expectMarker(MarkerTag.TypeParameter_defaultType);
      element.defaultType = _nextType();
      _expectMarker(MarkerTag.TypeParameter_end);

      // TODO(scheglov) We used to do this with the previous elements impl.
      // We probably still do this.
      // But the code below is bad and incomplete.
      // And why does this affect MethodMember(s)?
      {
        var parent = node.parent;
        if (parent is ClassDeclaration) {
          (parent.declaredElement as ElementImpl).encloseElement(element);
        } else if (parent is ClassTypeAlias) {
          (parent.declaredElement as ElementImpl).encloseElement(element);
        } else if (parent is ExtensionDeclaration) {
          (parent.declaredElement as ElementImpl).encloseElement(element);
        } else if (parent is FunctionExpression) {
          var parent2 = parent.parent;
          if (parent2 is FunctionDeclaration) {
            (parent2.declaredElement as ElementImpl).encloseElement(element);
          }
        } else if (parent is FunctionTypeAlias) {
          (parent.declaredElement as ElementImpl).encloseElement(element);
        } else if (parent is GenericTypeAlias) {
          (parent.declaredElement as ElementImpl).encloseElement(element);
        } else if (parent is MethodDeclaration) {
          (parent.declaredElement as ElementImpl).encloseElement(element);
        } else if (parent is MixinDeclaration) {
          (parent.declaredElement as ElementImpl).encloseElement(element);
        }
      }
    }
    _expectMarker(MarkerTag.TypeParameterList_end);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    var element = node.declaredElement as VariableElementImpl;
    _expectMarker(MarkerTag.VariableDeclaration_type);
    element.type = _nextType();
    _expectMarker(MarkerTag.VariableDeclaration_inferenceError);
    _setTopLevelInferenceError(element);
    if (element is FieldElementImpl) {
      _expectMarker(MarkerTag.VariableDeclaration_inheritsCovariant);
      element.inheritsCovariant = _resolution.readByte() != 0;
    }

    _expectMarker(MarkerTag.VariableDeclaration_initializer);
    node.initializer?.accept(this);
    _expectMarker(MarkerTag.VariableDeclaration_end);
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    _expectMarker(MarkerTag.VariableDeclarationList_type);
    node.type?.accept(this);
    _expectMarker(MarkerTag.VariableDeclarationList_variables);
    node.variables.accept(this);
    _expectMarker(MarkerTag.VariableDeclarationList_annotatedNode);
    _annotatedNode(node);
    _expectMarker(MarkerTag.VariableDeclarationList_end);
  }

  @override
  void visitWithClause(WithClause node) {
    _expectMarker(MarkerTag.WithClause_mixinTypes);
    node.mixinTypes.accept(this);
    _expectMarker(MarkerTag.WithClause_end);
  }

  void _annotatedNode(AnnotatedNode node) {
    _expectMarker(MarkerTag.AnnotatedNode_metadata);
    node.metadata?.accept(this);
    _expectMarker(MarkerTag.AnnotatedNode_end);
  }

  void _assertNoLocalElements() {
    assert(_localElements.isEmpty);
    assert(_enclosingElements.length == 1 &&
        _enclosingElements.first is CompilationUnitElement);
  }

  /// Return annotations for the given [nodeList] in the [unit].
  List<ElementAnnotation> _buildAnnotations(
      CompilationUnitElementImpl unit, List<Annotation> nodeList) {
    var length = nodeList.length;
    if (length == 0) {
      return const <ElementAnnotation>[];
    }

    var annotations = List<ElementAnnotation>.filled(length, null);
    for (int i = 0; i < length; i++) {
      var ast = nodeList[i];
      annotations[i] = ElementAnnotationImpl(unit)
        ..annotationAst = ast
        ..element = ast.element;
    }
    return annotations;
  }

  void _classMember(ClassMember node) {
    _expectMarker(MarkerTag.ClassMember_declaration);
    _declaration(node);
  }

  void _compilationUnitMember(CompilationUnitMember node) {
    _declaration(node);
  }

  void _declaration(Declaration node) {
    _annotatedNode(node);
  }

  void _directive(Directive node) {
    _annotatedNode(node);
  }

  void _expectMarker(MarkerTag tag) {
    if (enableDebugResolutionMarkers) {
      var actualIndex = _resolution.readUInt30();
      if (actualIndex != tag.index) {
        if (actualIndex < MarkerTag.values.length) {
          var actualTag = MarkerTag.values[actualIndex];
          throw StateError('Expected $tag, found $actualIndex = $actualTag');
        } else {
          throw StateError('Expected $tag, found $actualIndex');
        }
      }
    }
  }

  void _expression(Expression node) {
    _expectMarker(MarkerTag.Expression_staticType);
    node.staticType = _nextType();
  }

  void _forEachParts(ForEachParts node) {
    _expectMarker(MarkerTag.ForEachParts_iterable);
    node.iterable.accept(this);
    _expectMarker(MarkerTag.ForEachParts_forLoopParts);
    _forLoopParts(node);
    _expectMarker(MarkerTag.ForEachParts_end);
  }

  void _forLoopParts(ForLoopParts node) {}

  void _formalParameter(FormalParameter node) {
    _expectMarker(MarkerTag.FormalParameter_type);
    (node.declaredElement as ParameterElementImpl).type = _nextType();
  }

  void _forMixin(ForMixin node) {
    _expectMarker(MarkerTag.ForMixin_forLoopParts);
    node.forLoopParts.accept(this);
  }

  void _forParts(ForParts node) {
    _expectMarker(MarkerTag.ForParts_condition);
    node.condition?.accept(this);
    _expectMarker(MarkerTag.ForParts_updaters);
    node.updaters.accept(this);
    _expectMarker(MarkerTag.ForParts_forLoopParts);
    _forLoopParts(node);
    _expectMarker(MarkerTag.ForParts_end);
  }

  void _invocationExpression(InvocationExpression node) {
    _expectMarker(MarkerTag.InvocationExpression_typeArguments);
    node.typeArguments?.accept(this);
    _expectMarker(MarkerTag.InvocationExpression_argumentList);
    node.argumentList.accept(this);
    _expectMarker(MarkerTag.InvocationExpression_expression);
    _expression(node);
    _expectMarker(MarkerTag.InvocationExpression_end);
    // TODO(scheglov) typeArgumentTypes and staticInvokeType?
    var nodeImpl = node as InvocationExpressionImpl;
    nodeImpl.typeArgumentTypes = [];
  }

  void _namedCompilationUnitMember(NamedCompilationUnitMember node) {
    _compilationUnitMember(node);
  }

  void _namespaceDirective(NamespaceDirective node) {
    _expectMarker(MarkerTag.NamespaceDirective_combinators);
    node.combinators?.accept(this);
    _expectMarker(MarkerTag.NamespaceDirective_configurations);
    node.configurations?.accept(this);
    _expectMarker(MarkerTag.NamespaceDirective_uriBasedDirective);
    _uriBasedDirective(node);
    _expectMarker(MarkerTag.NamespaceDirective_end);
  }

  Element _nextElement() {
    return _resolution.nextElement();
  }

  DartType _nextType() {
    return _resolution.nextType();
  }

  void _normalFormalParameter(
    NormalFormalParameter node,
    ParameterElementImpl element,
  ) {
    if (node.parent is! DefaultFormalParameter) {
      var nodeImpl = node as NormalFormalParameterImpl;
      var summaryData = nodeImpl.summaryData as SummaryDataForFormalParameter;
      element.setCodeRange(summaryData.codeOffset, summaryData.codeLength);
    }

    _expectMarker(MarkerTag.NormalFormalParameter_metadata);
    node.metadata?.accept(this);
    _expectMarker(MarkerTag.NormalFormalParameter_formalParameter);
    _formalParameter(node);
    _expectMarker(MarkerTag.NormalFormalParameter_end);
  }

  /// TODO(scheglov) also enclosing elements
  void _pushEnclosingClassTypeParameters(ClassMember node) {
    var parent = node.parent;
    if (parent is ClassOrMixinDeclaration) {
      var classElement = parent.declaredElement;
      _localElements.addAll(classElement.typeParameters);
    } else {
      var extension = parent as ExtensionDeclaration;
      var classElement = extension.declaredElement;
      _localElements.addAll(classElement.typeParameters);
    }
  }

  TopLevelInferenceError _readTopLevelInferenceError() {
    var kindIndex = _resolution.readByte();
    var kind = TopLevelInferenceErrorKind.values[kindIndex];
    if (kind == TopLevelInferenceErrorKind.none) {
      return null;
    }
    return TopLevelInferenceError(
      kind: kind,
      arguments: _resolution.readStringList(),
    );
  }

  void _resolveNamedExpressions(
    Element executable,
    ArgumentList argumentList,
  ) {
    for (var argument in argumentList.arguments) {
      if (argument is NamedExpression) {
        var nameNode = argument.name.label;
        if (executable is ExecutableElement) {
          var parameters = executable.parameters;
          var name = nameNode.name;
          nameNode.staticElement = parameters.firstWhere((e) {
            return e.name == name;
          }, orElse: () => null);
        }
      }
    }
  }

  void _setTopLevelInferenceError(ElementImpl element) {
    if (element is MethodElementImpl) {
      element.typeInferenceError = _readTopLevelInferenceError();
    } else if (element is PropertyInducingElementImpl) {
      element.typeInferenceError = _readTopLevelInferenceError();
    }
  }

  void _typeAlias(TypeAlias node) {
    _namedCompilationUnitMember(node);
  }

  void _uriBasedDirective(UriBasedDirective node) {
    _expectMarker(MarkerTag.UriBasedDirective_uri);
    node.uri.accept(this);
    _expectMarker(MarkerTag.UriBasedDirective_directive);
    _directive(node);
    _expectMarker(MarkerTag.UriBasedDirective_end);
  }

  /// TODO(scheglov) Remove after fixing http://dartbug.com/44449
  static String _astCodeBeforeMarkerOrMaxLength(
      AstNode node, String marker, int maxLength) {
    var nodeStr = '$node';
    var indexOfBody = nodeStr.indexOf(marker);
    if (indexOfBody == -1) {
      indexOfBody = min(maxLength, nodeStr.length);
    }
    return nodeStr.substring(0, indexOfBody);
  }

  static Variance _decodeVariance(int encoding) {
    if (encoding == 0) {
      return null;
    } else if (encoding == 1) {
      return Variance.unrelated;
    } else if (encoding == 2) {
      return Variance.covariant;
    } else if (encoding == 3) {
      return Variance.contravariant;
    } else if (encoding == 4) {
      return Variance.invariant;
    } else {
      throw UnimplementedError('encoding: $encoding');
    }
  }
}
