// 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/analysis/features.dart';
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}) {
  return new _SummarizeAstVisitor(serializeInferrableFields,
          compilationUnit.featureSet.isEnabled(Feature.non_nullable))
      .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
  EntityRefNullabilitySuffix computeNullabilitySuffix(Token question) =>
      visitor.computeNullabilitySuffix(question);

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

/// 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.extensions].
  final List<UnlinkedExtensionBuilder> extensions =
      <UnlinkedExtensionBuilder>[];

  /// 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 if the 'dart:core' library defining unit is been summarized.
  bool isCoreLibraryDefiningUnit = 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;
  }

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

  /// 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(
        isNNBD: compilationUnit.featureSet.isEnabled(Feature.non_nullable));
    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.extensions = extensions;
    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);
    if (isCoreLibraryDefiningUnit) {
      b.publicNamespace.names.add(
        UnlinkedPublicNameBuilder(
          name: 'Never',
          kind: ReferenceKind.classOrEnum,
        ),
      );
    }

    _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.isRequiredPositional) {
      b.kind = UnlinkedParamKind.requiredPositional;
    } else if (node.isRequiredNamed) {
      b.kind = UnlinkedParamKind.requiredNamed;
    } else if (node.isOptionalPositional) {
      b.kind = UnlinkedParamKind.optionalPositional;
    } else if (node.isOptionalNamed) {
      b.kind = UnlinkedParamKind.optionalNamed;
    } 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;
  }

  /// 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.isLate = variable.isLate;
      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
  visitExtensionDeclaration(ExtensionDeclaration node) {
    int oldScopesLength = scopes.length;
    enclosingClassHasConstConstructor = false;
    List<UnlinkedExecutableBuilder> oldExecutables = executables;
    executables = <UnlinkedExecutableBuilder>[];
    List<UnlinkedVariableBuilder> oldVariables = variables;
    variables = <UnlinkedVariableBuilder>[];
    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
    scopes.add(typeParameterScope);

    UnlinkedExtensionBuilder b = UnlinkedExtensionBuilder();
    b.name = node.name?.name;
    b.nameOffset = node.name?.offset ?? 0;
    b.typeParameters =
        serializeTypeParameters(node.typeParameters, typeParameterScope);
    b.extendedType = serializeType(node.extendedType);
    if (node.members != null) {
      scopes.add(buildClassMemberScope(node.name?.name, node.members));
      for (ClassMember member in node.members) {
        member.accept(this);
      }
      scopes.removeLast();
    }
    b.executables = executables;
    b.fields = variables;
    b.documentationComment = serializeDocumentation(node.documentationComment);
    b.annotations = serializeAnnotations(node.metadata);
    b.codeRange = serializeCodeRange(node);
    extensions.add(b);

    scopes.removeLast();
    assert(scopes.length == oldScopesLength);
    executables = oldExecutables;
    variables = oldVariables;
  }

  @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';
    isCoreLibraryDefiningUnit = isCoreLibrary;
    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;
}
