// 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/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/ast_factory.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';
import 'package:collection/collection.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(covariant AnnotationImpl 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(covariant AsExpressionImpl 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() as MethodElement?;
    _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 visitAwaitExpression(covariant AwaitExpressionImpl node) {
    _expectMarker(MarkerTag.AwaitExpression_expression);
    node.expression.accept(this);
    _expectMarker(MarkerTag.AwaitExpression_expression2);
    _expression(node);
    _expectMarker(MarkerTag.AwaitExpression_end);
  }

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

    _expectMarker(MarkerTag.BinaryExpression_staticElement);
    node.staticElement = _nextElement() as MethodElement?;

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

  @override
  void visitBooleanLiteral(covariant BooleanLiteralImpl node) {
    _expression(node);
  }

  @override
  void visitCascadeExpression(covariant CascadeExpressionImpl 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(covariant ConditionalExpressionImpl 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(covariant ConstructorNameImpl 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() as ConstructorElement?;
    _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 enclosingReference = enclosing.reference;
    var reference = node.isNamed && enclosingReference != null
        ? enclosingReference.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) {
    var elementImpl = node.element as ExportElementImpl;
    _expectMarker(MarkerTag.ExportDirective_namespaceDirective);
    _namespaceDirective(node);
    _expectMarker(MarkerTag.ExportDirective_exportedLibrary);
    elementImpl.exportedLibrary = _nextElement() as LibraryElement?;
    _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(covariant FieldFormalParameterImpl node) {
    if (node.declaredElement == null) {
      assert(node.parent is! DefaultFormalParameter);
      var enclosing = _enclosingElements.last;
      var element =
          FieldFormalParameterElementImpl.forLinkedNode(enclosing, null, node);
      _normalFormalParameterNotDefault(node, element);
    }

    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);
    _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_forLoopParts);
    node.forLoopParts.accept(this);
    _expectMarker(MarkerTag.ForElement_body);
    node.body.accept(this);
    _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) {
      variable as VariableDeclarationImpl;
      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;
    _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(
    covariant FunctionExpressionInvocationImpl 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 TypeAliasElementImpl;
    _enclosingElements.add(element);

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

    var function = element.aliasedElement as GenericFunctionTypeElementImpl;
    _enclosingElements.add(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);
    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(
      covariant FunctionTypedFormalParameterImpl node) {
    if (node.declaredElement == null) {
      assert(node.parent is! DefaultFormalParameter);
      var enclosing = _enclosingElements.last;
      var element =
          ParameterElementImpl.forLinkedNodeFactory(enclosing, null, node);
      _normalFormalParameterNotDefault(node, element);
    }

    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);
    _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;
    _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() as LibraryElement?;

    _expectMarker(MarkerTag.ImportDirective_end);
  }

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

  @override
  void visitInstanceCreationExpression(
    covariant InstanceCreationExpressionImpl 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(covariant IntegerLiteralImpl node) {
    _expression(node);
  }

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

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

  @override
  void visitIsExpression(covariant IsExpressionImpl 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(covariant ListLiteralImpl 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 as ElementImpl);
    _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(covariant MethodInvocationImpl 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(
      covariant ParenthesizedExpressionImpl 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() as MethodElement?;
    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(covariant PrefixedIdentifierImpl 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() as MethodElement?;
    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(covariant PropertyAccessImpl 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(
      covariant RedirectingConstructorInvocationImpl node) {
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_constructorName);
    node.constructorName?.accept(this);
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_argumentList);
    node.argumentList.accept(this);
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_staticElement);
    node.staticElement = _nextElement() as ConstructorElement?;
    _resolveNamedExpressions(node.staticElement, node.argumentList);
    _expectMarker(MarkerTag.RedirectingConstructorInvocation_end);
  }

  @override
  void visitSetOrMapLiteral(covariant SetOrMapLiteralImpl node) {
    _expectMarker(MarkerTag.SetOrMapLiteral_flags);
    var mapOrSetBits = _resolution.readByte();
    if ((mapOrSetBits & 0x01) != 0) {
      node.becomeMap();
    } else if ((mapOrSetBits & 0x02) != 0) {
      node.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(covariant SimpleFormalParameterImpl node) {
    var element = node.declaredElement as ParameterElementImpl?;
    if (element == null) {
      assert(node.parent is! DefaultFormalParameter);
      var enclosing = _enclosingElements.last;
      element =
          ParameterElementImpl.forLinkedNodeFactory(enclosing, null, node);
      _normalFormalParameterNotDefault(node, element);
    }

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

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

  @override
  visitSimpleIdentifier(covariant SimpleIdentifierImpl 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(
      covariant SuperConstructorInvocationImpl node) {
    _expectMarker(MarkerTag.SuperConstructorInvocation_constructorName);
    node.constructorName?.accept(this);
    _expectMarker(MarkerTag.SuperConstructorInvocation_argumentList);
    node.argumentList.accept(this);
    _expectMarker(MarkerTag.SuperConstructorInvocation_staticElement);
    node.staticElement = _nextElement() as ConstructorElement?;
    _resolveNamedExpressions(node.staticElement, node.argumentList);
    _expectMarker(MarkerTag.SuperConstructorInvocation_end);
  }

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

  @override
  void visitSymbolLiteral(covariant SymbolLiteralImpl node) {
    _expression(node);
  }

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

  @override
  void visitThrowExpression(covariant ThrowExpressionImpl 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(covariant TypeNameImpl 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) {
      typeParameter as TypeParameterImpl;
      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>[];
    }

    return List.generate(length, (index) {
      var ast = nodeList[index];
      return ElementAnnotationImpl(unit)
        ..annotationAst = ast
        ..element = ast.element;
    });
  }

  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(ExpressionImpl 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 _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(covariant InvocationExpressionImpl 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;
    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) {
    _expectMarker(MarkerTag.NormalFormalParameter_metadata);
    node.metadata.accept(this);
    _expectMarker(MarkerTag.NormalFormalParameter_formalParameter);
    _formalParameter(node);
    _expectMarker(MarkerTag.NormalFormalParameter_end);
  }

  void _normalFormalParameterNotDefault(
      NormalFormalParameter node, ParameterElementImpl element) {
    var nodeImpl = node as NormalFormalParameterImpl;
    var summaryData = nodeImpl.summaryData as SummaryDataForFormalParameter;
    element.setCodeRange(summaryData.codeOffset, summaryData.codeLength);
  }

  /// 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 NamedExpressionImpl) {
        var nameNode = argument.name.label;
        if (executable is ExecutableElement) {
          var parameters = executable.parameters;
          var name = nameNode.name;
          nameNode.staticElement = parameters.firstWhereOrNull((e) {
            return e.name == name;
          });
        }
      }
    }
  }

  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');
    }
  }
}
