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

import 'dart:typed_data';

import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/field_name_non_promotability_info.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/name_union.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/ast_binary_tag.dart';
import 'package:analyzer/src/summary2/data_reader.dart';
import 'package:analyzer/src/summary2/element_flags.dart';
import 'package:analyzer/src/summary2/export.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro_application_error.dart';
import 'package:analyzer/src/summary2/macro_type_location.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/inference_error.dart';
import 'package:analyzer/src/utilities/extensions/collection.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:analyzer/src/utilities/uri_cache.dart';
import 'package:macros/macros.dart' as macro;
import 'package:pub_semver/pub_semver.dart';

class BundleReader {
  final SummaryDataReader _reader;
  final Map<Uri, Uint8List> _unitsInformativeBytes;
  final InfoDeclarationStore _infoDeclarationStore;

  final Map<Uri, LibraryReader> libraryMap = {};

  BundleReader({
    required LinkedElementFactory elementFactory,
    required Uint8List resolutionBytes,
    Map<Uri, Uint8List> unitsInformativeBytes = const {},
    required InfoDeclarationStore infoDeclarationStore,
  })  : _reader = SummaryDataReader(resolutionBytes),
        _unitsInformativeBytes = unitsInformativeBytes,
        _infoDeclarationStore = infoDeclarationStore {
    _reader.offset = _reader.bytes.length - 4 * 4;
    var baseResolutionOffset = _reader.readUInt32();
    var librariesOffset = _reader.readUInt32();
    var referencesOffset = _reader.readUInt32();
    var stringsOffset = _reader.readUInt32();
    _reader.createStringTable(stringsOffset);

    var referenceReader = _ReferenceReader(
      elementFactory,
      _reader,
      referencesOffset,
    );

    _reader.offset = librariesOffset;
    var libraryHeaderList = _reader.readTypedList(() {
      return _LibraryHeader(
        uri: uriCache.parse(_reader.readStringReference()),
        offset: _reader.readUInt30(),
        classMembersLengths: _reader.readUInt30List(),
        macroGeneratedCode: _reader.readOptionalObject((reader) {
          return _reader.readStringUtf8();
        }),
      );
    });

    for (var libraryHeader in libraryHeaderList) {
      var uri = libraryHeader.uri;
      var reference = elementFactory.rootReference.getChild('$uri');
      libraryMap[uri] = LibraryReader._(
        elementFactory: elementFactory,
        reader: _reader,
        uri: uri,
        unitsInformativeBytes: _unitsInformativeBytes,
        baseResolutionOffset: baseResolutionOffset,
        referenceReader: referenceReader,
        reference: reference,
        offset: libraryHeader.offset,
        classMembersLengths: libraryHeader.classMembersLengths,
        infoDeclarationStore: _infoDeclarationStore,
        macroGeneratedCode: libraryHeader.macroGeneratedCode,
      );
    }
  }
}

class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;
  void Function()? _readMembers;
  void Function()? applyInformativeDataToMembers;

  ClassElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void readMembers(InstanceElementImpl element) {
    if (element is! ClassElementImpl) {
      return;
    }

    // We might read class members before other properties.
    element.linkedData?.read(element);
    element.linkedData = null;

    if (element.isMixinApplication) {
      element.constructors;
    } else {
      _readMembers?.call();
      _readMembers = null;

      applyInformativeDataToMembers?.call();
      applyInformativeDataToMembers = null;
    }
  }

  @override
  void _clearLinkedDataOnRead(ClassElementImpl element) {
    // Don't clear yet, we use it to read members on demand.
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    _readTypeParameters(reader, element.typeParameters);
    element.supertype = reader._readOptionalInterfaceType();
    element.mixins = reader._readInterfaceTypeList();
    element.interfaces = reader._readInterfaceTypeList();
    element.augmentationTarget = reader.readElement() as ClassElementImpl?;
    element.augmentation = reader.readElement() as ClassElementImpl?;

    if (element.augmentationTarget == null) {
      if (reader.readBool()) {
        var augmented = AugmentedClassElementImpl(element);
        element.augmentedInternal = augmented;
        augmented.mixins = reader._readInterfaceTypeList();
        augmented.interfaces = reader._readInterfaceTypeList();
        augmented.fields = reader.readElementList();
        augmented.constructors = reader.readElementList();
        augmented.accessors = reader.readElementList();
        augmented.methods = reader.readElementList();
      }
    }

    applyConstantOffsets?.perform();
  }
}

class CompilationUnitElementLinkedData
    extends ElementLinkedData<CompilationUnitElementImpl> {
  CompilationUnitElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(CompilationUnitElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {}
}

class ConstructorElementLinkedData
    extends ElementLinkedData<ConstructorElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  ConstructorElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(ConstructorElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    _addEnclosingElementTypeParameters(reader, element);

    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    reader._addFormalParameters(element.parameters);
    _readFormalParameters(reader, element.parameters);
    element.superConstructor = reader.readElement() as ConstructorElement?;
    element.redirectedConstructor = reader.readElement() as ConstructorElement?;
    element.constantInitializers = reader._readNodeList();
    element.augmentation = reader.readElement() as ConstructorElementImpl?;
    element.augmentationTarget =
        reader.readElement() as ConstructorElementImpl?;
    applyConstantOffsets?.perform();
  }
}

/// Lazy reader of resolution information.
abstract class ElementLinkedData<E extends ElementImpl> {
  final Reference reference;
  final LibraryReader _libraryReader;
  final CompilationUnitElementImpl unitElement;

  /// When this object is created, this offset is the offset of the resolution
  /// information in the [_libraryReader]. After reading is done, this offset
  /// is set to `-1`.
  int _offset;

  ElementLinkedData(
      this.reference, LibraryReader libraryReader, this.unitElement, int offset)
      : _libraryReader = libraryReader,
        _offset = offset;

  void read(ElementImpl element) {
    _clearLinkedDataOnRead(element as E);
    if (_offset == -1) {
      return;
    }

    var dataReader = _libraryReader._reader.fork(_offset);
    _offset = -1;

    var reader = ResolutionReader(
      _libraryReader._elementFactory,
      _libraryReader._referenceReader,
      dataReader,
    );

    _read(element, reader);
  }

  /// Ensure that all members of the [element] are available. This includes
  /// being able to ask them for example using [ClassElement.methods], and
  /// as well access them through their [Reference]s. For a class declaration
  /// this means reading them, for a named mixin application this means
  /// computing constructors.
  void readMembers(InstanceElementImpl element) {}

  void _addEnclosingElementTypeParameters(
    ResolutionReader reader,
    ElementImpl element,
  ) {
    var enclosing = element.enclosingElement;
    if (enclosing is InstanceElement) {
      reader._addTypeParameters(enclosing.typeParameters);
    } else if (enclosing is CompilationUnitElement) {
      // Nothing.
    } else if (enclosing is EnumElement) {
      reader._addTypeParameters(enclosing.typeParameters);
    } else if (enclosing is ExtensionElement) {
      reader._addTypeParameters(enclosing.typeParameters);
    } else if (enclosing is MixinElement) {
      reader._addTypeParameters(enclosing.typeParameters);
    } else {
      throw UnimplementedError('${enclosing.runtimeType}');
    }
  }

  void _clearLinkedDataOnRead(E element);

  void _read(E element, ResolutionReader reader);

  void _readFormalParameters(
    ResolutionReader reader,
    List<ParameterElement> parameters,
  ) {
    for (var parameter in parameters) {
      parameter as ParameterElementImpl;
      parameter.metadata = reader._readAnnotationList(
        unitElement: unitElement,
      );
      _readTypeParameters(reader, parameter.typeParameters);
      _readFormalParameters(reader, parameter.parameters);
      parameter.type = reader.readRequiredType();
      if (parameter is ConstVariableElement) {
        var defaultParameter = parameter as ConstVariableElement;
        var initializer = reader._readOptionalExpression();
        if (initializer != null) {
          defaultParameter.constantInitializer = initializer;
        }
      }
      if (parameter is FieldFormalParameterElementImpl) {
        parameter.field = reader.readElement() as FieldElement?;
      }
    }
  }

  void _readTypeParameters(
    ResolutionReader reader,
    List<TypeParameterElement> typeParameters,
  ) {
    reader._addTypeParameters(typeParameters);
    for (var typeParameter in typeParameters) {
      typeParameter as TypeParameterElementImpl;
      typeParameter.metadata = reader._readAnnotationList(
        unitElement: unitElement,
      );
      typeParameter.bound = reader.readType();
      typeParameter.defaultType = reader.readType();
    }
  }
}

class EnumElementLinkedData extends ElementLinkedData<EnumElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  EnumElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(EnumElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: element.enclosingElement,
    );
    _readTypeParameters(reader, element.typeParameters);
    element.supertype = reader._readOptionalInterfaceType();
    element.mixins = reader._readInterfaceTypeList();
    element.interfaces = reader._readInterfaceTypeList();
    element.augmentationTarget = reader.readElement() as EnumElementImpl?;
    element.augmentation = reader.readElement() as EnumElementImpl?;
    if (element.augmentationTarget == null) {
      if (reader.readBool()) {
        var augmented = AugmentedEnumElementImpl(element);
        element.augmentedInternal = augmented;
        augmented.mixins = reader._readInterfaceTypeList();
        augmented.interfaces = reader._readInterfaceTypeList();
        augmented.fields = reader.readElementList();
        augmented.constructors = reader.readElementList();
        augmented.accessors = reader.readElementList();
        augmented.methods = reader.readElementList();
      }
    }
    applyConstantOffsets?.perform();
  }
}

class ExtensionElementLinkedData
    extends ElementLinkedData<ExtensionElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  ExtensionElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(ExtensionElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: element.enclosingElement,
    );
    _readTypeParameters(reader, element.typeParameters);
    element.augmentationTarget = reader.readElement() as ExtensionElementImpl?;
    element.augmentation = reader.readElement() as ExtensionElementImpl?;
    if (element.augmentationTarget == null) {
      var extendedType = reader.readRequiredType();
      if (reader.readBool()) {
        var augmented = AugmentedExtensionElementImpl(element);
        element.augmentedInternal = augmented;
        augmented.fields = reader.readElementList();
        augmented.accessors = reader.readElementList();
        augmented.methods = reader.readElementList();
      }
      element.augmented.extendedType = extendedType;
    }

    applyConstantOffsets?.perform();
  }
}

class ExtensionTypeElementLinkedData
    extends ElementLinkedData<ExtensionTypeElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  ExtensionTypeElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(ExtensionTypeElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: element.enclosingElement,
    );
    _readTypeParameters(reader, element.typeParameters);
    element.interfaces = reader._readInterfaceTypeList();
    element.augmentationTarget =
        reader.readElement() as ExtensionTypeElementImpl?;
    element.augmentation = reader.readElement() as ExtensionTypeElementImpl?;
    if (element.augmentationTarget == null) {
      if (reader.readBool()) {
        var augmented = AugmentedExtensionTypeElementImpl(element);
        element.augmentedInternal = augmented;
        augmented.interfaces = reader._readInterfaceTypeList();
        augmented.fields = reader.readElementList();
        augmented.accessors = reader.readElementList();
        augmented.constructors = reader.readElementList();
        augmented.methods = reader.readElementList();
      }
      element.augmented.typeErasure = reader.readRequiredType();
    }
    applyConstantOffsets?.perform();
  }
}

class FieldElementLinkedData extends ElementLinkedData<FieldElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  FieldElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(FieldElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    _addEnclosingElementTypeParameters(reader, element);
    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    element.type = reader.readRequiredType();

    var augmentationTarget = reader.readElement();
    if (augmentationTarget is FieldElementImpl) {
      augmentationTarget.augmentation = element;
      element.augmentationTarget = augmentationTarget;
    }

    if (element is ConstFieldElementImpl) {
      var initializer = reader._readOptionalExpression();
      if (initializer != null) {
        element.constantInitializer = initializer;
        ConstantContextForExpressionImpl(element, initializer);
      }
    }
    applyConstantOffsets?.perform();
  }
}

class FunctionElementLinkedData extends ElementLinkedData<FunctionElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  FunctionElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(FunctionElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    _readTypeParameters(reader, element.typeParameters);
    element.returnType = reader.readRequiredType();
    _readFormalParameters(reader, element.parameters);
    element.augmentation = reader.readElement() as FunctionElementImpl?;
    element.augmentationTarget = reader.readElement() as FunctionElementImpl?;
    applyConstantOffsets?.perform();
  }
}

/// Not an [ElementLinkedData], just a bundle with data.
class LibraryAugmentationElementLinkedData {
  final int offset;
  ApplyConstantOffsets? applyConstantOffsets;

  LibraryAugmentationElementLinkedData({
    required this.offset,
  });
}

class LibraryElementLinkedData extends ElementLinkedData<LibraryElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  /// When we are applying offsets to a library, we want to lock it.
  bool _isLocked = false;

  LibraryElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  LinkedElementFactory get elementFactory {
    return _libraryReader._elementFactory;
  }

  void lock() {
    assert(!_isLocked);
    _isLocked = true;
  }

  @override
  void read(ElementImpl element) {
    if (!_isLocked) {
      super.read(element);
    }
  }

  void unlock() {
    assert(_isLocked);
    _isLocked = false;
  }

  @override
  void _clearLinkedDataOnRead(LibraryElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    _readLibraryOrAugmentation(element, reader);
    for (var part in element.parts) {
      part.metadata = reader._readAnnotationList(
        unitElement: unitElement,
      );
    }

    element.macroDiagnostics = reader.readMacroDiagnostics();
    element.entryPoint = reader.readElement() as FunctionElement?;

    element.fieldNameNonPromotabilityInfo =
        _readFieldNameNonPromotabilityInfo(reader);

    element.exportNamespace = elementFactory.buildExportNamespace(
      element.source.uri,
      element.exportedReferences,
    );

    applyConstantOffsets?.perform();
  }

  Map<String, FieldNameNonPromotabilityInfo>?
      _readFieldNameNonPromotabilityInfo(ResolutionReader reader) {
    return reader.readOptionalObject((_) {
      return reader.readMap(
        readKey: () => reader.readStringReference(),
        readValue: () {
          return FieldNameNonPromotabilityInfo(
            conflictingFields: reader.readElementList(),
            conflictingGetters: reader.readElementList(),
            conflictingNsmClasses: reader.readElementList(),
          );
        },
      );
    });
  }

  void _readLibraryOrAugmentation(
    LibraryOrAugmentationElementImpl element,
    ResolutionReader reader,
  ) {
    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );

    for (var import in element.libraryImports) {
      import.metadata = reader._readAnnotationList(
        unitElement: unitElement,
      );
      var uri = import.uri;
      if (uri is DirectiveUriWithLibraryImpl) {
        uri.library = reader.libraryOfUri(uri.source.uri);
      }
    }

    for (var export in element.libraryExports) {
      export.metadata = reader._readAnnotationList(
        unitElement: unitElement,
      );
      var uri = export.uri;
      if (uri is DirectiveUriWithLibraryImpl) {
        uri.library = reader.libraryOfUri(uri.source.uri);
      }
    }

    for (var import in element.augmentationImports) {
      import.metadata = reader._readAnnotationList(
        // TODO(scheglov): Here and for parts, unit is not valid. Test and fix.
        unitElement: unitElement,
      );
      var importedAugmentation = import.importedAugmentation;
      if (importedAugmentation != null) {
        var linkedData = importedAugmentation.linkedData!;
        reader.setOffset(linkedData.offset);
        _readLibraryOrAugmentation(importedAugmentation, reader);
        linkedData.applyConstantOffsets?.perform();
      }
    }
  }
}

class LibraryReader {
  final LinkedElementFactory _elementFactory;
  final SummaryDataReader _reader;
  final Uri uri;
  final Map<Uri, Uint8List> _unitsInformativeBytes;
  final int _baseResolutionOffset;
  final _ReferenceReader _referenceReader;
  final Reference _reference;
  final int _offset;
  final InfoDeclarationStore _deserializedDataStore;
  final String? macroGeneratedCode;

  final Uint32List _classMembersLengths;
  int _classMembersLengthsIndex = 0;

  LibraryReader._({
    required LinkedElementFactory elementFactory,
    required SummaryDataReader reader,
    required this.uri,
    required Map<Uri, Uint8List> unitsInformativeBytes,
    required int baseResolutionOffset,
    required _ReferenceReader referenceReader,
    required Reference reference,
    required int offset,
    required Uint32List classMembersLengths,
    required InfoDeclarationStore infoDeclarationStore,
    required this.macroGeneratedCode,
  })  : _elementFactory = elementFactory,
        _reader = reader,
        _unitsInformativeBytes = unitsInformativeBytes,
        _baseResolutionOffset = baseResolutionOffset,
        _referenceReader = referenceReader,
        _reference = reference,
        _offset = offset,
        _classMembersLengths = classMembersLengths,
        _deserializedDataStore = infoDeclarationStore;

  LibraryElementImpl readElement({required Source librarySource}) {
    var analysisContext = _elementFactory.analysisContext;
    var analysisSession = _elementFactory.analysisSession;

    _reader.offset = _offset;
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();

    // TODO(scheglov): https://github.com/dart-lang/sdk/issues/51855
    // This should not be needed.
    // But I have a suspicion that we attempt to read the library twice.
    _classMembersLengthsIndex = 0;

    var name = _reader.readStringReference();
    var featureSet = _readFeatureSet();

    var libraryElement = LibraryElementImpl(
        analysisContext, analysisSession, name, -1, 0, featureSet);
    _reference.element = libraryElement;
    libraryElement.reference = _reference;

    libraryElement.languageVersion = _readLanguageVersion();
    _readLibraryOrAugmentationElement(libraryElement);
    LibraryElementFlags.read(_reader, libraryElement);

    libraryElement.definingCompilationUnit = _readUnitElement(
      containerSource: librarySource,
      unitSource: librarySource,
      unitContainerRef: _reference.getChild('@unit'),
    );

    libraryElement.parts = _reader.readTypedList(() {
      return _readPartElement(
        libraryElement: libraryElement,
      );
    });

    libraryElement.exportedReferences = _reader.readTypedList(
      _readExportedReference,
    );

    libraryElement.nameUnion = ElementNameUnion.read(
      _reader.readUInt30List(),
    );

    var accessorAugmentationsOffset = _reader.readUInt30();

    libraryElement.linkedData = LibraryElementLinkedData(
      reference: _reference,
      libraryReader: this,
      unitElement: libraryElement.definingCompilationUnit,
      offset: resolutionOffset,
    );

    _declareDartCoreDynamicNever();

    InformativeDataApplier(
            _elementFactory, _unitsInformativeBytes, _deserializedDataStore)
        .applyTo(libraryElement);

    _readPropertyAccessorAugmentations(accessorAugmentationsOffset);

    return libraryElement;
  }

  /// These elements are implicitly declared in `dart:core`.
  void _declareDartCoreDynamicNever() {
    if (_reference.name == 'dart:core') {
      _reference.getChild('dynamic').element = DynamicElementImpl.instance;
      _reference.getChild('Never').element = NeverElementImpl.instance;
    }
  }

  LibraryAugmentationElementImpl _readAugmentationElement({
    required LibraryOrAugmentationElementImpl augmentationTarget,
    required Source unitSource,
  }) {
    var macroGenerated = _reader.readOptionalObject((reader) {
      return MacroGeneratedAugmentationLibrary(
        code: _reader.readStringUtf8(),
        informativeBytes: _reader.readUint8List(),
      );
    });

    var definingUnit = _readUnitElement(
      containerSource: unitSource,
      unitSource: unitSource,
      unitContainerRef: _reference.getChild('@augmentation'),
    );

    var augmentation = LibraryAugmentationElementImpl(
      augmentationTarget: augmentationTarget,
      nameOffset: -1, // TODO(scheglov): implement, test
    );
    augmentation.definingCompilationUnit = definingUnit;
    augmentation.reference = definingUnit.reference!;
    augmentation.macroGenerated = macroGenerated;

    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
    _readLibraryOrAugmentationElement(augmentation);

    augmentation.linkedData = LibraryAugmentationElementLinkedData(
      offset: resolutionOffset,
    );

    return augmentation;
  }

  AugmentationImportElementImpl _readAugmentationImportElement({
    required LibraryOrAugmentationElementImpl container,
  }) {
    var uri = _readDirectiveUri(
      container: container,
    );
    return AugmentationImportElementImpl(
      importKeywordOffset: -1, // TODO(scheglov): implement, test
      uri: uri,
    );
  }

  ClassElementImpl _readClassElement(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();

    var reference = _readReference();
    var name = reference.elementName;

    var element = ClassElementImpl(name, -1);

    var linkedData = ClassElementLinkedData(
      reference: reference,
      libraryReader: this,
      unitElement: unitElement,
      offset: resolutionOffset,
    );
    element.setLinkedData(reference, linkedData);
    ClassElementFlags.read(_reader, element);

    element.typeParameters = _readTypeParameters();

    if (!element.isMixinApplication) {
      var membersOffset = _reader.offset;
      linkedData._readMembers = () {
        _reader.offset = membersOffset;
        _readClassElementMembers(unitElement, element, reference);
      };
      if (_classMembersLengthsIndex >= _classMembersLengths.length) {
        // TODO(scheglov): https://github.com/dart-lang/sdk/issues/51855
        throw StateError(
          '[libraryReference: $_reference]'
          '[classReference: $reference]'
          '[_classMembersLengthsIndex: $_classMembersLengthsIndex]'
          '[_classMembersLengths: $_classMembersLengths]',
        );
      }
      _reader.offset += _classMembersLengths[_classMembersLengthsIndex++];
    }

    return element;
  }

  void _readClassElementMembers(
    CompilationUnitElementImpl unitElement,
    ClassElementImpl element,
    Reference reference,
  ) {
    var accessors = <PropertyAccessorElementImpl>[];
    var fields = <FieldElementImpl>[];
    _readFields(unitElement, element, reference, accessors, fields);
    _readPropertyAccessors(
        unitElement, element, reference, accessors, fields, '@field');
    element.fields = fields.toFixedList();
    element.accessors = accessors.toFixedList();

    element.constructors = _readConstructors(unitElement, element, reference);
    element.methods = _readMethods(unitElement, element, reference);
  }

  void _readClasses(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    unitElement.classes = _reader.readTypedList(() {
      return _readClassElement(unitElement, unitReference);
    });
  }

  List<ConstructorElementImpl> _readConstructors(
    CompilationUnitElementImpl unitElement,
    InterfaceElementImpl classElement,
    Reference classReference,
  ) {
    return _reader.readTypedList(() {
      var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
      var reference = _readReference();
      var name = reference.elementName.ifEqualThen('new', '');
      var element = ConstructorElementImpl(name, -1);
      var linkedData = ConstructorElementLinkedData(
        reference: reference,
        libraryReader: this,
        unitElement: unitElement,
        offset: resolutionOffset,
      );
      element.setLinkedData(reference, linkedData);
      ConstructorElementFlags.read(_reader, element);
      element.parameters = _readParameters();
      return element;
    });
  }

  DirectiveUri _readDirectiveUri({
    required LibraryOrAugmentationElementImpl container,
  }) {
    DirectiveUriWithRelativeUriStringImpl readWithRelativeUriString() {
      var relativeUriString = _reader.readStringReference();
      return DirectiveUriWithRelativeUriStringImpl(
        relativeUriString: relativeUriString,
      );
    }

    DirectiveUriWithRelativeUriImpl readWithRelativeUri() {
      var parent = readWithRelativeUriString();
      var relativeUri = uriCache.parse(_reader.readStringReference());
      return DirectiveUriWithRelativeUriImpl(
        relativeUriString: parent.relativeUriString,
        relativeUri: relativeUri,
      );
    }

    DirectiveUriWithSourceImpl readWithSource() {
      var parent = readWithRelativeUri();

      var analysisContext = _elementFactory.analysisContext;
      var sourceFactory = analysisContext.sourceFactory;

      var sourceUriStr = _reader.readStringReference();
      var sourceUri = uriCache.parse(sourceUriStr);
      var source = sourceFactory.forUri2(sourceUri);

      // TODO(scheglov): https://github.com/dart-lang/sdk/issues/49431
      var fixedSource = source ?? sourceFactory.forUri('dart:math')!;

      return DirectiveUriWithSourceImpl(
        relativeUriString: parent.relativeUriString,
        relativeUri: parent.relativeUri,
        source: fixedSource,
      );
    }

    var kindIndex = _reader.readByte();
    var kind = DirectiveUriKind.values[kindIndex];
    switch (kind) {
      case DirectiveUriKind.withAugmentation:
        var parent = readWithSource();
        var augmentation = _readAugmentationElement(
          augmentationTarget: container,
          unitSource: parent.source,
        );
        return DirectiveUriWithAugmentationImpl(
          relativeUriString: parent.relativeUriString,
          relativeUri: parent.relativeUri,
          source: parent.source,
          augmentation: augmentation,
        );
      case DirectiveUriKind.withLibrary:
        var parent = readWithSource();
        return DirectiveUriWithLibraryImpl.read(
          relativeUriString: parent.relativeUriString,
          relativeUri: parent.relativeUri,
          source: parent.source,
        );
      case DirectiveUriKind.withUnit:
        var parent = readWithSource();
        var unitElement = _readUnitElement(
          containerSource: container.source,
          unitSource: parent.source,
          unitContainerRef: _reference.getChild('@unit'),
        );
        return DirectiveUriWithUnitImpl(
          relativeUriString: parent.relativeUriString,
          relativeUri: parent.relativeUri,
          unit: unitElement,
        );
      case DirectiveUriKind.withSource:
        return readWithSource();
      case DirectiveUriKind.withRelativeUri:
        return readWithRelativeUri();
      case DirectiveUriKind.withRelativeUriString:
        return readWithRelativeUriString();
      case DirectiveUriKind.withNothing:
        return DirectiveUriImpl();
    }
  }

  EnumElementImpl _readEnumElement(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
    var reference = _readReference();
    var name = reference.elementName;

    var element = EnumElementImpl(name, -1);

    var linkedData = EnumElementLinkedData(
      reference: reference,
      libraryReader: this,
      unitElement: unitElement,
      offset: resolutionOffset,
    );
    element.setLinkedData(reference, linkedData);
    EnumElementFlags.read(_reader, element);

    element.typeParameters = _readTypeParameters();

    var accessors = <PropertyAccessorElementImpl>[];
    var fields = <FieldElementImpl>[];

    _readFields(unitElement, element, reference, accessors, fields);
    _readPropertyAccessors(
        unitElement, element, reference, accessors, fields, '@field');
    element.fields = fields.toFixedList();
    element.accessors = accessors.toFixedList();

    element.constructors = _readConstructors(unitElement, element, reference);
    element.methods = _readMethods(unitElement, element, reference);

    return element;
  }

  void _readEnums(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    unitElement.enums = _reader.readTypedList(() {
      return _readEnumElement(unitElement, unitReference);
    });
  }

  ExportedReference _readExportedReference() {
    var kind = _reader.readByte();
    if (kind == 0) {
      var index = _reader.readUInt30();
      var reference = _referenceReader.referenceOfIndex(index);
      return ExportedReferenceDeclared(
        reference: reference,
      );
    } else if (kind == 1) {
      var index = _reader.readUInt30();
      var reference = _referenceReader.referenceOfIndex(index);
      return ExportedReferenceExported(
        reference: reference,
        locations: _reader.readTypedList(_readExportLocation),
      );
    } else {
      throw StateError('kind: $kind');
    }
  }

  LibraryExportElementImpl _readExportElement({
    required LibraryOrAugmentationElementImpl container,
  }) {
    return LibraryExportElementImpl(
      combinators: _reader.readTypedList(_readNamespaceCombinator),
      exportKeywordOffset: -1,
      uri: _readDirectiveUri(
        container: container,
      ),
    );
  }

  ExportLocation _readExportLocation() {
    return ExportLocation(
      containerIndex: _reader.readUInt30(),
      exportIndex: _reader.readUInt30(),
    );
  }

  ExtensionElementImpl _readExtensionElement(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();

    var reference = _readReference();
    var name = _reader.readBool() ? reference.elementName : null;

    var element = ExtensionElementImpl(name, -1);
    element.setLinkedData(
      reference,
      ExtensionElementLinkedData(
        reference: reference,
        libraryReader: this,
        unitElement: unitElement,
        offset: resolutionOffset,
      ),
    );
    ExtensionElementFlags.read(_reader, element);

    element.typeParameters = _readTypeParameters();

    var accessors = <PropertyAccessorElementImpl>[];
    var fields = <FieldElementImpl>[];
    _readPropertyAccessors(
        unitElement, element, reference, accessors, fields, '@field');
    _readFields(unitElement, element, reference, accessors, fields);
    element.accessors = accessors;
    element.fields = fields;

    element.methods = _readMethods(unitElement, element, reference);

    return element;
  }

  void _readExtensions(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    unitElement.extensions = _reader.readTypedList(() {
      return _readExtensionElement(unitElement, unitReference);
    });
  }

  ExtensionTypeElementImpl _readExtensionTypeElement(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
    var reference = _readReference();
    var name = reference.elementName;

    var element = ExtensionTypeElementImpl(name, -1);
    element.setLinkedData(
      reference,
      ExtensionTypeElementLinkedData(
        reference: reference,
        libraryReader: this,
        unitElement: unitElement,
        offset: resolutionOffset,
      ),
    );
    ExtensionTypeElementFlags.read(_reader, element);

    element.typeParameters = _readTypeParameters();

    var fields = <FieldElementImpl>[];
    var accessors = <PropertyAccessorElementImpl>[];
    _readFields(unitElement, element, reference, accessors, fields);
    _readPropertyAccessors(
        unitElement, element, reference, accessors, fields, '@field');
    element.fields = fields;
    element.accessors = accessors;

    element.constructors = _readConstructors(unitElement, element, reference);
    element.methods = _readMethods(unitElement, element, reference);

    if (element.isAugmentationChainStart) {
      element.augmentedInternal
        ..primaryConstructor = element.constructors.first
        ..representation = element.fields.first;
    }

    return element;
  }

  void _readExtensionTypes(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    unitElement.extensionTypes = _reader.readTypedList(() {
      return _readExtensionTypeElement(unitElement, unitReference);
    });
  }

  FeatureSet _readFeatureSet() {
    var featureSetEncoded = _reader.readUint8List();
    return ExperimentStatus.fromStorage(featureSetEncoded);
  }

  FieldElementImpl _readFieldElement(
    CompilationUnitElementImpl unitElement,
    ElementImpl classElement,
    Reference classReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();

    var reference = _readReference();
    var getterReference = _readOptionalReference();
    var setterReference = _readOptionalReference();

    var name = reference.elementName;
    var isConstElement = _reader.readBool();

    FieldElementImpl element;
    if (isConstElement) {
      element = ConstFieldElementImpl(name, -1);
    } else {
      element = FieldElementImpl(name, -1);
    }

    var linkedData = FieldElementLinkedData(
      reference: reference,
      libraryReader: this,
      unitElement: unitElement,
      offset: resolutionOffset,
    );
    element.setLinkedData(reference, linkedData);

    FieldElementFlags.read(_reader, element);
    element.typeInferenceError = _readTopLevelInferenceError();

    if (!element.isAugmentation) {
      if (getterReference != null) {
        element.createImplicitGetter(getterReference);
      }
      if (element.hasSetter && setterReference != null) {
        element.createImplicitSetter(setterReference);
      }
    }

    return element;
  }

  void _readFields(
    CompilationUnitElementImpl unitElement,
    ElementImpl classElement,
    Reference classReference,
    List<PropertyAccessorElement> accessors,
    List<FieldElement> variables,
  ) {
    var createdElements = <FieldElement>[];
    var variableElementCount = _reader.readUInt30();
    for (var i = 0; i < variableElementCount; i++) {
      var variable =
          _readFieldElement(unitElement, classElement, classReference);
      createdElements.add(variable);
      variables.add(variable);

      var getter = variable.getter;
      if (getter is PropertyAccessorElementImpl) {
        accessors.add(getter);
      }

      var setter = variable.setter;
      if (setter is PropertyAccessorElementImpl) {
        accessors.add(setter);
      }
    }
  }

  void _readFunctions(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    unitElement.functions = _reader.readTypedList(() {
      var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
      var reference = _readReference();
      var name = reference.elementName;

      var element = FunctionElementImpl(name, -1);

      var linkedData = FunctionElementLinkedData(
        reference: reference,
        libraryReader: this,
        unitElement: unitElement,
        offset: resolutionOffset,
      );
      element.setLinkedData(reference, linkedData);

      FunctionElementFlags.read(_reader, element);
      element.typeParameters = _readTypeParameters();
      element.parameters = _readParameters();

      return element;
    });
  }

  LibraryImportElementImpl _readImportElement({
    required LibraryOrAugmentationElementImpl container,
  }) {
    var element = LibraryImportElementImpl(
      combinators: _reader.readTypedList(_readNamespaceCombinator),
      importKeywordOffset: -1,
      prefix: _readImportElementPrefix(
        container: container,
      ),
      uri: _readDirectiveUri(
        container: container,
      ),
    );
    LibraryImportElementFlags.read(_reader, element);
    return element;
  }

  ImportElementPrefixImpl? _readImportElementPrefix({
    required LibraryOrAugmentationElementImpl container,
  }) {
    PrefixElementImpl buildElement(String name) {
      // TODO(scheglov): Make reference required.
      var containerRef = container.reference!;
      var reference = containerRef.getChild('@prefix').getChild(name);
      var existing = reference.element;
      if (existing is PrefixElementImpl) {
        return existing;
      } else {
        return PrefixElementImpl(name, -1, reference: reference);
      }
    }

    var kindIndex = _reader.readByte();
    var kind = ImportElementPrefixKind.values[kindIndex];
    switch (kind) {
      case ImportElementPrefixKind.isDeferred:
        var name = _reader.readStringReference();
        return DeferredImportElementPrefixImpl(
          element: buildElement(name),
        );
      case ImportElementPrefixKind.isNotDeferred:
        var name = _reader.readStringReference();
        return ImportElementPrefixImpl(
          element: buildElement(name),
        );
      case ImportElementPrefixKind.isNull:
        return null;
    }
  }

  LibraryLanguageVersion _readLanguageVersion() {
    var packageMajor = _reader.readUInt30();
    var packageMinor = _reader.readUInt30();
    var package = Version(packageMajor, packageMinor, 0);

    Version? override;
    if (_reader.readBool()) {
      var overrideMajor = _reader.readUInt30();
      var overrideMinor = _reader.readUInt30();
      override = Version(overrideMajor, overrideMinor, 0);
    }

    return LibraryLanguageVersion(package: package, override: override);
  }

  void _readLibraryOrAugmentationElement(
    LibraryOrAugmentationElementImpl container,
  ) {
    container.libraryImports = _reader.readTypedList(() {
      return _readImportElement(
        container: container,
      );
    });

    container.libraryExports = _reader.readTypedList(() {
      return _readExportElement(
        container: container,
      );
    });

    container.augmentationImports = _reader.readTypedList(() {
      return _readAugmentationImportElement(
        container: container,
      );
    });

    for (var import in container.libraryImports) {
      var prefixElement = import.prefix?.element;
      if (prefixElement is PrefixElementImpl) {
        container.encloseElement(prefixElement);
      }
    }
  }

  List<MethodElementImpl> _readMethods(
    CompilationUnitElementImpl unitElement,
    ElementImpl enclosingElement,
    Reference enclosingReference,
  ) {
    return _reader.readTypedList(() {
      var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
      var reference = _readReference();
      var name = reference.elementName;
      var element = MethodElementImpl(name, -1);
      var linkedData = MethodElementLinkedData(
        reference: reference,
        libraryReader: this,
        unitElement: unitElement,
        offset: resolutionOffset,
      );
      element.setLinkedData(reference, linkedData);
      MethodElementFlags.read(_reader, element);
      element.typeParameters = _readTypeParameters();
      element.parameters = _readParameters();
      element.typeInferenceError = _readTopLevelInferenceError();
      return element;
    });
  }

  MixinElementImpl _readMixinElement(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
    var reference = _readReference();
    var name = reference.elementName;

    var element = MixinElementImpl(name, -1);

    var linkedData = MixinElementLinkedData(
      reference: reference,
      libraryReader: this,
      unitElement: unitElement,
      offset: resolutionOffset,
    );
    element.setLinkedData(reference, linkedData);
    MixinElementFlags.read(_reader, element);

    element.typeParameters = _readTypeParameters();

    var fields = <FieldElementImpl>[];
    var accessors = <PropertyAccessorElementImpl>[];
    _readFields(unitElement, element, reference, accessors, fields);
    _readPropertyAccessors(
        unitElement, element, reference, accessors, fields, '@field');
    element.fields = fields.toFixedList();
    element.accessors = accessors.toFixedList();

    element.constructors = _readConstructors(unitElement, element, reference);
    element.methods = _readMethods(unitElement, element, reference);
    element.superInvokedNames = _reader.readStringReferenceList();

    return element;
  }

  void _readMixins(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    unitElement.mixins = _reader.readTypedList(() {
      return _readMixinElement(unitElement, unitReference);
    });
  }

  NamespaceCombinator _readNamespaceCombinator() {
    var tag = _reader.readByte();
    if (tag == Tag.HideCombinator) {
      var combinator = HideElementCombinatorImpl();
      combinator.hiddenNames = _reader.readStringReferenceList();
      return combinator;
    } else if (tag == Tag.ShowCombinator) {
      var combinator = ShowElementCombinatorImpl();
      combinator.shownNames = _reader.readStringReferenceList();
      return combinator;
    } else {
      throw UnimplementedError('tag: $tag');
    }
  }

  /// Read the reference of a non-local element.
  Reference? _readOptionalReference() {
    return _reader.readOptionalObject(
      (reader) => _readReference(),
    );
  }

  // TODO(scheglov): Deduplicate parameter reading implementation.
  List<ParameterElementImpl> _readParameters() {
    return _reader.readTypedList(() {
      var name = _reader.readStringReference();
      var isDefault = _reader.readBool();
      var isInitializingFormal = _reader.readBool();
      var isSuperFormal = _reader.readBool();
      var reference = _readOptionalReference();

      var kindIndex = _reader.readByte();
      var kind = ResolutionReader._formalParameterKind(kindIndex);

      ParameterElementImpl element;
      if (!isDefault) {
        if (isInitializingFormal) {
          element = FieldFormalParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          );
        } else if (isSuperFormal) {
          element = SuperFormalParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          );
        } else {
          element = ParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          );
        }
      } else {
        if (isInitializingFormal) {
          element = DefaultFieldFormalParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          );
        } else if (isSuperFormal) {
          element = DefaultSuperFormalParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          );
        } else {
          element = DefaultParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          );
        }
        if (reference != null) {
          element.reference = reference;
          reference.element = element;
        }
      }
      ParameterElementFlags.read(_reader, element);
      element.typeParameters = _readTypeParameters();
      element.parameters = _readParameters();
      return element;
    });
  }

  PartElementImpl _readPartElement({
    required LibraryElementImpl libraryElement,
  }) {
    var uri = _readDirectiveUri(
      container: libraryElement,
    );

    return PartElementImpl(
      uri: uri,
    );
  }

  /// This method is invoked when all units of the library are read, the
  /// defining unit, and all its augmentations. So, we have all elements
  /// created (excluding class members, that are delayed).
  ///
  /// We can read now augmentation back and forth pointers, for accessors and
  /// properties.
  void _readPropertyAccessorAugmentations(int offset) {
    var reader = ResolutionReader(
      _elementFactory,
      _referenceReader,
      _reader.fork(_baseResolutionOffset + offset),
    );
    var accessors = reader.readElementList<PropertyAccessorElementImpl>();
    for (var element in accessors) {
      element.linkedData?.read(element);
    }

    var properties = reader.readElementList<PropertyInducingElementImpl>();
    for (var element in properties) {
      element.linkedData?.read(element);
    }
  }

  PropertyAccessorElementImpl _readPropertyAccessorElement(
    CompilationUnitElementImpl unitElement,
    ElementImpl classElement,
    Reference classReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();

    var reference = _readReference();
    var name = reference.elementName;

    var element = PropertyAccessorElementImpl(name, -1);
    PropertyAccessorElementFlags.read(_reader, element);

    var linkedData = PropertyAccessorElementLinkedData(
      reference: reference,
      libraryReader: this,
      unitElement: unitElement,
      offset: resolutionOffset,
    );
    element.setLinkedData(reference, linkedData);

    element.parameters = _readParameters();
    return element;
  }

  void _readPropertyAccessors(
    CompilationUnitElementImpl unitElement,
    ElementImpl enclosingElement,
    Reference enclosingReference,
    List<PropertyAccessorElement> accessors,
    List<PropertyInducingElement> properties,
    String containerRefName,
  ) {
    var containerRef = enclosingReference.getChild(containerRefName);

    var accessorCount = _reader.readUInt30();
    for (var i = 0; i < accessorCount; i++) {
      var accessor = _readPropertyAccessorElement(
        unitElement,
        enclosingElement,
        enclosingReference,
      );
      accessors.add(accessor);

      if (accessor.isAugmentation) {
        continue;
      }

      var name = accessor.displayName;
      var isGetter = accessor.isGetter;

      bool canUseExisting(PropertyInducingElement property) {
        return property.isSynthetic ||
            accessor.isSetter && property.setter == null;
      }

      PropertyInducingElementImpl property;
      var reference = containerRef.getChild(name);
      var existing = reference.element;
      if (enclosingElement is CompilationUnitElementImpl) {
        if (existing is TopLevelVariableElementImpl &&
            canUseExisting(existing)) {
          property = existing;
        } else {
          property = TopLevelVariableElementImpl(name, -1)
            ..enclosingElement = enclosingElement
            ..reference = reference
            ..isSynthetic = true;
          reference.element ??= property;
          properties.add(property);
        }
      } else {
        if (existing is FieldElementImpl && canUseExisting(existing)) {
          property = existing;
        } else {
          property = FieldElementImpl(name, -1)
            ..enclosingElement = enclosingElement
            ..reference = reference
            ..isStatic = accessor.isStatic
            ..isSynthetic = true;
          reference.element ??= property;
          properties.add(property);
        }
      }

      accessor.variable2 = property;
      if (isGetter) {
        property.getter = accessor;
      } else {
        property.setter = accessor;
        if (property.isSynthetic) {
          property.isFinal = false;
        }
      }
    }
  }

  /// Read the reference of a non-local element.
  Reference _readReference() {
    var referenceIndex = _reader.readUInt30();
    return _referenceReader.referenceOfIndex(referenceIndex);
  }

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

  TopLevelVariableElementImpl _readTopLevelVariableElement(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();

    var reference = _readReference();
    var getterReference = _readOptionalReference();
    var setterReference = _readOptionalReference();

    var name = reference.elementName;
    var isConst = _reader.readBool();

    TopLevelVariableElementImpl element;
    if (isConst) {
      element = ConstTopLevelVariableElementImpl(name, -1);
    } else {
      element = TopLevelVariableElementImpl(name, -1);
    }

    var linkedData = TopLevelVariableElementLinkedData(
      reference: reference,
      libraryReader: this,
      unitElement: unitElement,
      offset: resolutionOffset,
    );
    element.setLinkedData(reference, linkedData);

    element.isConst = isConst;
    TopLevelVariableElementFlags.read(_reader, element);
    element.typeInferenceError = _readTopLevelInferenceError();

    if (getterReference != null) {
      element.createImplicitGetter(getterReference);
    }
    if (element.hasSetter && setterReference != null) {
      element.createImplicitSetter(setterReference);
    }

    return element;
  }

  void _readTopLevelVariables(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
    List<PropertyAccessorElementImpl> accessors,
    List<TopLevelVariableElementImpl> variables,
  ) {
    var variableElementCount = _reader.readUInt30();
    for (var i = 0; i < variableElementCount; i++) {
      var variable = _readTopLevelVariableElement(unitElement, unitReference);
      variables.add(variable);

      var getter = variable.getter;
      if (getter is PropertyAccessorElementImpl) {
        accessors.add(getter);
      }

      var setter = variable.setter;
      if (setter is PropertyAccessorElementImpl) {
        accessors.add(setter);
      }
    }
  }

  TypeAliasElementImpl _readTypeAliasElement(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
    var reference = _readReference();
    var name = reference.elementName;

    var isFunctionTypeAliasBased = _reader.readBool();

    TypeAliasElementImpl element;
    if (isFunctionTypeAliasBased) {
      element = TypeAliasElementImpl(name, -1);
      element.isFunctionTypeAliasBased = true;
    } else {
      element = TypeAliasElementImpl(name, -1);
    }

    var linkedData = TypeAliasElementLinkedData(
      reference: reference,
      libraryReader: this,
      unitElement: unitElement,
      offset: resolutionOffset,
    );
    element.setLinkedData(reference, linkedData);

    element.isFunctionTypeAliasBased = isFunctionTypeAliasBased;
    TypeAliasElementFlags.read(_reader, element);

    element.typeParameters = _readTypeParameters();

    return element;
  }

  void _readTypeAliases(
    CompilationUnitElementImpl unitElement,
    Reference unitReference,
  ) {
    unitElement.typeAliases = _reader.readTypedList(() {
      return _readTypeAliasElement(unitElement, unitReference);
    });
  }

  List<TypeParameterElementImpl> _readTypeParameters() {
    return _reader.readTypedList(() {
      var name = _reader.readStringReference();
      var varianceEncoding = _reader.readByte();
      var variance = _decodeVariance(varianceEncoding);
      var element = TypeParameterElementImpl(name, -1);
      element.variance = variance;
      return element;
    });
  }

  CompilationUnitElementImpl _readUnitElement({
    required Source containerSource,
    required Source unitSource,
    required Reference unitContainerRef,
  }) {
    var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();

    var unitElement = CompilationUnitElementImpl(
      source: unitSource,
      librarySource: containerSource,
      lineInfo: LineInfo([0]),
    );

    var unitReference = unitContainerRef.getChild('${unitSource.uri}');
    unitElement.setLinkedData(
      unitReference,
      CompilationUnitElementLinkedData(
        reference: unitReference,
        libraryReader: this,
        unitElement: unitElement,
        offset: resolutionOffset,
      ),
    );

    unitElement.uri = _reader.readOptionalStringReference();
    unitElement.isSynthetic = _reader.readBool();

    _readClasses(unitElement, unitReference);
    _readEnums(unitElement, unitReference);
    _readExtensions(unitElement, unitReference);
    _readExtensionTypes(unitElement, unitReference);
    _readFunctions(unitElement, unitReference);
    _readMixins(unitElement, unitReference);
    _readTypeAliases(unitElement, unitReference);

    var accessors = <PropertyAccessorElementImpl>[];
    var variables = <TopLevelVariableElementImpl>[];
    _readTopLevelVariables(unitElement, unitReference, accessors, variables);
    _readPropertyAccessors(unitElement, unitElement, unitReference, accessors,
        variables, '@variable');
    unitElement.accessors = accessors.toFixedList();
    unitElement.topLevelVariables = variables.toFixedList();
    return unitElement;
  }

  static Variance? _decodeVariance(int index) {
    var tag = TypeParameterVarianceTag.values[index];
    switch (tag) {
      case TypeParameterVarianceTag.legacy:
        return null;
      case TypeParameterVarianceTag.unrelated:
        return Variance.unrelated;
      case TypeParameterVarianceTag.covariant:
        return Variance.covariant;
      case TypeParameterVarianceTag.contravariant:
        return Variance.contravariant;
      case TypeParameterVarianceTag.invariant:
        return Variance.invariant;
    }
  }
}

class MethodElementLinkedData extends ElementLinkedData<MethodElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  MethodElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(MethodElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    _addEnclosingElementTypeParameters(reader, element);
    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    _readTypeParameters(reader, element.typeParameters);
    _readFormalParameters(reader, element.parameters);
    element.returnType = reader.readRequiredType();
    element.augmentation = reader.readElement() as MethodElementImpl?;
    element.augmentationTarget = reader.readElement() as MethodElementImpl?;
    applyConstantOffsets?.perform();
  }
}

class MixinElementLinkedData extends ElementLinkedData<MixinElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  MixinElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(MixinElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: element.enclosingElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    _readTypeParameters(reader, element.typeParameters);
    element.superclassConstraints = reader._readInterfaceTypeList();
    element.interfaces = reader._readInterfaceTypeList();
    element.augmentationTarget = reader.readElement() as MixinElementImpl?;
    element.augmentation = reader.readElement() as MixinElementImpl?;

    if (element.augmentationTarget == null) {
      if (reader.readBool()) {
        var augmented = AugmentedMixinElementImpl(element);
        element.augmentedInternal = augmented;
        augmented.superclassConstraints = reader._readInterfaceTypeList();
        augmented.interfaces = reader._readInterfaceTypeList();
        augmented.fields = reader.readElementList();
        augmented.accessors = reader.readElementList();
        augmented.methods = reader.readElementList();
      }
    }

    applyConstantOffsets?.perform();
  }
}

class PropertyAccessorElementLinkedData
    extends ElementLinkedData<PropertyAccessorElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  PropertyAccessorElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(PropertyAccessorElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    _addEnclosingElementTypeParameters(reader, element);

    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );

    element.returnType = reader.readRequiredType();
    _readFormalParameters(reader, element.parameters);

    var augmentationTarget = reader.readElement();
    if (augmentationTarget is PropertyAccessorElementImpl) {
      augmentationTarget.augmentation = element;
      element.augmentationTarget = augmentationTarget;
      element.variable2 = augmentationTarget.variable2;
    }

    applyConstantOffsets?.perform();
  }
}

/// Helper for reading elements and types from their binary encoding.
class ResolutionReader {
  final LinkedElementFactory _elementFactory;
  final _ReferenceReader _referenceReader;
  final SummaryDataReader _reader;

  /// The stack of [TypeParameterElement]s and [ParameterElement] that are
  /// available in the scope of [readElement] and [readType].
  ///
  /// This stack is shared with the client of the reader, and update mostly
  /// by the client. However it is also updated during [_readFunctionType].
  final List<Element> _localElements = [];

  ResolutionReader(
    this._elementFactory,
    this._referenceReader,
    this._reader,
  );

  LibraryElementImpl libraryOfUri(Uri uri) {
    return _elementFactory.libraryOfUri2(uri);
  }

  bool readBool() {
    return _reader.readBool();
  }

  int readByte() {
    return _reader.readByte();
  }

  double readDouble() {
    return _reader.readDouble();
  }

  Element? readElement() {
    var memberFlags = _reader.readByte();
    var element = _readRawElement();

    if (element == null) {
      return null;
    }

    if (memberFlags == Tag.RawElement) {
      return element;
    }

    if (memberFlags == Tag.MemberWithTypeArguments) {
      var enclosing = element.enclosingElement as InstanceElement;

      var declaration = enclosing.augmented.declaration;
      var declarationTypeParameters = declaration.typeParameters;

      var augmentationSubstitution = Substitution.empty;
      if (enclosing != declaration) {
        var elementTypeParameters = enclosing.typeParameters;
        // We don't add augmentation members if numbers of type parameters
        // don't match, so we can assume that they are the same here.
        augmentationSubstitution = Substitution.fromPairs(
          elementTypeParameters,
          declarationTypeParameters.instantiateNone(),
        );
      }

      var substitution = Substitution.empty;
      var typeArguments = _readTypeList();
      if (typeArguments.isNotEmpty) {
        substitution = Substitution.fromPairs(
          declarationTypeParameters,
          typeArguments,
        );
      }

      if (element is ExecutableElement) {
        element = ExecutableMember.fromAugmentation(
            element, augmentationSubstitution);
        element = ExecutableMember.from2(element, substitution);
      } else {
        element as FieldElement;
        element =
            FieldMember.fromAugmentation(element, augmentationSubstitution);
        element = FieldMember.from2(element, substitution);
      }
    }

    if (memberFlags == Tag.MemberWithTypeArguments) {
      return element;
    }

    throw UnimplementedError('memberFlags: $memberFlags');
  }

  List<T> readElementList<T extends Element>() {
    return _reader.readTypedListCast<T>(readElement);
  }

  T readEnum<T extends Enum>(List<T> values) {
    var index = readByte();
    return values[index];
  }

  List<AnalyzerMacroDiagnostic> readMacroDiagnostics() {
    return readTypedList(_readMacroDiagnostic);
  }

  Map<K, V> readMap<K, V>({
    required K Function() readKey,
    required V Function() readValue,
  }) {
    var length = readUInt30();
    if (length == 0) {
      return const {};
    }

    return {
      for (var i = 0; i < length; i++) readKey(): readValue(),
    };
  }

  FunctionType? readOptionalFunctionType() {
    var type = readType();
    return type is FunctionType ? type : null;
  }

  T? readOptionalObject<T>(T Function(SummaryDataReader reader) read) {
    return _reader.readOptionalObject(read);
  }

  List<DartType>? readOptionalTypeList() {
    if (_reader.readBool()) {
      return _readTypeList();
    } else {
      return null;
    }
  }

  DartType readRequiredType() {
    return readType()!;
  }

  String readStringReference() {
    return _reader.readStringReference();
  }

  List<String> readStringReferenceList() {
    return _reader.readStringReferenceList();
  }

  DartType? readType() {
    var tag = _reader.readByte();
    if (tag == Tag.NullType) {
      return null;
    } else if (tag == Tag.DynamicType) {
      var type = DynamicTypeImpl.instance;
      return _readAliasElementArguments(type);
    } else if (tag == Tag.FunctionType) {
      var type = _readFunctionType();
      return _readAliasElementArguments(type);
    } else if (tag == Tag.InterfaceType) {
      var element = readElement() as InterfaceElement;
      var typeArguments = _readTypeList();
      var nullability = _readNullability();
      var type = InterfaceTypeImpl(
        element: element,
        typeArguments: typeArguments,
        nullabilitySuffix: nullability,
      );
      return _readAliasElementArguments(type);
    } else if (tag == Tag.InterfaceType_noTypeArguments_none) {
      var element = readElement() as InterfaceElement;
      var type = element.instantiate(
          typeArguments: const <DartType>[],
          nullabilitySuffix: NullabilitySuffix.none);
      return _readAliasElementArguments(type);
    } else if (tag == Tag.InterfaceType_noTypeArguments_question) {
      var element = readElement() as InterfaceElement;
      var type = element.instantiate(
        typeArguments: const <DartType>[],
        nullabilitySuffix: NullabilitySuffix.question,
      );
      return _readAliasElementArguments(type);
    } else if (tag == Tag.InvalidType) {
      var type = InvalidTypeImpl.instance;
      return _readAliasElementArguments(type);
    } else if (tag == Tag.NeverType) {
      var nullability = _readNullability();
      var type = NeverTypeImpl.instance.withNullability(nullability);
      return _readAliasElementArguments(type);
    } else if (tag == Tag.RecordType) {
      var type = _readRecordType();
      return _readAliasElementArguments(type);
    } else if (tag == Tag.TypeParameterType) {
      var element = readElement() as TypeParameterElement;
      var nullability = _readNullability();
      var type = TypeParameterTypeImpl(
        element: element,
        nullabilitySuffix: nullability,
      );
      return _readAliasElementArguments(type);
    } else if (tag == Tag.VoidType) {
      var type = VoidTypeImpl.instance;
      return _readAliasElementArguments(type);
    } else {
      throw UnimplementedError('$tag');
    }
  }

  List<T> readTypedList<T>(T Function() read) {
    return _reader.readTypedList(read);
  }

  int readUInt30() {
    return _reader.readUInt30();
  }

  int readUInt32() {
    return _reader.readUInt32();
  }

  void setOffset(int offset) {
    _reader.offset = offset;
  }

  void _addFormalParameters(List<ParameterElement> parameters) {
    for (var parameter in parameters) {
      _localElements.add(parameter);
    }
  }

  void _addTypeParameters(List<TypeParameterElement> typeParameters) {
    for (var typeParameter in typeParameters) {
      _localElements.add(typeParameter);
    }
  }

  ElementImpl? _readAliasedElement(CompilationUnitElementImpl unitElement) {
    var tag = _reader.readByte();
    if (tag == AliasedElementTag.nothing) {
      return null;
    } else if (tag == AliasedElementTag.genericFunctionElement) {
      var typeParameters = _readTypeParameters(unitElement);
      var formalParameters = _readFormalParameters(unitElement);
      var returnType = readRequiredType();

      _localElements.length -= typeParameters.length;

      return GenericFunctionTypeElementImpl.forOffset(-1)
        ..typeParameters = typeParameters
        ..parameters = formalParameters
        ..returnType = returnType;
    } else {
      throw UnimplementedError('tag: $tag');
    }
  }

  DartType _readAliasElementArguments(DartType type) {
    var aliasElement = _readRawElement();
    if (aliasElement is TypeAliasElement) {
      var aliasArguments = _readTypeList();
      if (type is DynamicType) {
        // TODO(scheglov): add support for `dynamic` aliasing
        return type;
      } else if (type is FunctionType) {
        return FunctionTypeImpl(
          typeFormals: type.typeFormals,
          parameters: type.parameters,
          returnType: type.returnType,
          nullabilitySuffix: type.nullabilitySuffix,
          alias: InstantiatedTypeAliasElementImpl(
            element: aliasElement,
            typeArguments: aliasArguments,
          ),
        );
      } else if (type is InterfaceType) {
        return InterfaceTypeImpl(
          element: type.element,
          typeArguments: type.typeArguments,
          nullabilitySuffix: type.nullabilitySuffix,
          alias: InstantiatedTypeAliasElementImpl(
            element: aliasElement,
            typeArguments: aliasArguments,
          ),
        );
      } else if (type is RecordTypeImpl) {
        return RecordTypeImpl(
          positionalFields: type.positionalFields,
          namedFields: type.namedFields,
          nullabilitySuffix: type.nullabilitySuffix,
          alias: InstantiatedTypeAliasElementImpl(
            element: aliasElement,
            typeArguments: aliasArguments,
          ),
        );
      } else if (type is TypeParameterType) {
        return TypeParameterTypeImpl(
          element: type.element,
          nullabilitySuffix: type.nullabilitySuffix,
          alias: InstantiatedTypeAliasElementImpl(
            element: aliasElement,
            typeArguments: aliasArguments,
          ),
        );
      } else if (type is VoidType) {
        // TODO(scheglov): add support for `void` aliasing
        return type;
      } else {
        throw UnimplementedError('${type.runtimeType}');
      }
    }
    return type;
  }

  List<ElementAnnotationImpl> _readAnnotationList({
    required CompilationUnitElementImpl unitElement,
  }) {
    return readTypedList(() {
      var ast = _readRequiredNode() as AnnotationImpl;
      return ElementAnnotationImpl(unitElement)
        ..annotationAst = ast
        ..element = ast.element;
    });
  }

  List<ParameterElementImpl> _readFormalParameters(
    CompilationUnitElementImpl? unitElement,
  ) {
    return readTypedList(() {
      var kindIndex = _reader.readByte();
      var kind = _formalParameterKind(kindIndex);
      var isDefault = _reader.readBool();
      var hasImplicitType = _reader.readBool();
      var isInitializingFormal = _reader.readBool();
      var typeParameters = _readTypeParameters(unitElement);
      var type = readRequiredType();
      var name = readStringReference();
      if (!isDefault) {
        ParameterElementImpl element;
        if (isInitializingFormal) {
          element = FieldFormalParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          )..type = type;
        } else {
          element = ParameterElementImpl(
            name: name,
            nameOffset: -1,
            parameterKind: kind,
          )..type = type;
        }
        element.hasImplicitType = hasImplicitType;
        element.typeParameters = typeParameters;
        element.parameters = _readFormalParameters(unitElement);
        // TODO(scheglov): reuse for formal parameters
        _localElements.length -= typeParameters.length;
        if (unitElement != null) {
          element.metadata = _readAnnotationList(unitElement: unitElement);
        }
        return element;
      } else {
        var element = DefaultParameterElementImpl(
          name: name,
          nameOffset: -1,
          parameterKind: kind,
        )..type = type;
        element.hasImplicitType = hasImplicitType;
        element.typeParameters = typeParameters;
        element.parameters = _readFormalParameters(unitElement);
        // TODO(scheglov): reuse for formal parameters
        _localElements.length -= typeParameters.length;
        if (unitElement != null) {
          element.metadata = _readAnnotationList(unitElement: unitElement);
        }
        return element;
      }
    });
  }

  // TODO(scheglov): Optimize for write/read of types without type parameters.
  FunctionType _readFunctionType() {
    // TODO(scheglov): reuse for formal parameters
    var typeParameters = _readTypeParameters(null);
    var returnType = readRequiredType();
    var formalParameters = _readFormalParameters(null);

    var nullability = _readNullability();

    _localElements.length -= typeParameters.length;

    return FunctionTypeImpl(
      typeFormals: typeParameters,
      parameters: formalParameters,
      returnType: returnType,
      nullabilitySuffix: nullability,
    );
  }

  InterfaceType _readInterfaceType() {
    return readType() as InterfaceType;
  }

  List<InterfaceType> _readInterfaceTypeList() {
    return readTypedList(_readInterfaceType);
  }

  AnalyzerMacroDiagnostic _readMacroDiagnostic() {
    var kind = readEnum(MacroDiagnosticKind.values);
    switch (kind) {
      case MacroDiagnosticKind.argument:
        return ArgumentMacroDiagnostic(
          annotationIndex: readUInt30(),
          argumentIndex: readUInt30(),
          message: _reader.readStringUtf8(),
        );
      case MacroDiagnosticKind.exception:
        return ExceptionMacroDiagnostic(
          annotationIndex: readUInt30(),
          message: _reader.readStringUtf8(),
          stackTrace: _reader.readStringUtf8(),
        );
      case MacroDiagnosticKind.introspectionCycle:
        return DeclarationsIntrospectionCycleDiagnostic(
          annotationIndex: readUInt30(),
          introspectedElement: readElement() as ElementImpl,
          components: readTypedList(() {
            return DeclarationsIntrospectionCycleComponent(
              element: readElement() as ElementImpl,
              annotationIndex: readUInt30(),
              introspectedElement: readElement() as ElementImpl,
            );
          }),
        );
      case MacroDiagnosticKind.invalidTarget:
        return InvalidMacroTargetDiagnostic(
          annotationIndex: readUInt30(),
          supportedKinds: _reader.readStringUtf8List(),
        );
      case MacroDiagnosticKind.macro:
        return MacroDiagnostic(
          severity: readEnum(macro.Severity.values),
          message: _readMacroDiagnosticMessage(),
          contextMessages: readTypedList(_readMacroDiagnosticMessage),
          correctionMessage: _reader.readOptionalStringUtf8(),
        );
    }
  }

  MacroDiagnosticMessage _readMacroDiagnosticMessage() {
    var message = _reader.readStringUtf8();

    TypeAnnotationLocation readTypeAnnotationLocation() {
      var kind = readEnum(TypeAnnotationLocationKind.values);
      switch (kind) {
        case TypeAnnotationLocationKind.aliasedType:
          var parent = readTypeAnnotationLocation();
          return AliasedTypeLocation(parent);
        case TypeAnnotationLocationKind.element:
          var element = readElement()!;
          return ElementTypeLocation(element);
        case TypeAnnotationLocationKind.extendsClause:
          var parent = readTypeAnnotationLocation();
          return ExtendsClauseTypeLocation(parent);
        case TypeAnnotationLocationKind.formalParameter:
          return FormalParameterTypeLocation(
            readTypeAnnotationLocation(),
            readUInt30(),
          );
        case TypeAnnotationLocationKind.listIndex:
          return ListIndexTypeLocation(
            readTypeAnnotationLocation(),
            readUInt30(),
          );
        case TypeAnnotationLocationKind.recordNamedField:
          return RecordNamedFieldTypeLocation(
            readTypeAnnotationLocation(),
            readUInt30(),
          );
        case TypeAnnotationLocationKind.recordPositionalField:
          return RecordPositionalFieldTypeLocation(
            readTypeAnnotationLocation(),
            readUInt30(),
          );
        case TypeAnnotationLocationKind.returnType:
          var parent = readTypeAnnotationLocation();
          return ReturnTypeLocation(parent);
        case TypeAnnotationLocationKind.variableType:
          var parent = readTypeAnnotationLocation();
          return VariableTypeLocation(parent);
        default:
          throw UnimplementedError('kind: $kind');
      }
    }

    MacroDiagnosticTarget target;
    var targetKind = readEnum(MacroDiagnosticTargetKind.values);
    switch (targetKind) {
      case MacroDiagnosticTargetKind.application:
        target = ApplicationMacroDiagnosticTarget(
          annotationIndex: readUInt30(),
        );
      case MacroDiagnosticTargetKind.element:
        var element = readElement();
        target = ElementMacroDiagnosticTarget(
          element: element as ElementImpl,
        );
      case MacroDiagnosticTargetKind.elementAnnotation:
        var element = readElement();
        target = ElementAnnotationMacroDiagnosticTarget(
          element: element as ElementImpl,
          annotationIndex: readUInt30(),
        );
      case MacroDiagnosticTargetKind.type:
        var location = readTypeAnnotationLocation();
        target = TypeAnnotationMacroDiagnosticTarget(location: location);
    }

    return MacroDiagnosticMessage(
      message: message,
      target: target,
    );
  }

  List<T> _readNodeList<T>() {
    return readTypedList(() {
      return _readRequiredNode() as T;
    });
  }

  NullabilitySuffix _readNullability() {
    var index = _reader.readByte();
    return NullabilitySuffix.values[index];
  }

  ExpressionImpl? _readOptionalExpression() {
    if (_reader.readBool()) {
      return _readRequiredNode() as ExpressionImpl;
    } else {
      return null;
    }
  }

  InterfaceType? _readOptionalInterfaceType() {
    return readType() as InterfaceType?;
  }

  Element? _readRawElement() {
    var index = _reader.readUInt30();

    if ((index & 0x1) == 0x1) {
      return _localElements[index >> 1];
    }

    var referenceIndex = index >> 1;
    var reference = _referenceReader.referenceOfIndex(referenceIndex);

    return _elementFactory.elementOfReference(reference);
  }

  RecordTypeImpl _readRecordType() {
    var positionalFields = readTypedList(() {
      return RecordTypePositionalFieldImpl(
        type: readRequiredType(),
      );
    });

    var namedFields = readTypedList(() {
      return RecordTypeNamedFieldImpl(
        name: _reader.readStringReference(),
        type: readRequiredType(),
      );
    });

    var nullabilitySuffix = _readNullability();

    return RecordTypeImpl(
      positionalFields: positionalFields,
      namedFields: namedFields,
      nullabilitySuffix: nullabilitySuffix,
    );
  }

  AstNode _readRequiredNode() {
    var astReader = AstBinaryReader(reader: this);
    return astReader.readNode();
  }

  List<DartType> _readTypeList() {
    return readTypedList(() {
      return readRequiredType();
    });
  }

  List<TypeParameterElementImpl> _readTypeParameters(
    CompilationUnitElementImpl? unitElement,
  ) {
    var typeParameters = readTypedList(() {
      var name = readStringReference();
      var typeParameter = TypeParameterElementImpl(name, -1);
      _localElements.add(typeParameter);
      return typeParameter;
    });

    for (var typeParameter in typeParameters) {
      typeParameter.bound = readType();
      if (unitElement != null) {
        typeParameter.metadata = _readAnnotationList(unitElement: unitElement);
      }
    }
    return typeParameters;
  }

  static ParameterKind _formalParameterKind(int encoding) {
    if (encoding == Tag.ParameterKindRequiredPositional) {
      return ParameterKind.REQUIRED;
    } else if (encoding == Tag.ParameterKindOptionalPositional) {
      return ParameterKind.POSITIONAL;
    } else if (encoding == Tag.ParameterKindRequiredNamed) {
      return ParameterKind.NAMED_REQUIRED;
    } else if (encoding == Tag.ParameterKindOptionalNamed) {
      return ParameterKind.NAMED;
    } else {
      throw StateError('Unexpected parameter kind encoding: $encoding');
    }
  }
}

class TopLevelVariableElementLinkedData
    extends ElementLinkedData<TopLevelVariableElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  TopLevelVariableElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(TopLevelVariableElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    element.type = reader.readRequiredType();

    var augmentationTarget = reader.readElement();
    if (augmentationTarget is TopLevelVariableElementImpl) {
      augmentationTarget.augmentation = element;
      element.augmentationTarget = augmentationTarget;
    }

    if (element is ConstTopLevelVariableElementImpl) {
      var initializer = reader._readOptionalExpression();
      if (initializer != null) {
        element.constantInitializer = initializer;
        ConstantContextForExpressionImpl(element, initializer);
      }
    }
    applyConstantOffsets?.perform();
  }
}

class TypeAliasElementLinkedData
    extends ElementLinkedData<TypeAliasElementImpl> {
  ApplyConstantOffsets? applyConstantOffsets;

  TypeAliasElementLinkedData({
    required Reference reference,
    required LibraryReader libraryReader,
    required CompilationUnitElementImpl unitElement,
    required int offset,
  }) : super(reference, libraryReader, unitElement, offset);

  @override
  void _clearLinkedDataOnRead(TypeAliasElementImpl element) {
    element.linkedData = null;
  }

  @override
  void _read(element, reader) {
    element.metadata = reader._readAnnotationList(
      unitElement: unitElement,
    );
    element.macroDiagnostics = reader.readMacroDiagnostics();
    _readTypeParameters(reader, element.typeParameters);
    element.aliasedElement = reader._readAliasedElement(unitElement);
    element.aliasedType = reader.readRequiredType();
    applyConstantOffsets?.perform();
  }
}

/// Information that we need to know about each library before reading it,
/// and without reading it.
///
/// Specifically, the [offset] allows us to know the location of each library,
/// so that when we need to read this library, we know where it starts without
/// reading previous libraries.
class _LibraryHeader {
  final Uri uri;
  final int offset;

  /// We don't read class members when reading libraries, by performance
  /// reasons - in many cases only some classes of a library are used. But
  /// we need to know how much data to skip for each class.
  final Uint32List classMembersLengths;

  /// The only (if any) macro generated augmentation code.
  final String? macroGeneratedCode;

  _LibraryHeader({
    required this.uri,
    required this.offset,
    required this.classMembersLengths,
    required this.macroGeneratedCode,
  });
}

class _ReferenceReader {
  final LinkedElementFactory elementFactory;
  final SummaryDataReader _reader;
  late final Uint32List _parents;
  late final Uint32List _names;
  late final List<Reference?> _references;

  _ReferenceReader(this.elementFactory, this._reader, int offset) {
    _reader.offset = offset;
    _parents = _reader.readUInt30List();
    _names = _reader.readUInt30List();
    assert(_parents.length == _names.length);

    _references = List.filled(_names.length, null);
  }

  Reference referenceOfIndex(int index) {
    var reference = _references[index];
    if (reference != null) {
      return reference;
    }

    if (index == 0) {
      reference = elementFactory.rootReference;
      _references[index] = reference;
      return reference;
    }

    var nameIndex = _names[index];
    var name = _reader.stringOfIndex(nameIndex);

    var parentIndex = _parents[index];
    var parent = referenceOfIndex(parentIndex);

    reference = parent.getChild(name);
    _references[index] = reference;

    return reference;
  }
}
