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

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
import 'package:analyzer/src/summary/api_signature.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/public_namespace_computer.dart';
import 'package:analyzer/src/summary/summarize_const_expr.dart';

/// Serialize all the declarations in [compilationUnit] to an unlinked summary.
///
/// [serializeInferrableFields] indicates whether field initializers and closure
/// bodies should be serialized to facilitate type inference.
UnlinkedUnitBuilder serializeAstUnlinked(CompilationUnit compilationUnit,
    {bool serializeInferrableFields: true, bool nnbd: false}) {
  return new _SummarizeAstVisitor(serializeInferrableFields, nnbd)
      .serializeCompilationUnit(compilationUnit);
}

/// Instances of this class keep track of intermediate state during
/// serialization of a single constant [Expression].
class _ConstExprSerializer extends AbstractConstExprSerializer {
  final _SummarizeAstVisitor visitor;

  /// If the expression being serialized can contain closures, map whose
  /// keys are the offsets of local function nodes representing those closures,
  /// and whose values are indices of those local functions relative to their
  /// siblings.
  final Map<int, int> localClosureIndexMap;

  /// The names of local variables and parameters that are in scope.
  /// This is a list so that we can handle nesting by pushing and popping values
  /// at the end of it.
  final List<String> variableNames;

  _ConstExprSerializer(bool forConst, this.visitor, this.localClosureIndexMap,
      List<String> variableNames)
      : variableNames = variableNames ?? [],
        super(forConst);

  @override
  bool isParameterName(String name) {
    return variableNames?.contains(name) ?? false;
  }

  @override
  void popVariableNames(int count) {
    variableNames.length -= count;
  }

  @override
  void pushVariableName(String name) {
    variableNames.add(name);
  }

  @override
  void serialize(Expression expr) {
    int startingVariableCount = variableNames.length;
    super.serialize(expr);
    assert(startingVariableCount == variableNames.length);
  }

  @override
  void serializeAnnotation(Annotation annotation) {
    Identifier name = annotation.name;
    EntityRefBuilder constructor;
    if (name is PrefixedIdentifier && annotation.constructorName == null) {
      constructor = serializeConstructorRef(name.prefix, null, name.identifier);
    } else {
      constructor = serializeConstructorRef(
          annotation.name, null, annotation.constructorName);
    }
    if (annotation.arguments == null) {
      references.add(constructor);
      operations.add(UnlinkedExprOperation.pushReference);
    } else {
      serializeInstanceCreation(constructor, annotation.arguments, false);
    }
  }

  @override
  EntityRefBuilder serializeConstructorRef(Identifier typeName,
      TypeArgumentList typeArguments, SimpleIdentifier name) {
    EntityRefBuilder typeBuilder = serializeTypeName(
        typeName, typeArguments, EntityRefNullabilitySuffix.starOrIrrelevant);
    if (name == null) {
      return typeBuilder;
    } else {
      int nameRef =
          visitor.serializeReference(typeBuilder.reference, name.name);
      return new EntityRefBuilder(
          reference: nameRef, typeArguments: typeBuilder.typeArguments);
    }
  }

  @override
  List<int> serializeFunctionExpression(FunctionExpression functionExpression) {
    int localIndex;
    if (localClosureIndexMap == null) {
      return null;
    } else {
      localIndex = localClosureIndexMap[functionExpression.offset];
      assert(localIndex != null);
      return <int>[0, localIndex];
    }
  }

  @override
  EntityRefBuilder serializeGenericFunctionType(GenericFunctionType node) =>
      visitor.serializeGenericFunctionType(node);

  EntityRefBuilder serializeIdentifier(Identifier identifier) {
    EntityRefBuilder b =
        new EntityRefBuilder(nullabilitySuffix: computeNullabilitySuffix(null));
    if (identifier is SimpleIdentifier) {
      int index = visitor.serializeSimpleReference(identifier.name);
      if (index < 0) {
        b.paramReference = -index;
      } else {
        b.reference = index;
      }
    } else if (identifier is PrefixedIdentifier) {
      int prefix = visitor.serializeSimpleReference(identifier.prefix.name);
      if (prefix < 0) {
        throw new StateError('Invalid type parameter usage: $identifier}');
      }
      b.reference =
          visitor.serializeReference(prefix, identifier.identifier.name);
    } else {
      throw new StateError(
          'Unexpected identifier type: ${identifier.runtimeType}');
    }
    return b;
  }

  @override
  EntityRefBuilder serializeIdentifierSequence(Expression expr) {
    if (expr is Identifier) {
      AstNode parent = expr.parent;
      if (parent is MethodInvocation &&
          parent.methodName == expr &&
          parent.target != null) {
        int targetId = serializeIdentifierSequence(parent.target).reference;
        int nameId = visitor.serializeReference(targetId, expr.name);
        return new EntityRefBuilder(reference: nameId);
      }
      return serializeIdentifier(expr);
    }
    if (expr is PropertyAccess) {
      int targetId = serializeIdentifierSequence(expr.target).reference;
      int nameId = visitor.serializeReference(targetId, expr.propertyName.name);
      return new EntityRefBuilder(reference: nameId);
    } else {
      throw new StateError('Unexpected node type: ${expr.runtimeType}');
    }
  }

  @override
  EntityRefBuilder serializeTypeName(
      Identifier name,
      TypeArgumentList arguments,
      EntityRefNullabilitySuffix nullabilitySuffix) {
    return visitor.serializeTypeName(name, arguments, nullabilitySuffix);
  }

  @override
  EntityRefNullabilitySuffix computeNullabilitySuffix(Token question) =>
      visitor.computeNullabilitySuffix(question);
}

/// A [_Scope] represents a set of name/value pairs defined locally within a
/// limited span of a compilation unit.  (Note that the spec also uses the term
/// "scope" to refer to the set of names defined at top level within a
/// compilation unit, but we do not use [_Scope] for that purpose).
class _Scope {
  /// Names defined in this scope, and their meanings.
  Map<String, _ScopedEntity> _definedNames = <String, _ScopedEntity>{};

  /// Look up the meaning associated with the given [name], and return it.  If
  /// [name] is not defined in this scope, return `null`.
  _ScopedEntity operator [](String name) => _definedNames[name];

  /// Let the given [name] refer to [entity] within this scope.
  void operator []=(String name, _ScopedEntity entity) {
    _definedNames[name] = entity;
  }
}

/// A [_ScopedClassMember] is a [_ScopedEntity] refers to a member of a class.
class _ScopedClassMember extends _ScopedEntity {
  /// The name of the class.
  final String className;

  _ScopedClassMember(this.className);
}

/// Base class for entities that can live inside a scope.
abstract class _ScopedEntity {}

/// A [_ScopedTypeParameter] is a [_ScopedEntity] that refers to a type
/// parameter of a class, typedef, or executable.
class _ScopedTypeParameter extends _ScopedEntity {
  /// Index of the type parameter within this scope.  Since summaries use De
  /// Bruijn indices to refer to type parameters, which count upwards from the
  /// innermost bound name, the last type parameter in the scope has an index of
  /// 1, and each preceding type parameter has the next higher index.
  final int index;

  _ScopedTypeParameter(this.index);
}

/// Visitor used to create a summary from an AST.
class _SummarizeAstVisitor extends RecursiveAstVisitor {
  /// Indicates whether non-const field initializers and closure bodies should
  /// be serialized to facilitate type inference.
  ///
  /// For one-phase summary generation, the only field initializers that need to
  /// be serialized are those involved in constants, since type inference is
  /// performed using the AST representation.
  final bool _serializeInferrableFields;

  final bool _nnbd;

  /// List of objects which should be written to [UnlinkedUnit.classes].
  final List<UnlinkedClassBuilder> classes = <UnlinkedClassBuilder>[];

  /// List of objects which should be written to [UnlinkedUnit.enums].
  final List<UnlinkedEnumBuilder> enums = <UnlinkedEnumBuilder>[];

  /// List of objects which should be written to [UnlinkedUnit.executables],
  /// [UnlinkedClass.executables] or [UnlinkedExecutable.localFunctions].
  List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];

  /// List of objects which should be written to [UnlinkedUnit.exports].
  final List<UnlinkedExportNonPublicBuilder> exports =
      <UnlinkedExportNonPublicBuilder>[];

  /// Whether the current class declaration has a `const` constructor.
  bool enclosingClassHasConstConstructor = false;

  /// List of objects which should be written to [UnlinkedUnit.mixins].
  final List<UnlinkedClassBuilder> mixins = <UnlinkedClassBuilder>[];

  /// List of names of methods, getters, setters, and operators that are
  /// super-invoked in the current mixin declaration.
  Set<String> mixinSuperInvokedNames;

  /// List of objects which should be written to [UnlinkedUnit.parts].
  final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[];

  /// List of objects which should be written to [UnlinkedUnit.typedefs].
  final List<UnlinkedTypedefBuilder> typedefs = <UnlinkedTypedefBuilder>[];

  /// List of objects which should be written to [UnlinkedUnit.variables] or
  /// [UnlinkedClass.fields].
  List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];

  /// The unlinked portion of the "imports table".  This is the list of objects
  /// which should be written to [UnlinkedUnit.imports].
  final List<UnlinkedImportBuilder> unlinkedImports = <UnlinkedImportBuilder>[];

  /// The unlinked portion of the "references table".  This is the list of
  /// objects which should be written to [UnlinkedUnit.references].
  final List<UnlinkedReferenceBuilder> unlinkedReferences =
      <UnlinkedReferenceBuilder>[new UnlinkedReferenceBuilder()];

  /// List of [_Scope]s currently in effect.  This is used to resolve type names
  /// to type parameters within classes, typedefs, and executables, as well as
  /// references to class members.
  final List<_Scope> scopes = <_Scope>[];

  /// True if 'dart:core' has been explicitly imported.
  bool hasCoreBeenImported = false;

  /// Names referenced by this compilation unit.  Structured as a map from
  /// prefix index to (map from name to reference table index), where "prefix
  /// index" means the index into [UnlinkedUnit.references] of the prefix (or
  /// `null` if there is no prefix), and "reference table index" means the index
  /// into [UnlinkedUnit.references] for the name itself.
  final Map<int, Map<String, int>> nameToReference = <int, Map<String, int>>{};

  /// True if the 'dart:core' library is been summarized.
  bool isCoreLibrary = false;

  /// True is a [PartOfDirective] was found, so the unit is a part.
  bool isPartOf = false;

  /// If the library has a library directive, the library name derived from it.
  /// Otherwise `null`.
  String libraryName;

  /// If the library has a library directive, the offset of the library name.
  /// Otherwise `null`.
  int libraryNameOffset;

  /// If the library has a library directive, the length of the library name, as
  /// it appears in the source file.  Otherwise `null`.
  int libraryNameLength;

  /// If the library has a library directive, the documentation comment for it
  /// (if any).  Otherwise `null`.
  UnlinkedDocumentationCommentBuilder libraryDocumentationComment;

  /// If the library has a library directive, the annotations for it (if any).
  /// Otherwise `null`.
  List<UnlinkedExpr> libraryAnnotations = const <UnlinkedExprBuilder>[];

  /// The number of slot ids which have been assigned to this compilation unit.
  int numSlots = 0;

  /// The [Block] that is being visited now, or `null` for non-local contexts.
  Block enclosingBlock = null;

  /// If an expression is being serialized which can contain closures, map whose
  /// keys are the offsets of local function nodes representing those closures,
  /// and whose values are indices of those local functions relative to their
  /// siblings.
  Map<int, int> _localClosureIndexMap;

  /// Indicates whether closure function bodies should be serialized.  This flag
  /// is set while visiting the bodies of initializer expressions that will be
  /// needed by type inference.
  bool _serializeClosureBodyExprs = false;

  /// The set of variable names which are currently in scope.
  List<String> _variableNames = [];

  /// Indicates whether parameters found during visitors might inherit
  /// covariance.
  bool _parametersMayInheritCovariance = false;

  _SummarizeAstVisitor(this._serializeInferrableFields, this._nnbd);

  /// Create a slot id for storing a propagated or inferred type or const cycle
  /// info.
  int assignSlot() => ++numSlots;

  /// Build a [_Scope] object containing the names defined within the body of a
  /// class declaration.
  _Scope buildClassMemberScope(
      String className, NodeList<ClassMember> members) {
    _Scope scope = new _Scope();
    for (ClassMember member in members) {
      if (member is MethodDeclaration) {
        if (member.isSetter || member.isOperator) {
          // We don't have to handle setters or operators because the only
          // things we look up are type names and identifiers.
        } else {
          scope[member.name.name] = new _ScopedClassMember(className);
        }
      } else if (member is FieldDeclaration) {
        for (VariableDeclaration field in member.fields.variables) {
          // A field declaration introduces two names, one with a trailing `=`.
          // We don't have to worry about the one with a trailing `=` because
          // the only things we look up are type names and identifiers.
          scope[field.name.name] = new _ScopedClassMember(className);
        }
      }
    }
    return scope;
  }

  /// Serialize the given list of [annotations].  If there are no annotations,
  /// the empty list is returned.
  List<UnlinkedExprBuilder> serializeAnnotations(
      NodeList<Annotation> annotations) {
    if (annotations == null || annotations.isEmpty) {
      return const <UnlinkedExprBuilder>[];
    }
    return annotations.map((Annotation a) {
      // Closures can't appear inside annotations, so we don't need a
      // localClosureIndexMap.
      Map<int, int> localClosureIndexMap = null;
      _ConstExprSerializer serializer =
          new _ConstExprSerializer(true, this, localClosureIndexMap, null);
      try {
        serializer.serializeAnnotation(a);
      } on StateError {
        return new UnlinkedExprBuilder()..isValidConst = false;
      }
      return serializer.toBuilder(a.atSign.next, a.endToken);
    }).toList();
  }

  /// Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass]
  /// and store the result in [classes].
  void serializeClass(
      AstNode node,
      Token abstractKeyword,
      String name,
      int nameOffset,
      TypeParameterList typeParameters,
      TypeName superclass,
      WithClause withClause,
      ImplementsClause implementsClause,
      NodeList<ClassMember> members,
      bool isMixinApplication,
      Comment documentationComment,
      NodeList<Annotation> annotations) {
    int oldScopesLength = scopes.length;
    enclosingClassHasConstConstructor = node is ClassDeclaration &&
        node.members
            .any((m) => m is ConstructorDeclaration && m.constKeyword != null);
    List<UnlinkedExecutableBuilder> oldExecutables = executables;
    executables = <UnlinkedExecutableBuilder>[];
    List<UnlinkedVariableBuilder> oldVariables = variables;
    variables = <UnlinkedVariableBuilder>[];
    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
    scopes.add(typeParameterScope);
    UnlinkedClassBuilder b = new UnlinkedClassBuilder();
    b.name = name;
    b.nameOffset = nameOffset;
    b.isMixinApplication = isMixinApplication;
    b.typeParameters =
        serializeTypeParameters(typeParameters, typeParameterScope);
    if (_shouldAssignNotSimplyBoundedSlot(typeParameters)) {
      b.notSimplyBoundedSlot = assignSlot();
    }
    if (superclass != null) {
      b.supertype = serializeType(superclass);
    } else {
      b.hasNoSupertype = isCoreLibrary && name == 'Object';
    }
    if (withClause != null) {
      b.mixins = withClause.mixinTypes.map(serializeMixedInType).toList();
    }
    if (implementsClause != null) {
      b.interfaces = implementsClause.interfaces.map(serializeType).toList();
    }
    if (members != null) {
      scopes.add(buildClassMemberScope(name, members));
      for (ClassMember member in members) {
        member.accept(this);
      }
      scopes.removeLast();
    }
    b.executables = executables;
    b.fields = variables;
    b.isAbstract = abstractKeyword != null;
    b.documentationComment = serializeDocumentation(documentationComment);
    b.annotations = serializeAnnotations(annotations);
    b.codeRange = serializeCodeRange(node);
    classes.add(b);
    scopes.removeLast();
    assert(scopes.length == oldScopesLength);
    executables = oldExecutables;
    variables = oldVariables;
  }

  /// Create a [CodeRangeBuilder] for the given [node].
  CodeRangeBuilder serializeCodeRange(AstNode node) {
    return new CodeRangeBuilder(offset: node.offset, length: node.length);
  }

  /// Serialize a [Combinator] into an [UnlinkedCombinator].
  UnlinkedCombinatorBuilder serializeCombinator(Combinator combinator) {
    UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder();
    if (combinator is ShowCombinator) {
      b.shows =
          combinator.shownNames.map((SimpleIdentifier id) => id.name).toList();
      b.offset = combinator.offset;
      b.end = combinator.end;
    } else if (combinator is HideCombinator) {
      b.hides =
          combinator.hiddenNames.map((SimpleIdentifier id) => id.name).toList();
    } else {
      throw new StateError(
          'Unexpected combinator type: ${combinator.runtimeType}');
    }
    return b;
  }

  /// Main entry point for serializing an AST.
  UnlinkedUnitBuilder serializeCompilationUnit(
      CompilationUnit compilationUnit) {
    compilationUnit.directives.accept(this);
    if (!hasCoreBeenImported) {
      unlinkedImports.add(new UnlinkedImportBuilder(isImplicit: true));
    }
    compilationUnit.declarations.accept(this);
    UnlinkedUnitBuilder b = new UnlinkedUnitBuilder();
    b.lineStarts = compilationUnit.lineInfo?.lineStarts;
    b.isPartOf = isPartOf;
    b.libraryName = libraryName;
    b.libraryNameOffset = libraryNameOffset;
    b.libraryNameLength = libraryNameLength;
    b.libraryDocumentationComment = libraryDocumentationComment;
    b.libraryAnnotations = libraryAnnotations;
    b.codeRange = serializeCodeRange(compilationUnit);
    b.classes = classes;
    b.enums = enums;
    b.executables = executables;
    b.exports = exports;
    b.imports = unlinkedImports;
    b.mixins = mixins;
    b.parts = parts;
    b.references = unlinkedReferences;
    b.typedefs = typedefs;
    b.variables = variables;
    b.publicNamespace = computePublicNamespace(compilationUnit);
    _computeApiSignature(b);
    return b;
  }

  /// Serialize the given [expression], creating an [UnlinkedExprBuilder].
  UnlinkedExprBuilder serializeConstExpr(
      bool forConst, Map<int, int> localClosureIndexMap, Expression expression,
      [List<String> variableNames]) {
    _ConstExprSerializer serializer = new _ConstExprSerializer(
        forConst, this, localClosureIndexMap, variableNames);
    serializer.serialize(expression);
    return serializer.toBuilder(expression.beginToken, expression.endToken);
  }

  /// Serialize a [Comment] node into an [UnlinkedDocumentationComment] object.
  UnlinkedDocumentationCommentBuilder serializeDocumentation(
      Comment documentationComment) {
    if (documentationComment == null) {
      return null;
    }
    String text = documentationComment.tokens
        .map((Token t) => t.toString())
        .join('\n')
        .replaceAll('\r\n', '\n');
    return new UnlinkedDocumentationCommentBuilder(text: text);
  }

  /// Return an entity reference builder representing the type 'dynamic'.
  EntityRefBuilder serializeDynamic() {
    EntityRefBuilder builder = new EntityRefBuilder();
    builder.reference = serializeReference(null, 'dynamic');
    return builder;
  }

  /// Serialize an [EnumConstantDeclaration] into an [UnlinkedEnumValue].
  UnlinkedEnumValueBuilder serializeEnumConstantDeclaration(
      EnumConstantDeclaration node) {
    return new UnlinkedEnumValueBuilder(
        annotations: serializeAnnotations(node.metadata),
        documentationComment: serializeDocumentation(node.documentationComment),
        name: node.name.name,
        nameOffset: node.name.offset);
  }

  /// Serialize a [FunctionDeclaration] or [MethodDeclaration] into an
  /// [UnlinkedExecutable].
  ///
  /// If [serializeBodyExpr] is `true`, then the function definition is stored
  /// in [UnlinkedExecutableBuilder.bodyExpr].
  UnlinkedExecutableBuilder serializeExecutable(
      AstNode node,
      String name,
      int nameOffset,
      bool isGetter,
      bool isSetter,
      TypeAnnotation returnType,
      FormalParameterList formalParameters,
      FunctionBody body,
      bool isTopLevel,
      bool isDeclaredStatic,
      Comment documentationComment,
      NodeList<Annotation> annotations,
      TypeParameterList typeParameters,
      bool isExternal,
      bool serializeBodyExpr,
      bool serializeBody) {
    int oldScopesLength = scopes.length;
    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
    scopes.add(typeParameterScope);
    UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
    String nameString = name;
    if (isGetter) {
      b.kind = UnlinkedExecutableKind.getter;
    } else if (isSetter) {
      b.kind = UnlinkedExecutableKind.setter;
      nameString = '$nameString=';
    } else {
      b.kind = UnlinkedExecutableKind.functionOrMethod;
    }
    b.isExternal = isExternal;
    b.isAbstract = !isExternal && body is EmptyFunctionBody;
    b.isAsynchronous = body.isAsynchronous;
    b.isGenerator = body.isGenerator;
    b.name = nameString;
    b.nameOffset = nameOffset;
    b.typeParameters =
        serializeTypeParameters(typeParameters, typeParameterScope);
    if (!isTopLevel) {
      b.isStatic = isDeclaredStatic;
    }
    b.returnType = serializeType(returnType);
    bool isSemanticallyStatic = isTopLevel || isDeclaredStatic;
    if (formalParameters != null) {
      bool oldMayInheritCovariance = _parametersMayInheritCovariance;
      _parametersMayInheritCovariance = !isTopLevel && !isDeclaredStatic;
      b.parameters = formalParameters.parameters
          .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
          .toList();
      _parametersMayInheritCovariance = oldMayInheritCovariance;
      if (!isSemanticallyStatic) {
        for (int i = 0; i < formalParameters.parameters.length; i++) {
          if (!b.parameters[i].isFunctionTyped &&
              b.parameters[i].type == null) {
            b.parameters[i].inferredTypeSlot = assignSlot();
          }
        }
      }
    }
    b.documentationComment = serializeDocumentation(documentationComment);
    b.annotations = serializeAnnotations(annotations);
    b.codeRange = serializeCodeRange(node);
    if (returnType == null && !isSemanticallyStatic) {
      b.inferredReturnTypeSlot = assignSlot();
    }
    b.visibleOffset = enclosingBlock?.offset;
    b.visibleLength = enclosingBlock?.length;
    int oldVariableNamesLength = _variableNames.length;
    if (formalParameters != null && formalParameters.parameters.isNotEmpty) {
      _variableNames.addAll(formalParameters.parameters
          .map((FormalParameter p) => p.identifier.name));
    }
    serializeFunctionBody(
        b, null, body, serializeBodyExpr, serializeBody, false);

    if (mixinSuperInvokedNames != null) {
      body?.accept(new MixinSuperInvokedNamesCollector(mixinSuperInvokedNames));
    }

    _variableNames.length = oldVariableNamesLength;
    scopes.removeLast();
    assert(scopes.length == oldScopesLength);
    return b;
  }

  /// Record local functions and variables into the given executable. The given
  /// [body] is usually an actual [FunctionBody], but may be an [Expression]
  /// when we process a synthetic variable initializer function.
  ///
  /// If [initializers] is non-`null`, closures occurring inside the
  /// initializers are serialized first.
  ///
  /// If [serializeBodyExpr] is `true`, then the function definition is stored
  /// in [UnlinkedExecutableBuilder.bodyExpr], and closures occurring inside
  /// [initializers] and [body] have their function bodies serialized as well.
  ///
  /// The return value is a map whose keys are the offsets of local function
  /// nodes representing closures inside [initializers] and [body], and whose
  /// values are the indices of those local functions relative to their
  /// siblings.
  Map<int, int> serializeFunctionBody(
      UnlinkedExecutableBuilder b,
      List<ConstructorInitializer> initializers,
      AstNode body,
      bool serializeBodyExpr,
      bool serializeBody,
      bool forConst) {
    if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
      for (UnlinkedParamBuilder parameter in b.parameters) {
        if (!parameter.isInitializingFormal) {
          parameter.visibleOffset = body.offset;
          parameter.visibleLength = body.length;
        }
      }
    }
    List<UnlinkedExecutableBuilder> oldExecutables = executables;
    Map<int, int> oldLocalClosureIndexMap = _localClosureIndexMap;
    bool oldSerializeClosureBodyExprs = _serializeClosureBodyExprs;
    executables = <UnlinkedExecutableBuilder>[];
    _localClosureIndexMap = <int, int>{};
    _serializeClosureBodyExprs =
        serializeBodyExpr && _serializeInferrableFields;
    if (initializers != null) {
      for (ConstructorInitializer initializer in initializers) {
        initializer.accept(this);
      }
    }
    if (serializeBody) {
      body.accept(this);
    }
    if (serializeBodyExpr) {
      if (body is Expression) {
        b.bodyExpr = serializeConstExpr(
            forConst, _localClosureIndexMap, body, _variableNames);
      } else if (body is ExpressionFunctionBody) {
        b.bodyExpr = serializeConstExpr(
            forConst, _localClosureIndexMap, body.expression, _variableNames);
      } else {
        // TODO(paulberry): serialize other types of function bodies.
      }
    }
    b.localFunctions = executables;
    Map<int, int> localClosureIndexMap = _localClosureIndexMap;
    executables = oldExecutables;
    _localClosureIndexMap = oldLocalClosureIndexMap;
    _serializeClosureBodyExprs = oldSerializeClosureBodyExprs;
    return localClosureIndexMap;
  }

  /// Serialize the return type and parameters of a function-typed formal
  /// parameter and store them in [b].
  void serializeFunctionTypedParameterDetails(UnlinkedParamBuilder b,
      TypeAnnotation returnType, FormalParameterList parameters) {
    EntityRefBuilder serializedReturnType = serializeType(returnType);
    if (serializedReturnType != null) {
      b.type = serializedReturnType;
    }
    bool oldMayInheritCovariance = _parametersMayInheritCovariance;
    _parametersMayInheritCovariance = false;
    b.parameters = parameters.parameters
        .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
        .toList();
    _parametersMayInheritCovariance = oldMayInheritCovariance;
  }

  /// Serialize a generic function type.
  EntityRefBuilder serializeGenericFunctionType(GenericFunctionType node) {
    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
    scopes.add(typeParameterScope);
    EntityRefBuilder b = new EntityRefBuilder(
        nullabilitySuffix: computeNullabilitySuffix(node?.question));
    b.entityKind = EntityRefKind.genericFunctionType;
    b.typeParameters =
        serializeTypeParameters(node.typeParameters, typeParameterScope);
    b.syntheticReturnType = node.returnType == null
        ? serializeDynamic()
        : serializeType(node.returnType);
    b.syntheticParams = node.parameters.parameters
        .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
        .toList();
    scopes.removeLast();
    return b;
  }

  /// If the given [expression] is not `null`, serialize it as an
  /// [UnlinkedExecutableBuilder], otherwise return `null`.
  ///
  /// If [serializeBodyExpr] is `true`, then the initializer expression is
  /// stored in [UnlinkedExecutableBuilder.bodyExpr].
  UnlinkedExecutableBuilder serializeInitializerFunction(
      Expression expression, bool serializeBodyExpr, bool forConst) {
    if (expression == null) {
      return null;
    }
    UnlinkedExecutableBuilder initializer =
        new UnlinkedExecutableBuilder(nameOffset: expression.offset);
    serializeFunctionBody(
        initializer, null, expression, serializeBodyExpr, true, forConst);
    initializer.inferredReturnTypeSlot = assignSlot();
    return initializer;
  }

  /// Serialize a type name that appears in a "with" clause to an [EntityRef].
  EntityRefBuilder serializeMixedInType(TypeAnnotation node) {
    var builder = serializeType(node);
    if (builder != null && builder.typeArguments.isEmpty) {
      // Type arguments may get inferred so we need to assign a slot to hold the
      // complete inferred mixed in type.
      builder.refinedSlot = assignSlot();
    }
    return builder;
  }

  /// Serialize a [MixinDeclaration] into an [UnlinkedClass]
  /// and store the result in [mixins].
  void serializeMixin(
      AstNode node,
      String name,
      int nameOffset,
      TypeParameterList typeParameters,
      OnClause onClause,
      ImplementsClause implementsClause,
      NodeList<ClassMember> members,
      Comment documentationComment,
      NodeList<Annotation> annotations) {
    List<UnlinkedExecutableBuilder> oldExecutables = executables;
    executables = <UnlinkedExecutableBuilder>[];

    mixinSuperInvokedNames = new Set<String>();

    List<UnlinkedVariableBuilder> oldVariables = variables;
    variables = <UnlinkedVariableBuilder>[];

    int oldScopesLength = scopes.length;
    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
    scopes.add(typeParameterScope);

    UnlinkedClassBuilder b = new UnlinkedClassBuilder();
    b.name = name;
    b.nameOffset = nameOffset;
    b.typeParameters =
        serializeTypeParameters(typeParameters, typeParameterScope);
    if (onClause != null) {
      b.superclassConstraints =
          onClause.superclassConstraints.map(serializeType).toList();
    }
    if (implementsClause != null) {
      b.interfaces = implementsClause.interfaces.map(serializeType).toList();
    }
    if (members != null) {
      scopes.add(buildClassMemberScope(name, members));
      for (ClassMember member in members) {
        member.accept(this);
      }
      scopes.removeLast();
    }
    b.executables = executables;
    b.fields = variables;
    b.superInvokedNames = mixinSuperInvokedNames.toList();
    b.documentationComment = serializeDocumentation(documentationComment);
    b.annotations = serializeAnnotations(annotations);
    b.codeRange = serializeCodeRange(node);
    mixins.add(b);

    scopes.removeLast();
    assert(scopes.length == oldScopesLength);

    executables = oldExecutables;
    mixinSuperInvokedNames = null;
    variables = oldVariables;
  }

  /// Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or
  /// [SimpleFormalParameter] into an [UnlinkedParam].
  UnlinkedParamBuilder serializeParameter(NormalFormalParameter node) {
    UnlinkedParamBuilder b = new UnlinkedParamBuilder();
    b.name = node.identifier?.name;
    b.nameOffset = node.identifier?.offset;
    b.annotations = serializeAnnotations(node.metadata);
    b.codeRange = serializeCodeRange(node);
    b.isExplicitlyCovariant = node.covariantKeyword != null;
    b.isFinal = node.isFinal;
    if (_parametersMayInheritCovariance) {
      b.inheritsCovariantSlot = assignSlot();
    }
    if (node.isRequired) {
      b.kind = UnlinkedParamKind.required;
    } else if (node.isOptionalPositional) {
      b.kind = UnlinkedParamKind.positional;
    } else if (node.isNamed) {
      b.kind = UnlinkedParamKind.named;
    } else {
      // ignore: deprecated_member_use_from_same_package
      throw new StateError('Unexpected parameter kind: ${node.kind}');
    }
    return b;
  }

  /// Serialize a reference to a top level name declared elsewhere, by adding an
  /// entry to the references table if necessary.  If [prefixIndex] is not null,
  /// the reference is associated with the prefix having the given index in the
  /// references table.
  int serializeReference(int prefixIndex, String name) => nameToReference
          .putIfAbsent(prefixIndex, () => <String, int>{})
          .putIfAbsent(name, () {
        int index = unlinkedReferences.length;
        unlinkedReferences.add(new UnlinkedReferenceBuilder(
            prefixReference: prefixIndex, name: name));
        return index;
      });

  /// Serialize a reference to a name declared either at top level or in a
  /// nested scope.
  ///
  /// References to type parameters are returned as negative numbers.
  int serializeSimpleReference(String name) {
    int indexOffset = 0;
    for (int i = scopes.length - 1; i >= 0; i--) {
      _Scope scope = scopes[i];
      _ScopedEntity entity = scope[name];
      if (entity != null) {
        if (entity is _ScopedClassMember) {
          return serializeReference(
              serializeReference(null, entity.className), name);
        } else if (entity is _ScopedTypeParameter) {
          int paramReference = indexOffset + entity.index;
          return -paramReference;
        }
      }
      if (scope is _TypeParameterScope) {
        indexOffset += scope.length;
      }
    }
    return serializeReference(null, name);
  }

  /// Serialize a type name (which might be defined in a nested scope, at top
  /// level within this library, or at top level within an imported library) to
  /// a [EntityRef].  Note that this method does the right thing if the
  /// name doesn't refer to an entity other than a type (e.g. a class member).
  EntityRefBuilder serializeType(TypeAnnotation node) {
    var nullabilitySuffix = computeNullabilitySuffix(node?.question);
    if (node is TypeName) {
      return serializeTypeName(
          node?.name, node?.typeArguments, nullabilitySuffix);
    } else if (node is GenericFunctionType) {
      return serializeGenericFunctionType(node);
    } else if (node != null) {
      throw new ArgumentError('Cannot serialize a ${node.runtimeType}');
    }
    return null;
  }

  EntityRefNullabilitySuffix computeNullabilitySuffix(Token question) {
    if (!_nnbd) return EntityRefNullabilitySuffix.starOrIrrelevant;
    if (question != null) return EntityRefNullabilitySuffix.question;
    return EntityRefNullabilitySuffix.none;
  }

  /// Serialize a type name (which might be defined in a nested scope, at top
  /// level within this library, or at top level within an imported library) to
  /// a [EntityRef].  Note that this method does the right thing if the
  /// name doesn't refer to an entity other than a type (e.g. a class member).
  EntityRefBuilder serializeTypeName(
      Identifier identifier,
      TypeArgumentList typeArguments,
      EntityRefNullabilitySuffix nullabilitySuffix) {
    if (identifier == null) {
      return null;
    } else {
      EntityRefBuilder b =
          new EntityRefBuilder(nullabilitySuffix: nullabilitySuffix);
      if (identifier is SimpleIdentifier) {
        String name = identifier.name;
        int indexOffset = 0;
        for (int i = scopes.length - 1; i >= 0; i--) {
          _Scope scope = scopes[i];
          _ScopedEntity entity = scope[name];
          if (entity != null) {
            if (entity is _ScopedTypeParameter) {
              b.paramReference = indexOffset + entity.index;
              return b;
            } else {
              // None of the other things that can be declared in local scopes
              // are types, so this is an error and should be treated as a
              // reference to `dynamic`.
              b.reference = serializeReference(null, 'dynamic');
              return b;
            }
          }
          if (scope is _TypeParameterScope) {
            indexOffset += scope.length;
          }
        }
        b.reference = serializeReference(null, name);
      } else if (identifier is PrefixedIdentifier) {
        int prefixIndex = serializeSimpleReference(identifier.prefix.name);
        if (prefixIndex < 0) {
          // Type parameters are not expected here, so this is an error and the
          // type should be treated as a reference to `dynamic`.
          b.reference = serializeReference(null, 'dynamic');
          return b;
        } else {
          b.reference =
              serializeReference(prefixIndex, identifier.identifier.name);
        }
      } else {
        throw new StateError(
            'Unexpected identifier type: ${identifier.runtimeType}');
      }
      if (typeArguments != null) {
        b.typeArguments = typeArguments.arguments.map(serializeType).toList();
      }
      return b;
    }
  }

  /// Serialize the given [typeParameters] into a list of [UnlinkedTypeParam]s,
  /// and also store them in [typeParameterScope].
  List<UnlinkedTypeParamBuilder> serializeTypeParameters(
      TypeParameterList typeParameters,
      _TypeParameterScope typeParameterScope) {
    if (typeParameters != null) {
      for (int i = 0; i < typeParameters.typeParameters.length; i++) {
        TypeParameter typeParameter = typeParameters.typeParameters[i];
        typeParameterScope[typeParameter.name.name] =
            new _ScopedTypeParameter(typeParameters.typeParameters.length - i);
      }
      return typeParameters.typeParameters.map(visitTypeParameter).toList();
    }
    return const <UnlinkedTypeParamBuilder>[];
  }

  /// Serialize the given [variables] into [UnlinkedVariable]s, and store them
  /// in [this.variables].
  void serializeVariables(
      VariableDeclarationList variables,
      bool isDeclaredStatic,
      Comment documentationComment,
      NodeList<Annotation> annotations,
      bool isField) {
    bool isCovariant = isField
        ? (variables.parent as FieldDeclaration).covariantKeyword != null
        : false;
    for (int i = 0; i < variables.variables.length; i++) {
      VariableDeclaration variable = variables.variables[i];
      UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
      b.isConst = variables.isConst;
      b.isCovariant = isCovariant;
      b.isFinal = variables.isFinal;
      b.isStatic = isDeclaredStatic;
      b.name = variable.name.name;
      b.nameOffset = variable.name.offset;
      b.type = serializeType(variables.type);
      b.documentationComment = serializeDocumentation(documentationComment);
      b.annotations = serializeAnnotations(annotations);

      {
        int offset = (i == 0 ? variables.parent : variable).offset;
        int length = variable.end - offset;
        b.codeRange = new CodeRangeBuilder(offset: offset, length: length);
      }

      bool serializeBodyExpr = variable.isConst ||
          _serializeInferrableFields && variables.type == null ||
          isField &&
              !isDeclaredStatic &&
              variables.isFinal &&
              enclosingClassHasConstConstructor;
      b.initializer = serializeInitializerFunction(
          variable.initializer, serializeBodyExpr, b.isConst);
      if (isField && !isDeclaredStatic && !variables.isFinal) {
        b.inheritsCovariantSlot = assignSlot();
      }
      if (variable.initializer != null &&
          (variables.isFinal || variables.isConst)) {
        b.propagatedTypeSlot = assignSlot();
      }
      bool isSemanticallyStatic = !isField || isDeclaredStatic;
      if (variables.type == null &&
          (variable.initializer != null || !isSemanticallyStatic)) {
        b.inferredTypeSlot = assignSlot();
      }
      this.variables.add(b);
    }
  }

  @override
  void visitBlock(Block node) {
    Block oldBlock = enclosingBlock;
    enclosingBlock = node;
    super.visitBlock(node);
    enclosingBlock = oldBlock;
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    TypeName superclass =
        node.extendsClause == null ? null : node.extendsClause.superclass;
    serializeClass(
        node,
        node.abstractKeyword,
        node.name.name,
        node.name.offset,
        node.typeParameters,
        superclass,
        node.withClause,
        node.implementsClause,
        node.members,
        false,
        node.documentationComment,
        node.metadata);
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    serializeClass(
        node,
        node.abstractKeyword,
        node.name.name,
        node.name.offset,
        node.typeParameters,
        node.superclass,
        node.withClause,
        node.implementsClause,
        null,
        true,
        node.documentationComment,
        node.metadata);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
    if (node.name != null) {
      b.name = node.name.name;
      b.nameOffset = node.name.offset;
      b.periodOffset = node.period.offset;
      b.nameEnd = node.name.end;
    } else {
      b.nameOffset = node.returnType.offset;
    }
    b.parameters = node.parameters.parameters
        .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
        .toList();
    b.kind = UnlinkedExecutableKind.constructor;
    if (node.factoryKeyword != null) {
      b.isFactory = true;
      if (node.redirectedConstructor != null) {
        b.isRedirectedConstructor = true;
        TypeName typeName = node.redirectedConstructor.type;
        // Closures can't appear inside factory constructor redirections, so we
        // don't need a localClosureIndexMap.
        Map<int, int> localClosureIndexMap = null;
        b.redirectedConstructor =
            new _ConstExprSerializer(true, this, localClosureIndexMap, null)
                .serializeConstructorRef(typeName.name, typeName.typeArguments,
                    node.redirectedConstructor.name);
      }
    } else {
      for (ConstructorInitializer initializer in node.initializers) {
        if (initializer is RedirectingConstructorInvocation) {
          b.isRedirectedConstructor = true;
          b.redirectedConstructorName = initializer.constructorName?.name;
        }
      }
    }
    if (node.constKeyword != null) {
      b.isConst = true;
      b.constCycleSlot = assignSlot();
    }
    b.isExternal =
        node.externalKeyword != null || node.body is NativeFunctionBody;
    b.documentationComment = serializeDocumentation(node.documentationComment);
    b.annotations = serializeAnnotations(node.metadata);
    b.codeRange = serializeCodeRange(node);
    Map<int, int> localClosureIndexMap = serializeFunctionBody(b,
        node.initializers, node.body, node.constKeyword != null, false, false);
    if (node.constKeyword != null) {
      List<String> constructorParameterNames =
          node.parameters.parameters.map((p) => p.identifier.name).toList();
      b.constantInitializers = node.initializers
          .map((ConstructorInitializer initializer) =>
              serializeConstructorInitializer(initializer, (Expression expr) {
                return serializeConstExpr(true, localClosureIndexMap, expr,
                    constructorParameterNames);
              }))
          .toList();
    }
    executables.add(b);
  }

  @override
  UnlinkedParamBuilder visitDefaultFormalParameter(
      DefaultFormalParameter node) {
    UnlinkedParamBuilder b =
        node.parameter.accept(this) as UnlinkedParamBuilder;
    b.initializer = serializeInitializerFunction(node.defaultValue, true, true);
    if (node.defaultValue != null) {
      b.defaultValueCode = node.defaultValue.toSource();
    }
    b.codeRange = serializeCodeRange(node);
    return b;
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
    b.name = node.name.name;
    b.nameOffset = node.name.offset;
    b.values = node.constants.map(serializeEnumConstantDeclaration).toList();
    b.documentationComment = serializeDocumentation(node.documentationComment);
    b.annotations = serializeAnnotations(node.metadata);
    b.codeRange = serializeCodeRange(node);
    enums.add(b);
  }

  @override
  void visitExportDirective(ExportDirective node) {
    UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder(
        uriOffset: node.uri.offset, uriEnd: node.uri.end, offset: node.offset);
    b.annotations = serializeAnnotations(node.metadata);
    exports.add(b);
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    serializeVariables(node.fields, node.staticKeyword != null,
        node.documentationComment, node.metadata, true);
  }

  @override
  UnlinkedParamBuilder visitFieldFormalParameter(FieldFormalParameter node) {
    UnlinkedParamBuilder b = serializeParameter(node);
    b.isInitializingFormal = true;
    if (node.type != null || node.parameters != null) {
      b.isFunctionTyped = node.parameters != null;
      if (node.parameters != null) {
        serializeFunctionTypedParameterDetails(b, node.type, node.parameters);
      } else {
        b.type = serializeType(node.type);
      }
    }
    return b;
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    executables.add(serializeExecutable(
        node,
        node.name.name,
        node.name.offset,
        node.isGetter,
        node.isSetter,
        node.returnType,
        node.functionExpression.parameters,
        node.functionExpression.body,
        true,
        false,
        node.documentationComment,
        node.metadata,
        node.functionExpression.typeParameters,
        node.externalKeyword != null ||
            node.functionExpression.body is NativeFunctionBody,
        false,
        node.parent is FunctionDeclarationStatement));
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    if (node.parent is! FunctionDeclaration) {
      if (_localClosureIndexMap != null) {
        _localClosureIndexMap[node.offset] = executables.length;
      }
      executables.add(serializeExecutable(
          node,
          null,
          node.offset,
          false,
          false,
          null,
          node.parameters,
          node.body,
          false,
          false,
          null,
          null,
          node.typeParameters,
          false,
          _serializeClosureBodyExprs,
          true));
    }
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    int oldScopesLength = scopes.length;
    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
    scopes.add(typeParameterScope);
    UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
    b.name = node.name.name;
    b.nameOffset = node.name.offset;
    b.typeParameters =
        serializeTypeParameters(node.typeParameters, typeParameterScope);
    b.notSimplyBoundedSlot = assignSlot();
    EntityRefBuilder serializedReturnType = serializeType(node.returnType);
    if (serializedReturnType != null) {
      b.returnType = serializedReturnType;
    }
    b.parameters = node.parameters.parameters
        .map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
        .toList();
    b.documentationComment = serializeDocumentation(node.documentationComment);
    b.annotations = serializeAnnotations(node.metadata);
    b.codeRange = serializeCodeRange(node);
    typedefs.add(b);

    scopes.removeLast();
    assert(scopes.length == oldScopesLength);
  }

  @override
  UnlinkedParamBuilder visitFunctionTypedFormalParameter(
      FunctionTypedFormalParameter node) {
    UnlinkedParamBuilder b = serializeParameter(node);
    b.isFunctionTyped = true;
    serializeFunctionTypedParameterDetails(b, node.returnType, node.parameters);
    return b;
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    int oldScopesLength = scopes.length;
    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
    scopes.add(typeParameterScope);
    UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
    b.style = TypedefStyle.genericFunctionType;
    b.name = node.name.name;
    b.nameOffset = node.name.offset;
    b.typeParameters =
        serializeTypeParameters(node.typeParameters, typeParameterScope);
    b.notSimplyBoundedSlot = assignSlot();
    GenericFunctionType functionType = node.functionType;
    EntityRefBuilder serializedType = functionType == null
        ? null
        : serializeGenericFunctionType(functionType);
    if (serializedType != null) {
      b.returnType = serializedType;
    }
    b.documentationComment = serializeDocumentation(node.documentationComment);
    b.annotations = serializeAnnotations(node.metadata);
    b.codeRange = serializeCodeRange(node);
    typedefs.add(b);
    scopes.removeLast();
    assert(scopes.length == oldScopesLength);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    UnlinkedImportBuilder b = new UnlinkedImportBuilder();
    b.annotations = serializeAnnotations(node.metadata);
    if (node.uri.stringValue == 'dart:core') {
      hasCoreBeenImported = true;
    }
    b.offset = node.offset;
    b.combinators = node.combinators.map(serializeCombinator).toList();
    b.configurations = node.configurations.map(serializeConfiguration).toList();
    if (node.prefix != null) {
      b.prefixReference = serializeReference(null, node.prefix.name);
      b.prefixOffset = node.prefix.offset;
    }
    b.isDeferred = node.deferredKeyword != null;
    b.uri = node.uri.stringValue;
    b.uriOffset = node.uri.offset;
    b.uriEnd = node.uri.end;
    unlinkedImports.add(b);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    libraryName =
        node.name.components.map((SimpleIdentifier id) => id.name).join('.');
    libraryNameOffset = node.name.offset;
    libraryNameLength = node.name.length;
    isCoreLibrary = libraryName == 'dart.core';
    libraryDocumentationComment =
        serializeDocumentation(node.documentationComment);
    libraryAnnotations = serializeAnnotations(node.metadata);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    executables.add(serializeExecutable(
        node,
        node.name.name,
        node.name.offset,
        node.isGetter,
        node.isSetter,
        node.returnType,
        node.parameters,
        node.body,
        false,
        node.isStatic,
        node.documentationComment,
        node.metadata,
        node.typeParameters,
        node.externalKeyword != null || node.body is NativeFunctionBody,
        false,
        false));
  }

  @override
  visitMixinDeclaration(MixinDeclaration node) {
    serializeMixin(
        node,
        node.name.name,
        node.name.offset,
        node.typeParameters,
        node.onClause,
        node.implementsClause,
        node.members,
        node.documentationComment,
        node.metadata);
  }

  @override
  void visitPartDirective(PartDirective node) {
    parts.add(new UnlinkedPartBuilder(
        uriOffset: node.uri.offset,
        uriEnd: node.uri.end,
        annotations: serializeAnnotations(node.metadata)));
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    isCoreLibrary = node.libraryName?.name == 'dart.core' ||
        node.uri?.stringValue == 'core.dart';
    isPartOf = true;
  }

  @override
  UnlinkedParamBuilder visitSimpleFormalParameter(SimpleFormalParameter node) {
    UnlinkedParamBuilder b = serializeParameter(node);
    b.type = serializeType(node.type);
    return b;
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    serializeVariables(
        node.variables, false, node.documentationComment, node.metadata, false);
  }

  @override
  UnlinkedTypeParamBuilder visitTypeParameter(TypeParameter node) {
    UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder();
    b.name = node.name.name;
    b.nameOffset = node.name.offset;
    if (node.bound != null) {
      b.bound = serializeType(node.bound);
    }
    b.annotations = serializeAnnotations(node.metadata);
    b.codeRange = serializeCodeRange(node);
    return b;
  }

  @override
  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
    // TODO(scheglov) Remove when we stop serializing local functions.
  }

  /// Determines whether a class declaration with the given [typeParameters]
  /// needs to be assigned a slot to indicate whether it is simply bounded.
  bool _shouldAssignNotSimplyBoundedSlot(TypeParameterList typeParameters) {
    if (typeParameters == null) return false;
    for (var typeParameter in typeParameters.typeParameters) {
      if (typeParameter.bound != null) return true;
    }
    return false;
  }

  /// Compute the API signature of the unit and record it.
  static void _computeApiSignature(UnlinkedUnitBuilder b) {
    ApiSignature apiSignature = new ApiSignature();
    b.collectApiSignature(apiSignature);
    b.apiSignature = apiSignature.toByteList();
  }
}

/// A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s.
class _TypeParameterScope extends _Scope {
  /// Get the number of [_ScopedTypeParameter]s defined in this
  /// [_TypeParameterScope].
  int get length => _definedNames.length;
}
