// Copyright (c) 2015, 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.

// This file has been automatically generated.  Please do not edit it manually.
// To regenerate the file, use the SDK script
// "pkg/analyzer/tool/summary/generate.dart $IDL_FILE_PATH",
// or "pkg/analyzer/tool/generate_files" for the analyzer package IDL/sources.

// The generator sometimes generates unnecessary 'this' references.
// ignore_for_file: unnecessary_this

library analyzer.src.summary.format;

import 'dart:convert' as convert;

import 'package:analyzer/src/summary/api_signature.dart' as api_sig;
import 'package:analyzer/src/summary/flat_buffers.dart' as fb;
import 'package:analyzer/src/summary/idl.dart' as idl;

class _AvailableDeclarationKindReader
    extends fb.Reader<idl.AvailableDeclarationKind> {
  const _AvailableDeclarationKindReader() : super();

  @override
  int get size => 1;

  @override
  idl.AvailableDeclarationKind read(fb.BufferContext bc, int offset) {
    int index = const fb.Uint8Reader().read(bc, offset);
    return index < idl.AvailableDeclarationKind.values.length
        ? idl.AvailableDeclarationKind.values[index]
        : idl.AvailableDeclarationKind.CLASS;
  }
}

class _IndexRelationKindReader extends fb.Reader<idl.IndexRelationKind> {
  const _IndexRelationKindReader() : super();

  @override
  int get size => 1;

  @override
  idl.IndexRelationKind read(fb.BufferContext bc, int offset) {
    int index = const fb.Uint8Reader().read(bc, offset);
    return index < idl.IndexRelationKind.values.length
        ? idl.IndexRelationKind.values[index]
        : idl.IndexRelationKind.IS_ANCESTOR_OF;
  }
}

class _IndexSyntheticElementKindReader
    extends fb.Reader<idl.IndexSyntheticElementKind> {
  const _IndexSyntheticElementKindReader() : super();

  @override
  int get size => 1;

  @override
  idl.IndexSyntheticElementKind read(fb.BufferContext bc, int offset) {
    int index = const fb.Uint8Reader().read(bc, offset);
    return index < idl.IndexSyntheticElementKind.values.length
        ? idl.IndexSyntheticElementKind.values[index]
        : idl.IndexSyntheticElementKind.notSynthetic;
  }
}

class AnalysisDriverExceptionContextBuilder extends Object
    with _AnalysisDriverExceptionContextMixin
    implements idl.AnalysisDriverExceptionContext {
  String? _exception;
  List<AnalysisDriverExceptionFileBuilder>? _files;
  String? _path;
  String? _stackTrace;

  @override
  String get exception => _exception ??= '';

  /// The exception string.
  set exception(String value) {
    this._exception = value;
  }

  @override
  List<AnalysisDriverExceptionFileBuilder> get files =>
      _files ??= <AnalysisDriverExceptionFileBuilder>[];

  /// The state of files when the exception happened.
  set files(List<AnalysisDriverExceptionFileBuilder> value) {
    this._files = value;
  }

  @override
  String get path => _path ??= '';

  /// The path of the file being analyzed when the exception happened.
  set path(String value) {
    this._path = value;
  }

  @override
  String get stackTrace => _stackTrace ??= '';

  /// The exception stack trace string.
  set stackTrace(String value) {
    this._stackTrace = value;
  }

  AnalysisDriverExceptionContextBuilder(
      {String? exception,
      List<AnalysisDriverExceptionFileBuilder>? files,
      String? path,
      String? stackTrace})
      : _exception = exception,
        _files = files,
        _path = path,
        _stackTrace = stackTrace;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _files?.forEach((b) => b.flushInformative());
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addString(this._path ?? '');
    signatureSink.addString(this._exception ?? '');
    signatureSink.addString(this._stackTrace ?? '');
    var files = this._files;
    if (files == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(files.length);
      for (var x in files) {
        x.collectApiSignature(signatureSink);
      }
    }
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "ADEC");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_exception;
    fb.Offset? offset_files;
    fb.Offset? offset_path;
    fb.Offset? offset_stackTrace;
    var exception = _exception;
    if (exception != null) {
      offset_exception = fbBuilder.writeString(exception);
    }
    var files = _files;
    if (!(files == null || files.isEmpty)) {
      offset_files =
          fbBuilder.writeList(files.map((b) => b.finish(fbBuilder)).toList());
    }
    var path = _path;
    if (path != null) {
      offset_path = fbBuilder.writeString(path);
    }
    var stackTrace = _stackTrace;
    if (stackTrace != null) {
      offset_stackTrace = fbBuilder.writeString(stackTrace);
    }
    fbBuilder.startTable();
    if (offset_exception != null) {
      fbBuilder.addOffset(1, offset_exception);
    }
    if (offset_files != null) {
      fbBuilder.addOffset(3, offset_files);
    }
    if (offset_path != null) {
      fbBuilder.addOffset(0, offset_path);
    }
    if (offset_stackTrace != null) {
      fbBuilder.addOffset(2, offset_stackTrace);
    }
    return fbBuilder.endTable();
  }
}

idl.AnalysisDriverExceptionContext readAnalysisDriverExceptionContext(
    List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _AnalysisDriverExceptionContextReader().read(rootRef, 0);
}

class _AnalysisDriverExceptionContextReader
    extends fb.TableReader<_AnalysisDriverExceptionContextImpl> {
  const _AnalysisDriverExceptionContextReader();

  @override
  _AnalysisDriverExceptionContextImpl createObject(
          fb.BufferContext bc, int offset) =>
      _AnalysisDriverExceptionContextImpl(bc, offset);
}

class _AnalysisDriverExceptionContextImpl extends Object
    with _AnalysisDriverExceptionContextMixin
    implements idl.AnalysisDriverExceptionContext {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AnalysisDriverExceptionContextImpl(this._bc, this._bcOffset);

  String? _exception;
  List<idl.AnalysisDriverExceptionFile>? _files;
  String? _path;
  String? _stackTrace;

  @override
  String get exception {
    return _exception ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
  }

  @override
  List<idl.AnalysisDriverExceptionFile> get files {
    return _files ??= const fb.ListReader<idl.AnalysisDriverExceptionFile>(
            _AnalysisDriverExceptionFileReader())
        .vTableGet(
            _bc, _bcOffset, 3, const <idl.AnalysisDriverExceptionFile>[]);
  }

  @override
  String get path {
    return _path ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
  }

  @override
  String get stackTrace {
    return _stackTrace ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
  }
}

abstract class _AnalysisDriverExceptionContextMixin
    implements idl.AnalysisDriverExceptionContext {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_exception = exception;
    if (local_exception != '') {
      _result["exception"] = local_exception;
    }
    var local_files = files;
    if (local_files.isNotEmpty) {
      _result["files"] = local_files.map((_value) => _value.toJson()).toList();
    }
    var local_path = path;
    if (local_path != '') {
      _result["path"] = local_path;
    }
    var local_stackTrace = stackTrace;
    if (local_stackTrace != '') {
      _result["stackTrace"] = local_stackTrace;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "exception": exception,
        "files": files,
        "path": path,
        "stackTrace": stackTrace,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AnalysisDriverExceptionFileBuilder extends Object
    with _AnalysisDriverExceptionFileMixin
    implements idl.AnalysisDriverExceptionFile {
  String? _content;
  String? _path;

  @override
  String get content => _content ??= '';

  /// The content of the file.
  set content(String value) {
    this._content = value;
  }

  @override
  String get path => _path ??= '';

  /// The path of the file.
  set path(String value) {
    this._path = value;
  }

  AnalysisDriverExceptionFileBuilder({String? content, String? path})
      : _content = content,
        _path = path;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addString(this._path ?? '');
    signatureSink.addString(this._content ?? '');
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_content;
    fb.Offset? offset_path;
    var content = _content;
    if (content != null) {
      offset_content = fbBuilder.writeString(content);
    }
    var path = _path;
    if (path != null) {
      offset_path = fbBuilder.writeString(path);
    }
    fbBuilder.startTable();
    if (offset_content != null) {
      fbBuilder.addOffset(1, offset_content);
    }
    if (offset_path != null) {
      fbBuilder.addOffset(0, offset_path);
    }
    return fbBuilder.endTable();
  }
}

class _AnalysisDriverExceptionFileReader
    extends fb.TableReader<_AnalysisDriverExceptionFileImpl> {
  const _AnalysisDriverExceptionFileReader();

  @override
  _AnalysisDriverExceptionFileImpl createObject(
          fb.BufferContext bc, int offset) =>
      _AnalysisDriverExceptionFileImpl(bc, offset);
}

class _AnalysisDriverExceptionFileImpl extends Object
    with _AnalysisDriverExceptionFileMixin
    implements idl.AnalysisDriverExceptionFile {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AnalysisDriverExceptionFileImpl(this._bc, this._bcOffset);

  String? _content;
  String? _path;

  @override
  String get content {
    return _content ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
  }

  @override
  String get path {
    return _path ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
  }
}

abstract class _AnalysisDriverExceptionFileMixin
    implements idl.AnalysisDriverExceptionFile {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_content = content;
    if (local_content != '') {
      _result["content"] = local_content;
    }
    var local_path = path;
    if (local_path != '') {
      _result["path"] = local_path;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "content": content,
        "path": path,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AnalysisDriverResolvedUnitBuilder extends Object
    with _AnalysisDriverResolvedUnitMixin
    implements idl.AnalysisDriverResolvedUnit {
  List<AnalysisDriverUnitErrorBuilder>? _errors;
  AnalysisDriverUnitIndexBuilder? _index;

  @override
  List<AnalysisDriverUnitErrorBuilder> get errors =>
      _errors ??= <AnalysisDriverUnitErrorBuilder>[];

  /// The full list of analysis errors, both syntactic and semantic.
  set errors(List<AnalysisDriverUnitErrorBuilder> value) {
    this._errors = value;
  }

  @override
  AnalysisDriverUnitIndexBuilder? get index => _index;

  /// The index of the unit.
  set index(AnalysisDriverUnitIndexBuilder? value) {
    this._index = value;
  }

  AnalysisDriverResolvedUnitBuilder(
      {List<AnalysisDriverUnitErrorBuilder>? errors,
      AnalysisDriverUnitIndexBuilder? index})
      : _errors = errors,
        _index = index;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _errors?.forEach((b) => b.flushInformative());
    _index?.flushInformative();
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var errors = this._errors;
    if (errors == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(errors.length);
      for (var x in errors) {
        x.collectApiSignature(signatureSink);
      }
    }
    signatureSink.addBool(this._index != null);
    this._index?.collectApiSignature(signatureSink);
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "ADRU");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_errors;
    fb.Offset? offset_index;
    var errors = _errors;
    if (!(errors == null || errors.isEmpty)) {
      offset_errors =
          fbBuilder.writeList(errors.map((b) => b.finish(fbBuilder)).toList());
    }
    var index = _index;
    if (index != null) {
      offset_index = index.finish(fbBuilder);
    }
    fbBuilder.startTable();
    if (offset_errors != null) {
      fbBuilder.addOffset(0, offset_errors);
    }
    if (offset_index != null) {
      fbBuilder.addOffset(1, offset_index);
    }
    return fbBuilder.endTable();
  }
}

idl.AnalysisDriverResolvedUnit readAnalysisDriverResolvedUnit(
    List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _AnalysisDriverResolvedUnitReader().read(rootRef, 0);
}

class _AnalysisDriverResolvedUnitReader
    extends fb.TableReader<_AnalysisDriverResolvedUnitImpl> {
  const _AnalysisDriverResolvedUnitReader();

  @override
  _AnalysisDriverResolvedUnitImpl createObject(
          fb.BufferContext bc, int offset) =>
      _AnalysisDriverResolvedUnitImpl(bc, offset);
}

class _AnalysisDriverResolvedUnitImpl extends Object
    with _AnalysisDriverResolvedUnitMixin
    implements idl.AnalysisDriverResolvedUnit {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AnalysisDriverResolvedUnitImpl(this._bc, this._bcOffset);

  List<idl.AnalysisDriverUnitError>? _errors;
  idl.AnalysisDriverUnitIndex? _index;

  @override
  List<idl.AnalysisDriverUnitError> get errors {
    return _errors ??= const fb.ListReader<idl.AnalysisDriverUnitError>(
            _AnalysisDriverUnitErrorReader())
        .vTableGet(_bc, _bcOffset, 0, const <idl.AnalysisDriverUnitError>[]);
  }

  @override
  idl.AnalysisDriverUnitIndex? get index {
    return _index ??= const _AnalysisDriverUnitIndexReader()
        .vTableGetOrNull(_bc, _bcOffset, 1);
  }
}

abstract class _AnalysisDriverResolvedUnitMixin
    implements idl.AnalysisDriverResolvedUnit {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_errors = errors;
    if (local_errors.isNotEmpty) {
      _result["errors"] =
          local_errors.map((_value) => _value.toJson()).toList();
    }
    var local_index = index;
    if (local_index != null) {
      _result["index"] = local_index.toJson();
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "errors": errors,
        "index": index,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AnalysisDriverSubtypeBuilder extends Object
    with _AnalysisDriverSubtypeMixin
    implements idl.AnalysisDriverSubtype {
  List<int>? _members;
  int? _name;

  @override
  List<int> get members => _members ??= <int>[];

  /// The names of defined instance members.
  /// They are indexes into [AnalysisDriverUnitError.strings] list.
  /// The list is sorted in ascending order.
  set members(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._members = value;
  }

  @override
  int get name => _name ??= 0;

  /// The name of the class.
  /// It is an index into [AnalysisDriverUnitError.strings] list.
  set name(int value) {
    assert(value >= 0);
    this._name = value;
  }

  AnalysisDriverSubtypeBuilder({List<int>? members, int? name})
      : _members = members,
        _name = name;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addInt(this._name ?? 0);
    var members = this._members;
    if (members == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(members.length);
      for (var x in members) {
        signatureSink.addInt(x);
      }
    }
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_members;
    var members = _members;
    if (!(members == null || members.isEmpty)) {
      offset_members = fbBuilder.writeListUint32(members);
    }
    fbBuilder.startTable();
    if (offset_members != null) {
      fbBuilder.addOffset(1, offset_members);
    }
    fbBuilder.addUint32(0, _name, 0);
    return fbBuilder.endTable();
  }
}

class _AnalysisDriverSubtypeReader
    extends fb.TableReader<_AnalysisDriverSubtypeImpl> {
  const _AnalysisDriverSubtypeReader();

  @override
  _AnalysisDriverSubtypeImpl createObject(fb.BufferContext bc, int offset) =>
      _AnalysisDriverSubtypeImpl(bc, offset);
}

class _AnalysisDriverSubtypeImpl extends Object
    with _AnalysisDriverSubtypeMixin
    implements idl.AnalysisDriverSubtype {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AnalysisDriverSubtypeImpl(this._bc, this._bcOffset);

  List<int>? _members;
  int? _name;

  @override
  List<int> get members {
    return _members ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 1, const <int>[]);
  }

  @override
  int get name {
    return _name ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
  }
}

abstract class _AnalysisDriverSubtypeMixin
    implements idl.AnalysisDriverSubtype {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_members = members;
    if (local_members.isNotEmpty) {
      _result["members"] = local_members;
    }
    var local_name = name;
    if (local_name != 0) {
      _result["name"] = local_name;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "members": members,
        "name": name,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AnalysisDriverUnitErrorBuilder extends Object
    with _AnalysisDriverUnitErrorMixin
    implements idl.AnalysisDriverUnitError {
  List<DiagnosticMessageBuilder>? _contextMessages;
  String? _correction;
  int? _length;
  String? _message;
  int? _offset;
  String? _uniqueName;

  @override
  List<DiagnosticMessageBuilder> get contextMessages =>
      _contextMessages ??= <DiagnosticMessageBuilder>[];

  /// The context messages associated with the error.
  set contextMessages(List<DiagnosticMessageBuilder> value) {
    this._contextMessages = value;
  }

  @override
  String get correction => _correction ??= '';

  /// The optional correction hint for the error.
  set correction(String value) {
    this._correction = value;
  }

  @override
  int get length => _length ??= 0;

  /// The length of the error in the file.
  set length(int value) {
    assert(value >= 0);
    this._length = value;
  }

  @override
  String get message => _message ??= '';

  /// The message of the error.
  set message(String value) {
    this._message = value;
  }

  @override
  int get offset => _offset ??= 0;

  /// The offset from the beginning of the file.
  set offset(int value) {
    assert(value >= 0);
    this._offset = value;
  }

  @override
  String get uniqueName => _uniqueName ??= '';

  /// The unique name of the error code.
  set uniqueName(String value) {
    this._uniqueName = value;
  }

  AnalysisDriverUnitErrorBuilder(
      {List<DiagnosticMessageBuilder>? contextMessages,
      String? correction,
      int? length,
      String? message,
      int? offset,
      String? uniqueName})
      : _contextMessages = contextMessages,
        _correction = correction,
        _length = length,
        _message = message,
        _offset = offset,
        _uniqueName = uniqueName;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _contextMessages?.forEach((b) => b.flushInformative());
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addInt(this._offset ?? 0);
    signatureSink.addInt(this._length ?? 0);
    signatureSink.addString(this._uniqueName ?? '');
    signatureSink.addString(this._message ?? '');
    signatureSink.addString(this._correction ?? '');
    var contextMessages = this._contextMessages;
    if (contextMessages == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(contextMessages.length);
      for (var x in contextMessages) {
        x.collectApiSignature(signatureSink);
      }
    }
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_contextMessages;
    fb.Offset? offset_correction;
    fb.Offset? offset_message;
    fb.Offset? offset_uniqueName;
    var contextMessages = _contextMessages;
    if (!(contextMessages == null || contextMessages.isEmpty)) {
      offset_contextMessages = fbBuilder
          .writeList(contextMessages.map((b) => b.finish(fbBuilder)).toList());
    }
    var correction = _correction;
    if (correction != null) {
      offset_correction = fbBuilder.writeString(correction);
    }
    var message = _message;
    if (message != null) {
      offset_message = fbBuilder.writeString(message);
    }
    var uniqueName = _uniqueName;
    if (uniqueName != null) {
      offset_uniqueName = fbBuilder.writeString(uniqueName);
    }
    fbBuilder.startTable();
    if (offset_contextMessages != null) {
      fbBuilder.addOffset(5, offset_contextMessages);
    }
    if (offset_correction != null) {
      fbBuilder.addOffset(4, offset_correction);
    }
    fbBuilder.addUint32(1, _length, 0);
    if (offset_message != null) {
      fbBuilder.addOffset(3, offset_message);
    }
    fbBuilder.addUint32(0, _offset, 0);
    if (offset_uniqueName != null) {
      fbBuilder.addOffset(2, offset_uniqueName);
    }
    return fbBuilder.endTable();
  }
}

class _AnalysisDriverUnitErrorReader
    extends fb.TableReader<_AnalysisDriverUnitErrorImpl> {
  const _AnalysisDriverUnitErrorReader();

  @override
  _AnalysisDriverUnitErrorImpl createObject(fb.BufferContext bc, int offset) =>
      _AnalysisDriverUnitErrorImpl(bc, offset);
}

class _AnalysisDriverUnitErrorImpl extends Object
    with _AnalysisDriverUnitErrorMixin
    implements idl.AnalysisDriverUnitError {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AnalysisDriverUnitErrorImpl(this._bc, this._bcOffset);

  List<idl.DiagnosticMessage>? _contextMessages;
  String? _correction;
  int? _length;
  String? _message;
  int? _offset;
  String? _uniqueName;

  @override
  List<idl.DiagnosticMessage> get contextMessages {
    return _contextMessages ??=
        const fb.ListReader<idl.DiagnosticMessage>(_DiagnosticMessageReader())
            .vTableGet(_bc, _bcOffset, 5, const <idl.DiagnosticMessage>[]);
  }

  @override
  String get correction {
    return _correction ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 4, '');
  }

  @override
  int get length {
    return _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
  }

  @override
  String get message {
    return _message ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
  }

  @override
  int get offset {
    return _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
  }

  @override
  String get uniqueName {
    return _uniqueName ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
  }
}

abstract class _AnalysisDriverUnitErrorMixin
    implements idl.AnalysisDriverUnitError {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_contextMessages = contextMessages;
    if (local_contextMessages.isNotEmpty) {
      _result["contextMessages"] =
          local_contextMessages.map((_value) => _value.toJson()).toList();
    }
    var local_correction = correction;
    if (local_correction != '') {
      _result["correction"] = local_correction;
    }
    var local_length = length;
    if (local_length != 0) {
      _result["length"] = local_length;
    }
    var local_message = message;
    if (local_message != '') {
      _result["message"] = local_message;
    }
    var local_offset = offset;
    if (local_offset != 0) {
      _result["offset"] = local_offset;
    }
    var local_uniqueName = uniqueName;
    if (local_uniqueName != '') {
      _result["uniqueName"] = local_uniqueName;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "contextMessages": contextMessages,
        "correction": correction,
        "length": length,
        "message": message,
        "offset": offset,
        "uniqueName": uniqueName,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AnalysisDriverUnitIndexBuilder extends Object
    with _AnalysisDriverUnitIndexMixin
    implements idl.AnalysisDriverUnitIndex {
  List<idl.IndexSyntheticElementKind>? _elementKinds;
  List<int>? _elementNameClassMemberIds;
  List<int>? _elementNameParameterIds;
  List<int>? _elementNameUnitMemberIds;
  List<int>? _elementUnits;
  int? _nullStringId;
  List<String>? _strings;
  List<AnalysisDriverSubtypeBuilder>? _subtypes;
  List<int>? _supertypes;
  List<int>? _unitLibraryUris;
  List<int>? _unitUnitUris;
  List<bool>? _usedElementIsQualifiedFlags;
  List<idl.IndexRelationKind>? _usedElementKinds;
  List<int>? _usedElementLengths;
  List<int>? _usedElementOffsets;
  List<int>? _usedElements;
  List<bool>? _usedNameIsQualifiedFlags;
  List<idl.IndexRelationKind>? _usedNameKinds;
  List<int>? _usedNameOffsets;
  List<int>? _usedNames;

  @override
  List<idl.IndexSyntheticElementKind> get elementKinds =>
      _elementKinds ??= <idl.IndexSyntheticElementKind>[];

  /// Each item of this list corresponds to a unique referenced element.  It is
  /// the kind of the synthetic element.
  set elementKinds(List<idl.IndexSyntheticElementKind> value) {
    this._elementKinds = value;
  }

  @override
  List<int> get elementNameClassMemberIds =>
      _elementNameClassMemberIds ??= <int>[];

  /// Each item of this list corresponds to a unique referenced element.  It is
  /// the identifier of the class member element name, or `null` if the element
  /// is a top-level element.  The list is sorted in ascending order, so that
  /// the client can quickly check whether an element is referenced in this
  /// index.
  set elementNameClassMemberIds(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._elementNameClassMemberIds = value;
  }

  @override
  List<int> get elementNameParameterIds => _elementNameParameterIds ??= <int>[];

  /// Each item of this list corresponds to a unique referenced element.  It is
  /// the identifier of the named parameter name, or `null` if the element is
  /// not a named parameter.  The list is sorted in ascending order, so that the
  /// client can quickly check whether an element is referenced in this index.
  set elementNameParameterIds(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._elementNameParameterIds = value;
  }

  @override
  List<int> get elementNameUnitMemberIds =>
      _elementNameUnitMemberIds ??= <int>[];

  /// Each item of this list corresponds to a unique referenced element.  It is
  /// the identifier of the top-level element name, or `null` if the element is
  /// the unit.  The list is sorted in ascending order, so that the client can
  /// quickly check whether an element is referenced in this index.
  set elementNameUnitMemberIds(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._elementNameUnitMemberIds = value;
  }

  @override
  List<int> get elementUnits => _elementUnits ??= <int>[];

  /// Each item of this list corresponds to a unique referenced element.  It is
  /// the index into [unitLibraryUris] and [unitUnitUris] for the library
  /// specific unit where the element is declared.
  set elementUnits(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._elementUnits = value;
  }

  @override
  int get nullStringId => _nullStringId ??= 0;

  /// Identifier of the null string in [strings].
  set nullStringId(int value) {
    assert(value >= 0);
    this._nullStringId = value;
  }

  @override
  List<String> get strings => _strings ??= <String>[];

  /// List of unique element strings used in this index.  The list is sorted in
  /// ascending order, so that the client can quickly check the presence of a
  /// string in this index.
  set strings(List<String> value) {
    this._strings = value;
  }

  @override
  List<AnalysisDriverSubtypeBuilder> get subtypes =>
      _subtypes ??= <AnalysisDriverSubtypeBuilder>[];

  /// The list of classes declared in the unit.
  set subtypes(List<AnalysisDriverSubtypeBuilder> value) {
    this._subtypes = value;
  }

  @override
  List<int> get supertypes => _supertypes ??= <int>[];

  /// The identifiers of supertypes of elements at corresponding indexes
  /// in [subtypes].  They are indexes into [strings] list. The list is sorted
  /// in ascending order.  There might be more than one element with the same
  /// value if there is more than one subtype of this supertype.
  set supertypes(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._supertypes = value;
  }

  @override
  List<int> get unitLibraryUris => _unitLibraryUris ??= <int>[];

  /// Each item of this list corresponds to the library URI of a unique library
  /// specific unit referenced in the index.  It is an index into [strings]
  /// list.
  set unitLibraryUris(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._unitLibraryUris = value;
  }

  @override
  List<int> get unitUnitUris => _unitUnitUris ??= <int>[];

  /// Each item of this list corresponds to the unit URI of a unique library
  /// specific unit referenced in the index.  It is an index into [strings]
  /// list.
  set unitUnitUris(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._unitUnitUris = value;
  }

  @override
  List<bool> get usedElementIsQualifiedFlags =>
      _usedElementIsQualifiedFlags ??= <bool>[];

  /// Each item of this list is the `true` if the corresponding element usage
  /// is qualified with some prefix.
  set usedElementIsQualifiedFlags(List<bool> value) {
    this._usedElementIsQualifiedFlags = value;
  }

  @override
  List<idl.IndexRelationKind> get usedElementKinds =>
      _usedElementKinds ??= <idl.IndexRelationKind>[];

  /// Each item of this list is the kind of the element usage.
  set usedElementKinds(List<idl.IndexRelationKind> value) {
    this._usedElementKinds = value;
  }

  @override
  List<int> get usedElementLengths => _usedElementLengths ??= <int>[];

  /// Each item of this list is the length of the element usage.
  set usedElementLengths(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._usedElementLengths = value;
  }

  @override
  List<int> get usedElementOffsets => _usedElementOffsets ??= <int>[];

  /// Each item of this list is the offset of the element usage relative to the
  /// beginning of the file.
  set usedElementOffsets(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._usedElementOffsets = value;
  }

  @override
  List<int> get usedElements => _usedElements ??= <int>[];

  /// Each item of this list is the index into [elementUnits],
  /// [elementNameUnitMemberIds], [elementNameClassMemberIds] and
  /// [elementNameParameterIds].  The list is sorted in ascending order, so
  /// that the client can quickly find element references in this index.
  set usedElements(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._usedElements = value;
  }

  @override
  List<bool> get usedNameIsQualifiedFlags =>
      _usedNameIsQualifiedFlags ??= <bool>[];

  /// Each item of this list is the `true` if the corresponding name usage
  /// is qualified with some prefix.
  set usedNameIsQualifiedFlags(List<bool> value) {
    this._usedNameIsQualifiedFlags = value;
  }

  @override
  List<idl.IndexRelationKind> get usedNameKinds =>
      _usedNameKinds ??= <idl.IndexRelationKind>[];

  /// Each item of this list is the kind of the name usage.
  set usedNameKinds(List<idl.IndexRelationKind> value) {
    this._usedNameKinds = value;
  }

  @override
  List<int> get usedNameOffsets => _usedNameOffsets ??= <int>[];

  /// Each item of this list is the offset of the name usage relative to the
  /// beginning of the file.
  set usedNameOffsets(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._usedNameOffsets = value;
  }

  @override
  List<int> get usedNames => _usedNames ??= <int>[];

  /// Each item of this list is the index into [strings] for a used name.  The
  /// list is sorted in ascending order, so that the client can quickly find
  /// whether a name is used in this index.
  set usedNames(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._usedNames = value;
  }

  AnalysisDriverUnitIndexBuilder(
      {List<idl.IndexSyntheticElementKind>? elementKinds,
      List<int>? elementNameClassMemberIds,
      List<int>? elementNameParameterIds,
      List<int>? elementNameUnitMemberIds,
      List<int>? elementUnits,
      int? nullStringId,
      List<String>? strings,
      List<AnalysisDriverSubtypeBuilder>? subtypes,
      List<int>? supertypes,
      List<int>? unitLibraryUris,
      List<int>? unitUnitUris,
      List<bool>? usedElementIsQualifiedFlags,
      List<idl.IndexRelationKind>? usedElementKinds,
      List<int>? usedElementLengths,
      List<int>? usedElementOffsets,
      List<int>? usedElements,
      List<bool>? usedNameIsQualifiedFlags,
      List<idl.IndexRelationKind>? usedNameKinds,
      List<int>? usedNameOffsets,
      List<int>? usedNames})
      : _elementKinds = elementKinds,
        _elementNameClassMemberIds = elementNameClassMemberIds,
        _elementNameParameterIds = elementNameParameterIds,
        _elementNameUnitMemberIds = elementNameUnitMemberIds,
        _elementUnits = elementUnits,
        _nullStringId = nullStringId,
        _strings = strings,
        _subtypes = subtypes,
        _supertypes = supertypes,
        _unitLibraryUris = unitLibraryUris,
        _unitUnitUris = unitUnitUris,
        _usedElementIsQualifiedFlags = usedElementIsQualifiedFlags,
        _usedElementKinds = usedElementKinds,
        _usedElementLengths = usedElementLengths,
        _usedElementOffsets = usedElementOffsets,
        _usedElements = usedElements,
        _usedNameIsQualifiedFlags = usedNameIsQualifiedFlags,
        _usedNameKinds = usedNameKinds,
        _usedNameOffsets = usedNameOffsets,
        _usedNames = usedNames;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _subtypes?.forEach((b) => b.flushInformative());
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var strings = this._strings;
    if (strings == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(strings.length);
      for (var x in strings) {
        signatureSink.addString(x);
      }
    }
    signatureSink.addInt(this._nullStringId ?? 0);
    var unitLibraryUris = this._unitLibraryUris;
    if (unitLibraryUris == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(unitLibraryUris.length);
      for (var x in unitLibraryUris) {
        signatureSink.addInt(x);
      }
    }
    var unitUnitUris = this._unitUnitUris;
    if (unitUnitUris == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(unitUnitUris.length);
      for (var x in unitUnitUris) {
        signatureSink.addInt(x);
      }
    }
    var elementKinds = this._elementKinds;
    if (elementKinds == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(elementKinds.length);
      for (var x in elementKinds) {
        signatureSink.addInt(x.index);
      }
    }
    var elementUnits = this._elementUnits;
    if (elementUnits == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(elementUnits.length);
      for (var x in elementUnits) {
        signatureSink.addInt(x);
      }
    }
    var elementNameUnitMemberIds = this._elementNameUnitMemberIds;
    if (elementNameUnitMemberIds == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(elementNameUnitMemberIds.length);
      for (var x in elementNameUnitMemberIds) {
        signatureSink.addInt(x);
      }
    }
    var elementNameClassMemberIds = this._elementNameClassMemberIds;
    if (elementNameClassMemberIds == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(elementNameClassMemberIds.length);
      for (var x in elementNameClassMemberIds) {
        signatureSink.addInt(x);
      }
    }
    var elementNameParameterIds = this._elementNameParameterIds;
    if (elementNameParameterIds == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(elementNameParameterIds.length);
      for (var x in elementNameParameterIds) {
        signatureSink.addInt(x);
      }
    }
    var usedElements = this._usedElements;
    if (usedElements == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedElements.length);
      for (var x in usedElements) {
        signatureSink.addInt(x);
      }
    }
    var usedElementKinds = this._usedElementKinds;
    if (usedElementKinds == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedElementKinds.length);
      for (var x in usedElementKinds) {
        signatureSink.addInt(x.index);
      }
    }
    var usedElementOffsets = this._usedElementOffsets;
    if (usedElementOffsets == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedElementOffsets.length);
      for (var x in usedElementOffsets) {
        signatureSink.addInt(x);
      }
    }
    var usedElementLengths = this._usedElementLengths;
    if (usedElementLengths == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedElementLengths.length);
      for (var x in usedElementLengths) {
        signatureSink.addInt(x);
      }
    }
    var usedElementIsQualifiedFlags = this._usedElementIsQualifiedFlags;
    if (usedElementIsQualifiedFlags == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedElementIsQualifiedFlags.length);
      for (var x in usedElementIsQualifiedFlags) {
        signatureSink.addBool(x);
      }
    }
    var usedNames = this._usedNames;
    if (usedNames == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedNames.length);
      for (var x in usedNames) {
        signatureSink.addInt(x);
      }
    }
    var usedNameKinds = this._usedNameKinds;
    if (usedNameKinds == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedNameKinds.length);
      for (var x in usedNameKinds) {
        signatureSink.addInt(x.index);
      }
    }
    var usedNameOffsets = this._usedNameOffsets;
    if (usedNameOffsets == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedNameOffsets.length);
      for (var x in usedNameOffsets) {
        signatureSink.addInt(x);
      }
    }
    var usedNameIsQualifiedFlags = this._usedNameIsQualifiedFlags;
    if (usedNameIsQualifiedFlags == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(usedNameIsQualifiedFlags.length);
      for (var x in usedNameIsQualifiedFlags) {
        signatureSink.addBool(x);
      }
    }
    var supertypes = this._supertypes;
    if (supertypes == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(supertypes.length);
      for (var x in supertypes) {
        signatureSink.addInt(x);
      }
    }
    var subtypes = this._subtypes;
    if (subtypes == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(subtypes.length);
      for (var x in subtypes) {
        x.collectApiSignature(signatureSink);
      }
    }
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "ADUI");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_elementKinds;
    fb.Offset? offset_elementNameClassMemberIds;
    fb.Offset? offset_elementNameParameterIds;
    fb.Offset? offset_elementNameUnitMemberIds;
    fb.Offset? offset_elementUnits;
    fb.Offset? offset_strings;
    fb.Offset? offset_subtypes;
    fb.Offset? offset_supertypes;
    fb.Offset? offset_unitLibraryUris;
    fb.Offset? offset_unitUnitUris;
    fb.Offset? offset_usedElementIsQualifiedFlags;
    fb.Offset? offset_usedElementKinds;
    fb.Offset? offset_usedElementLengths;
    fb.Offset? offset_usedElementOffsets;
    fb.Offset? offset_usedElements;
    fb.Offset? offset_usedNameIsQualifiedFlags;
    fb.Offset? offset_usedNameKinds;
    fb.Offset? offset_usedNameOffsets;
    fb.Offset? offset_usedNames;
    var elementKinds = _elementKinds;
    if (!(elementKinds == null || elementKinds.isEmpty)) {
      offset_elementKinds =
          fbBuilder.writeListUint8(elementKinds.map((b) => b.index).toList());
    }
    var elementNameClassMemberIds = _elementNameClassMemberIds;
    if (!(elementNameClassMemberIds == null ||
        elementNameClassMemberIds.isEmpty)) {
      offset_elementNameClassMemberIds =
          fbBuilder.writeListUint32(elementNameClassMemberIds);
    }
    var elementNameParameterIds = _elementNameParameterIds;
    if (!(elementNameParameterIds == null || elementNameParameterIds.isEmpty)) {
      offset_elementNameParameterIds =
          fbBuilder.writeListUint32(elementNameParameterIds);
    }
    var elementNameUnitMemberIds = _elementNameUnitMemberIds;
    if (!(elementNameUnitMemberIds == null ||
        elementNameUnitMemberIds.isEmpty)) {
      offset_elementNameUnitMemberIds =
          fbBuilder.writeListUint32(elementNameUnitMemberIds);
    }
    var elementUnits = _elementUnits;
    if (!(elementUnits == null || elementUnits.isEmpty)) {
      offset_elementUnits = fbBuilder.writeListUint32(elementUnits);
    }
    var strings = _strings;
    if (!(strings == null || strings.isEmpty)) {
      offset_strings = fbBuilder
          .writeList(strings.map((b) => fbBuilder.writeString(b)).toList());
    }
    var subtypes = _subtypes;
    if (!(subtypes == null || subtypes.isEmpty)) {
      offset_subtypes = fbBuilder
          .writeList(subtypes.map((b) => b.finish(fbBuilder)).toList());
    }
    var supertypes = _supertypes;
    if (!(supertypes == null || supertypes.isEmpty)) {
      offset_supertypes = fbBuilder.writeListUint32(supertypes);
    }
    var unitLibraryUris = _unitLibraryUris;
    if (!(unitLibraryUris == null || unitLibraryUris.isEmpty)) {
      offset_unitLibraryUris = fbBuilder.writeListUint32(unitLibraryUris);
    }
    var unitUnitUris = _unitUnitUris;
    if (!(unitUnitUris == null || unitUnitUris.isEmpty)) {
      offset_unitUnitUris = fbBuilder.writeListUint32(unitUnitUris);
    }
    var usedElementIsQualifiedFlags = _usedElementIsQualifiedFlags;
    if (!(usedElementIsQualifiedFlags == null ||
        usedElementIsQualifiedFlags.isEmpty)) {
      offset_usedElementIsQualifiedFlags =
          fbBuilder.writeListBool(usedElementIsQualifiedFlags);
    }
    var usedElementKinds = _usedElementKinds;
    if (!(usedElementKinds == null || usedElementKinds.isEmpty)) {
      offset_usedElementKinds = fbBuilder
          .writeListUint8(usedElementKinds.map((b) => b.index).toList());
    }
    var usedElementLengths = _usedElementLengths;
    if (!(usedElementLengths == null || usedElementLengths.isEmpty)) {
      offset_usedElementLengths = fbBuilder.writeListUint32(usedElementLengths);
    }
    var usedElementOffsets = _usedElementOffsets;
    if (!(usedElementOffsets == null || usedElementOffsets.isEmpty)) {
      offset_usedElementOffsets = fbBuilder.writeListUint32(usedElementOffsets);
    }
    var usedElements = _usedElements;
    if (!(usedElements == null || usedElements.isEmpty)) {
      offset_usedElements = fbBuilder.writeListUint32(usedElements);
    }
    var usedNameIsQualifiedFlags = _usedNameIsQualifiedFlags;
    if (!(usedNameIsQualifiedFlags == null ||
        usedNameIsQualifiedFlags.isEmpty)) {
      offset_usedNameIsQualifiedFlags =
          fbBuilder.writeListBool(usedNameIsQualifiedFlags);
    }
    var usedNameKinds = _usedNameKinds;
    if (!(usedNameKinds == null || usedNameKinds.isEmpty)) {
      offset_usedNameKinds =
          fbBuilder.writeListUint8(usedNameKinds.map((b) => b.index).toList());
    }
    var usedNameOffsets = _usedNameOffsets;
    if (!(usedNameOffsets == null || usedNameOffsets.isEmpty)) {
      offset_usedNameOffsets = fbBuilder.writeListUint32(usedNameOffsets);
    }
    var usedNames = _usedNames;
    if (!(usedNames == null || usedNames.isEmpty)) {
      offset_usedNames = fbBuilder.writeListUint32(usedNames);
    }
    fbBuilder.startTable();
    if (offset_elementKinds != null) {
      fbBuilder.addOffset(4, offset_elementKinds);
    }
    if (offset_elementNameClassMemberIds != null) {
      fbBuilder.addOffset(7, offset_elementNameClassMemberIds);
    }
    if (offset_elementNameParameterIds != null) {
      fbBuilder.addOffset(8, offset_elementNameParameterIds);
    }
    if (offset_elementNameUnitMemberIds != null) {
      fbBuilder.addOffset(6, offset_elementNameUnitMemberIds);
    }
    if (offset_elementUnits != null) {
      fbBuilder.addOffset(5, offset_elementUnits);
    }
    fbBuilder.addUint32(1, _nullStringId, 0);
    if (offset_strings != null) {
      fbBuilder.addOffset(0, offset_strings);
    }
    if (offset_subtypes != null) {
      fbBuilder.addOffset(19, offset_subtypes);
    }
    if (offset_supertypes != null) {
      fbBuilder.addOffset(18, offset_supertypes);
    }
    if (offset_unitLibraryUris != null) {
      fbBuilder.addOffset(2, offset_unitLibraryUris);
    }
    if (offset_unitUnitUris != null) {
      fbBuilder.addOffset(3, offset_unitUnitUris);
    }
    if (offset_usedElementIsQualifiedFlags != null) {
      fbBuilder.addOffset(13, offset_usedElementIsQualifiedFlags);
    }
    if (offset_usedElementKinds != null) {
      fbBuilder.addOffset(10, offset_usedElementKinds);
    }
    if (offset_usedElementLengths != null) {
      fbBuilder.addOffset(12, offset_usedElementLengths);
    }
    if (offset_usedElementOffsets != null) {
      fbBuilder.addOffset(11, offset_usedElementOffsets);
    }
    if (offset_usedElements != null) {
      fbBuilder.addOffset(9, offset_usedElements);
    }
    if (offset_usedNameIsQualifiedFlags != null) {
      fbBuilder.addOffset(17, offset_usedNameIsQualifiedFlags);
    }
    if (offset_usedNameKinds != null) {
      fbBuilder.addOffset(15, offset_usedNameKinds);
    }
    if (offset_usedNameOffsets != null) {
      fbBuilder.addOffset(16, offset_usedNameOffsets);
    }
    if (offset_usedNames != null) {
      fbBuilder.addOffset(14, offset_usedNames);
    }
    return fbBuilder.endTable();
  }
}

idl.AnalysisDriverUnitIndex readAnalysisDriverUnitIndex(List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _AnalysisDriverUnitIndexReader().read(rootRef, 0);
}

class _AnalysisDriverUnitIndexReader
    extends fb.TableReader<_AnalysisDriverUnitIndexImpl> {
  const _AnalysisDriverUnitIndexReader();

  @override
  _AnalysisDriverUnitIndexImpl createObject(fb.BufferContext bc, int offset) =>
      _AnalysisDriverUnitIndexImpl(bc, offset);
}

class _AnalysisDriverUnitIndexImpl extends Object
    with _AnalysisDriverUnitIndexMixin
    implements idl.AnalysisDriverUnitIndex {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AnalysisDriverUnitIndexImpl(this._bc, this._bcOffset);

  List<idl.IndexSyntheticElementKind>? _elementKinds;
  List<int>? _elementNameClassMemberIds;
  List<int>? _elementNameParameterIds;
  List<int>? _elementNameUnitMemberIds;
  List<int>? _elementUnits;
  int? _nullStringId;
  List<String>? _strings;
  List<idl.AnalysisDriverSubtype>? _subtypes;
  List<int>? _supertypes;
  List<int>? _unitLibraryUris;
  List<int>? _unitUnitUris;
  List<bool>? _usedElementIsQualifiedFlags;
  List<idl.IndexRelationKind>? _usedElementKinds;
  List<int>? _usedElementLengths;
  List<int>? _usedElementOffsets;
  List<int>? _usedElements;
  List<bool>? _usedNameIsQualifiedFlags;
  List<idl.IndexRelationKind>? _usedNameKinds;
  List<int>? _usedNameOffsets;
  List<int>? _usedNames;

  @override
  List<idl.IndexSyntheticElementKind> get elementKinds {
    return _elementKinds ??= const fb.ListReader<idl.IndexSyntheticElementKind>(
            _IndexSyntheticElementKindReader())
        .vTableGet(_bc, _bcOffset, 4, const <idl.IndexSyntheticElementKind>[]);
  }

  @override
  List<int> get elementNameClassMemberIds {
    return _elementNameClassMemberIds ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 7, const <int>[]);
  }

  @override
  List<int> get elementNameParameterIds {
    return _elementNameParameterIds ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 8, const <int>[]);
  }

  @override
  List<int> get elementNameUnitMemberIds {
    return _elementNameUnitMemberIds ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 6, const <int>[]);
  }

  @override
  List<int> get elementUnits {
    return _elementUnits ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 5, const <int>[]);
  }

  @override
  int get nullStringId {
    return _nullStringId ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
  }

  @override
  List<String> get strings {
    return _strings ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 0, const <String>[]);
  }

  @override
  List<idl.AnalysisDriverSubtype> get subtypes {
    return _subtypes ??= const fb.ListReader<idl.AnalysisDriverSubtype>(
            _AnalysisDriverSubtypeReader())
        .vTableGet(_bc, _bcOffset, 19, const <idl.AnalysisDriverSubtype>[]);
  }

  @override
  List<int> get supertypes {
    return _supertypes ??= const fb.Uint32ListReader()
        .vTableGet(_bc, _bcOffset, 18, const <int>[]);
  }

  @override
  List<int> get unitLibraryUris {
    return _unitLibraryUris ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 2, const <int>[]);
  }

  @override
  List<int> get unitUnitUris {
    return _unitUnitUris ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 3, const <int>[]);
  }

  @override
  List<bool> get usedElementIsQualifiedFlags {
    return _usedElementIsQualifiedFlags ??=
        const fb.BoolListReader().vTableGet(_bc, _bcOffset, 13, const <bool>[]);
  }

  @override
  List<idl.IndexRelationKind> get usedElementKinds {
    return _usedElementKinds ??=
        const fb.ListReader<idl.IndexRelationKind>(_IndexRelationKindReader())
            .vTableGet(_bc, _bcOffset, 10, const <idl.IndexRelationKind>[]);
  }

  @override
  List<int> get usedElementLengths {
    return _usedElementLengths ??= const fb.Uint32ListReader()
        .vTableGet(_bc, _bcOffset, 12, const <int>[]);
  }

  @override
  List<int> get usedElementOffsets {
    return _usedElementOffsets ??= const fb.Uint32ListReader()
        .vTableGet(_bc, _bcOffset, 11, const <int>[]);
  }

  @override
  List<int> get usedElements {
    return _usedElements ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 9, const <int>[]);
  }

  @override
  List<bool> get usedNameIsQualifiedFlags {
    return _usedNameIsQualifiedFlags ??=
        const fb.BoolListReader().vTableGet(_bc, _bcOffset, 17, const <bool>[]);
  }

  @override
  List<idl.IndexRelationKind> get usedNameKinds {
    return _usedNameKinds ??=
        const fb.ListReader<idl.IndexRelationKind>(_IndexRelationKindReader())
            .vTableGet(_bc, _bcOffset, 15, const <idl.IndexRelationKind>[]);
  }

  @override
  List<int> get usedNameOffsets {
    return _usedNameOffsets ??= const fb.Uint32ListReader()
        .vTableGet(_bc, _bcOffset, 16, const <int>[]);
  }

  @override
  List<int> get usedNames {
    return _usedNames ??= const fb.Uint32ListReader()
        .vTableGet(_bc, _bcOffset, 14, const <int>[]);
  }
}

abstract class _AnalysisDriverUnitIndexMixin
    implements idl.AnalysisDriverUnitIndex {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_elementKinds = elementKinds;
    if (local_elementKinds.isNotEmpty) {
      _result["elementKinds"] = local_elementKinds
          .map((_value) => _value.toString().split('.')[1])
          .toList();
    }
    var local_elementNameClassMemberIds = elementNameClassMemberIds;
    if (local_elementNameClassMemberIds.isNotEmpty) {
      _result["elementNameClassMemberIds"] = local_elementNameClassMemberIds;
    }
    var local_elementNameParameterIds = elementNameParameterIds;
    if (local_elementNameParameterIds.isNotEmpty) {
      _result["elementNameParameterIds"] = local_elementNameParameterIds;
    }
    var local_elementNameUnitMemberIds = elementNameUnitMemberIds;
    if (local_elementNameUnitMemberIds.isNotEmpty) {
      _result["elementNameUnitMemberIds"] = local_elementNameUnitMemberIds;
    }
    var local_elementUnits = elementUnits;
    if (local_elementUnits.isNotEmpty) {
      _result["elementUnits"] = local_elementUnits;
    }
    var local_nullStringId = nullStringId;
    if (local_nullStringId != 0) {
      _result["nullStringId"] = local_nullStringId;
    }
    var local_strings = strings;
    if (local_strings.isNotEmpty) {
      _result["strings"] = local_strings;
    }
    var local_subtypes = subtypes;
    if (local_subtypes.isNotEmpty) {
      _result["subtypes"] =
          local_subtypes.map((_value) => _value.toJson()).toList();
    }
    var local_supertypes = supertypes;
    if (local_supertypes.isNotEmpty) {
      _result["supertypes"] = local_supertypes;
    }
    var local_unitLibraryUris = unitLibraryUris;
    if (local_unitLibraryUris.isNotEmpty) {
      _result["unitLibraryUris"] = local_unitLibraryUris;
    }
    var local_unitUnitUris = unitUnitUris;
    if (local_unitUnitUris.isNotEmpty) {
      _result["unitUnitUris"] = local_unitUnitUris;
    }
    var local_usedElementIsQualifiedFlags = usedElementIsQualifiedFlags;
    if (local_usedElementIsQualifiedFlags.isNotEmpty) {
      _result["usedElementIsQualifiedFlags"] =
          local_usedElementIsQualifiedFlags;
    }
    var local_usedElementKinds = usedElementKinds;
    if (local_usedElementKinds.isNotEmpty) {
      _result["usedElementKinds"] = local_usedElementKinds
          .map((_value) => _value.toString().split('.')[1])
          .toList();
    }
    var local_usedElementLengths = usedElementLengths;
    if (local_usedElementLengths.isNotEmpty) {
      _result["usedElementLengths"] = local_usedElementLengths;
    }
    var local_usedElementOffsets = usedElementOffsets;
    if (local_usedElementOffsets.isNotEmpty) {
      _result["usedElementOffsets"] = local_usedElementOffsets;
    }
    var local_usedElements = usedElements;
    if (local_usedElements.isNotEmpty) {
      _result["usedElements"] = local_usedElements;
    }
    var local_usedNameIsQualifiedFlags = usedNameIsQualifiedFlags;
    if (local_usedNameIsQualifiedFlags.isNotEmpty) {
      _result["usedNameIsQualifiedFlags"] = local_usedNameIsQualifiedFlags;
    }
    var local_usedNameKinds = usedNameKinds;
    if (local_usedNameKinds.isNotEmpty) {
      _result["usedNameKinds"] = local_usedNameKinds
          .map((_value) => _value.toString().split('.')[1])
          .toList();
    }
    var local_usedNameOffsets = usedNameOffsets;
    if (local_usedNameOffsets.isNotEmpty) {
      _result["usedNameOffsets"] = local_usedNameOffsets;
    }
    var local_usedNames = usedNames;
    if (local_usedNames.isNotEmpty) {
      _result["usedNames"] = local_usedNames;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "elementKinds": elementKinds,
        "elementNameClassMemberIds": elementNameClassMemberIds,
        "elementNameParameterIds": elementNameParameterIds,
        "elementNameUnitMemberIds": elementNameUnitMemberIds,
        "elementUnits": elementUnits,
        "nullStringId": nullStringId,
        "strings": strings,
        "subtypes": subtypes,
        "supertypes": supertypes,
        "unitLibraryUris": unitLibraryUris,
        "unitUnitUris": unitUnitUris,
        "usedElementIsQualifiedFlags": usedElementIsQualifiedFlags,
        "usedElementKinds": usedElementKinds,
        "usedElementLengths": usedElementLengths,
        "usedElementOffsets": usedElementOffsets,
        "usedElements": usedElements,
        "usedNameIsQualifiedFlags": usedNameIsQualifiedFlags,
        "usedNameKinds": usedNameKinds,
        "usedNameOffsets": usedNameOffsets,
        "usedNames": usedNames,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AvailableDeclarationBuilder extends Object
    with _AvailableDeclarationMixin
    implements idl.AvailableDeclaration {
  List<AvailableDeclarationBuilder>? _children;
  int? _codeLength;
  int? _codeOffset;
  String? _defaultArgumentListString;
  List<int>? _defaultArgumentListTextRanges;
  String? _docComplete;
  String? _docSummary;
  int? _fieldMask;
  bool? _isAbstract;
  bool? _isConst;
  bool? _isDeprecated;
  bool? _isFinal;
  bool? _isStatic;
  idl.AvailableDeclarationKind? _kind;
  int? _locationOffset;
  int? _locationStartColumn;
  int? _locationStartLine;
  String? _name;
  List<String>? _parameterNames;
  String? _parameters;
  List<String>? _parameterTypes;
  List<String>? _relevanceTags;
  int? _requiredParameterCount;
  String? _returnType;
  String? _typeParameters;

  @override
  List<AvailableDeclarationBuilder> get children =>
      _children ??= <AvailableDeclarationBuilder>[];

  set children(List<AvailableDeclarationBuilder> value) {
    this._children = value;
  }

  @override
  int get codeLength => _codeLength ??= 0;

  set codeLength(int value) {
    assert(value >= 0);
    this._codeLength = value;
  }

  @override
  int get codeOffset => _codeOffset ??= 0;

  set codeOffset(int value) {
    assert(value >= 0);
    this._codeOffset = value;
  }

  @override
  String get defaultArgumentListString => _defaultArgumentListString ??= '';

  set defaultArgumentListString(String value) {
    this._defaultArgumentListString = value;
  }

  @override
  List<int> get defaultArgumentListTextRanges =>
      _defaultArgumentListTextRanges ??= <int>[];

  set defaultArgumentListTextRanges(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._defaultArgumentListTextRanges = value;
  }

  @override
  String get docComplete => _docComplete ??= '';

  set docComplete(String value) {
    this._docComplete = value;
  }

  @override
  String get docSummary => _docSummary ??= '';

  set docSummary(String value) {
    this._docSummary = value;
  }

  @override
  int get fieldMask => _fieldMask ??= 0;

  set fieldMask(int value) {
    assert(value >= 0);
    this._fieldMask = value;
  }

  @override
  bool get isAbstract => _isAbstract ??= false;

  set isAbstract(bool value) {
    this._isAbstract = value;
  }

  @override
  bool get isConst => _isConst ??= false;

  set isConst(bool value) {
    this._isConst = value;
  }

  @override
  bool get isDeprecated => _isDeprecated ??= false;

  set isDeprecated(bool value) {
    this._isDeprecated = value;
  }

  @override
  bool get isFinal => _isFinal ??= false;

  set isFinal(bool value) {
    this._isFinal = value;
  }

  @override
  bool get isStatic => _isStatic ??= false;

  set isStatic(bool value) {
    this._isStatic = value;
  }

  @override
  idl.AvailableDeclarationKind get kind =>
      _kind ??= idl.AvailableDeclarationKind.CLASS;

  /// The kind of the declaration.
  set kind(idl.AvailableDeclarationKind value) {
    this._kind = value;
  }

  @override
  int get locationOffset => _locationOffset ??= 0;

  set locationOffset(int value) {
    assert(value >= 0);
    this._locationOffset = value;
  }

  @override
  int get locationStartColumn => _locationStartColumn ??= 0;

  set locationStartColumn(int value) {
    assert(value >= 0);
    this._locationStartColumn = value;
  }

  @override
  int get locationStartLine => _locationStartLine ??= 0;

  set locationStartLine(int value) {
    assert(value >= 0);
    this._locationStartLine = value;
  }

  @override
  String get name => _name ??= '';

  /// The first part of the declaration name, usually the only one, for example
  /// the name of a class like `MyClass`, or a function like `myFunction`.
  set name(String value) {
    this._name = value;
  }

  @override
  List<String> get parameterNames => _parameterNames ??= <String>[];

  set parameterNames(List<String> value) {
    this._parameterNames = value;
  }

  @override
  String get parameters => _parameters ??= '';

  set parameters(String value) {
    this._parameters = value;
  }

  @override
  List<String> get parameterTypes => _parameterTypes ??= <String>[];

  set parameterTypes(List<String> value) {
    this._parameterTypes = value;
  }

  @override
  List<String> get relevanceTags => _relevanceTags ??= <String>[];

  /// The partial list of relevance tags.  Not every declaration has one (for
  /// example, function do not currently), and not every declaration has to
  /// store one (for classes it can be computed when we know the library that
  /// includes this file).
  set relevanceTags(List<String> value) {
    this._relevanceTags = value;
  }

  @override
  int get requiredParameterCount => _requiredParameterCount ??= 0;

  set requiredParameterCount(int value) {
    assert(value >= 0);
    this._requiredParameterCount = value;
  }

  @override
  String get returnType => _returnType ??= '';

  set returnType(String value) {
    this._returnType = value;
  }

  @override
  String get typeParameters => _typeParameters ??= '';

  set typeParameters(String value) {
    this._typeParameters = value;
  }

  AvailableDeclarationBuilder(
      {List<AvailableDeclarationBuilder>? children,
      int? codeLength,
      int? codeOffset,
      String? defaultArgumentListString,
      List<int>? defaultArgumentListTextRanges,
      String? docComplete,
      String? docSummary,
      int? fieldMask,
      bool? isAbstract,
      bool? isConst,
      bool? isDeprecated,
      bool? isFinal,
      bool? isStatic,
      idl.AvailableDeclarationKind? kind,
      int? locationOffset,
      int? locationStartColumn,
      int? locationStartLine,
      String? name,
      List<String>? parameterNames,
      String? parameters,
      List<String>? parameterTypes,
      List<String>? relevanceTags,
      int? requiredParameterCount,
      String? returnType,
      String? typeParameters})
      : _children = children,
        _codeLength = codeLength,
        _codeOffset = codeOffset,
        _defaultArgumentListString = defaultArgumentListString,
        _defaultArgumentListTextRanges = defaultArgumentListTextRanges,
        _docComplete = docComplete,
        _docSummary = docSummary,
        _fieldMask = fieldMask,
        _isAbstract = isAbstract,
        _isConst = isConst,
        _isDeprecated = isDeprecated,
        _isFinal = isFinal,
        _isStatic = isStatic,
        _kind = kind,
        _locationOffset = locationOffset,
        _locationStartColumn = locationStartColumn,
        _locationStartLine = locationStartLine,
        _name = name,
        _parameterNames = parameterNames,
        _parameters = parameters,
        _parameterTypes = parameterTypes,
        _relevanceTags = relevanceTags,
        _requiredParameterCount = requiredParameterCount,
        _returnType = returnType,
        _typeParameters = typeParameters;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _children?.forEach((b) => b.flushInformative());
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var children = this._children;
    if (children == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(children.length);
      for (var x in children) {
        x.collectApiSignature(signatureSink);
      }
    }
    signatureSink.addInt(this._codeLength ?? 0);
    signatureSink.addInt(this._codeOffset ?? 0);
    signatureSink.addString(this._defaultArgumentListString ?? '');
    var defaultArgumentListTextRanges = this._defaultArgumentListTextRanges;
    if (defaultArgumentListTextRanges == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(defaultArgumentListTextRanges.length);
      for (var x in defaultArgumentListTextRanges) {
        signatureSink.addInt(x);
      }
    }
    signatureSink.addString(this._docComplete ?? '');
    signatureSink.addString(this._docSummary ?? '');
    signatureSink.addInt(this._fieldMask ?? 0);
    signatureSink.addBool(this._isAbstract == true);
    signatureSink.addBool(this._isConst == true);
    signatureSink.addBool(this._isDeprecated == true);
    signatureSink.addBool(this._isFinal == true);
    signatureSink.addBool(this._isStatic == true);
    signatureSink.addInt(this._kind?.index ?? 0);
    signatureSink.addInt(this._locationOffset ?? 0);
    signatureSink.addInt(this._locationStartColumn ?? 0);
    signatureSink.addInt(this._locationStartLine ?? 0);
    signatureSink.addString(this._name ?? '');
    var parameterNames = this._parameterNames;
    if (parameterNames == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(parameterNames.length);
      for (var x in parameterNames) {
        signatureSink.addString(x);
      }
    }
    signatureSink.addString(this._parameters ?? '');
    var parameterTypes = this._parameterTypes;
    if (parameterTypes == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(parameterTypes.length);
      for (var x in parameterTypes) {
        signatureSink.addString(x);
      }
    }
    var relevanceTags = this._relevanceTags;
    if (relevanceTags == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(relevanceTags.length);
      for (var x in relevanceTags) {
        signatureSink.addString(x);
      }
    }
    signatureSink.addInt(this._requiredParameterCount ?? 0);
    signatureSink.addString(this._returnType ?? '');
    signatureSink.addString(this._typeParameters ?? '');
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_children;
    fb.Offset? offset_defaultArgumentListString;
    fb.Offset? offset_defaultArgumentListTextRanges;
    fb.Offset? offset_docComplete;
    fb.Offset? offset_docSummary;
    fb.Offset? offset_name;
    fb.Offset? offset_parameterNames;
    fb.Offset? offset_parameters;
    fb.Offset? offset_parameterTypes;
    fb.Offset? offset_relevanceTags;
    fb.Offset? offset_returnType;
    fb.Offset? offset_typeParameters;
    var children = _children;
    if (!(children == null || children.isEmpty)) {
      offset_children = fbBuilder
          .writeList(children.map((b) => b.finish(fbBuilder)).toList());
    }
    var defaultArgumentListString = _defaultArgumentListString;
    if (defaultArgumentListString != null) {
      offset_defaultArgumentListString =
          fbBuilder.writeString(defaultArgumentListString);
    }
    var defaultArgumentListTextRanges = _defaultArgumentListTextRanges;
    if (!(defaultArgumentListTextRanges == null ||
        defaultArgumentListTextRanges.isEmpty)) {
      offset_defaultArgumentListTextRanges =
          fbBuilder.writeListUint32(defaultArgumentListTextRanges);
    }
    var docComplete = _docComplete;
    if (docComplete != null) {
      offset_docComplete = fbBuilder.writeString(docComplete);
    }
    var docSummary = _docSummary;
    if (docSummary != null) {
      offset_docSummary = fbBuilder.writeString(docSummary);
    }
    var name = _name;
    if (name != null) {
      offset_name = fbBuilder.writeString(name);
    }
    var parameterNames = _parameterNames;
    if (!(parameterNames == null || parameterNames.isEmpty)) {
      offset_parameterNames = fbBuilder.writeList(
          parameterNames.map((b) => fbBuilder.writeString(b)).toList());
    }
    var parameters = _parameters;
    if (parameters != null) {
      offset_parameters = fbBuilder.writeString(parameters);
    }
    var parameterTypes = _parameterTypes;
    if (!(parameterTypes == null || parameterTypes.isEmpty)) {
      offset_parameterTypes = fbBuilder.writeList(
          parameterTypes.map((b) => fbBuilder.writeString(b)).toList());
    }
    var relevanceTags = _relevanceTags;
    if (!(relevanceTags == null || relevanceTags.isEmpty)) {
      offset_relevanceTags = fbBuilder.writeList(
          relevanceTags.map((b) => fbBuilder.writeString(b)).toList());
    }
    var returnType = _returnType;
    if (returnType != null) {
      offset_returnType = fbBuilder.writeString(returnType);
    }
    var typeParameters = _typeParameters;
    if (typeParameters != null) {
      offset_typeParameters = fbBuilder.writeString(typeParameters);
    }
    fbBuilder.startTable();
    if (offset_children != null) {
      fbBuilder.addOffset(0, offset_children);
    }
    fbBuilder.addUint32(1, _codeLength, 0);
    fbBuilder.addUint32(2, _codeOffset, 0);
    if (offset_defaultArgumentListString != null) {
      fbBuilder.addOffset(3, offset_defaultArgumentListString);
    }
    if (offset_defaultArgumentListTextRanges != null) {
      fbBuilder.addOffset(4, offset_defaultArgumentListTextRanges);
    }
    if (offset_docComplete != null) {
      fbBuilder.addOffset(5, offset_docComplete);
    }
    if (offset_docSummary != null) {
      fbBuilder.addOffset(6, offset_docSummary);
    }
    fbBuilder.addUint32(7, _fieldMask, 0);
    fbBuilder.addBool(8, _isAbstract == true);
    fbBuilder.addBool(9, _isConst == true);
    fbBuilder.addBool(10, _isDeprecated == true);
    fbBuilder.addBool(11, _isFinal == true);
    fbBuilder.addBool(12, _isStatic == true);
    fbBuilder.addUint8(
        13, _kind?.index, idl.AvailableDeclarationKind.CLASS.index);
    fbBuilder.addUint32(14, _locationOffset, 0);
    fbBuilder.addUint32(15, _locationStartColumn, 0);
    fbBuilder.addUint32(16, _locationStartLine, 0);
    if (offset_name != null) {
      fbBuilder.addOffset(17, offset_name);
    }
    if (offset_parameterNames != null) {
      fbBuilder.addOffset(18, offset_parameterNames);
    }
    if (offset_parameters != null) {
      fbBuilder.addOffset(19, offset_parameters);
    }
    if (offset_parameterTypes != null) {
      fbBuilder.addOffset(20, offset_parameterTypes);
    }
    if (offset_relevanceTags != null) {
      fbBuilder.addOffset(21, offset_relevanceTags);
    }
    fbBuilder.addUint32(22, _requiredParameterCount, 0);
    if (offset_returnType != null) {
      fbBuilder.addOffset(23, offset_returnType);
    }
    if (offset_typeParameters != null) {
      fbBuilder.addOffset(24, offset_typeParameters);
    }
    return fbBuilder.endTable();
  }
}

class _AvailableDeclarationReader
    extends fb.TableReader<_AvailableDeclarationImpl> {
  const _AvailableDeclarationReader();

  @override
  _AvailableDeclarationImpl createObject(fb.BufferContext bc, int offset) =>
      _AvailableDeclarationImpl(bc, offset);
}

class _AvailableDeclarationImpl extends Object
    with _AvailableDeclarationMixin
    implements idl.AvailableDeclaration {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AvailableDeclarationImpl(this._bc, this._bcOffset);

  List<idl.AvailableDeclaration>? _children;
  int? _codeLength;
  int? _codeOffset;
  String? _defaultArgumentListString;
  List<int>? _defaultArgumentListTextRanges;
  String? _docComplete;
  String? _docSummary;
  int? _fieldMask;
  bool? _isAbstract;
  bool? _isConst;
  bool? _isDeprecated;
  bool? _isFinal;
  bool? _isStatic;
  idl.AvailableDeclarationKind? _kind;
  int? _locationOffset;
  int? _locationStartColumn;
  int? _locationStartLine;
  String? _name;
  List<String>? _parameterNames;
  String? _parameters;
  List<String>? _parameterTypes;
  List<String>? _relevanceTags;
  int? _requiredParameterCount;
  String? _returnType;
  String? _typeParameters;

  @override
  List<idl.AvailableDeclaration> get children {
    return _children ??= const fb.ListReader<idl.AvailableDeclaration>(
            _AvailableDeclarationReader())
        .vTableGet(_bc, _bcOffset, 0, const <idl.AvailableDeclaration>[]);
  }

  @override
  int get codeLength {
    return _codeLength ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
  }

  @override
  int get codeOffset {
    return _codeOffset ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 2, 0);
  }

  @override
  String get defaultArgumentListString {
    return _defaultArgumentListString ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
  }

  @override
  List<int> get defaultArgumentListTextRanges {
    return _defaultArgumentListTextRanges ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 4, const <int>[]);
  }

  @override
  String get docComplete {
    return _docComplete ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 5, '');
  }

  @override
  String get docSummary {
    return _docSummary ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 6, '');
  }

  @override
  int get fieldMask {
    return _fieldMask ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 7, 0);
  }

  @override
  bool get isAbstract {
    return _isAbstract ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 8, false);
  }

  @override
  bool get isConst {
    return _isConst ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 9, false);
  }

  @override
  bool get isDeprecated {
    return _isDeprecated ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 10, false);
  }

  @override
  bool get isFinal {
    return _isFinal ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 11, false);
  }

  @override
  bool get isStatic {
    return _isStatic ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 12, false);
  }

  @override
  idl.AvailableDeclarationKind get kind {
    return _kind ??= const _AvailableDeclarationKindReader()
        .vTableGet(_bc, _bcOffset, 13, idl.AvailableDeclarationKind.CLASS);
  }

  @override
  int get locationOffset {
    return _locationOffset ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 14, 0);
  }

  @override
  int get locationStartColumn {
    return _locationStartColumn ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
  }

  @override
  int get locationStartLine {
    return _locationStartLine ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
  }

  @override
  String get name {
    return _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 17, '');
  }

  @override
  List<String> get parameterNames {
    return _parameterNames ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 18, const <String>[]);
  }

  @override
  String get parameters {
    return _parameters ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 19, '');
  }

  @override
  List<String> get parameterTypes {
    return _parameterTypes ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 20, const <String>[]);
  }

  @override
  List<String> get relevanceTags {
    return _relevanceTags ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 21, const <String>[]);
  }

  @override
  int get requiredParameterCount {
    return _requiredParameterCount ??=
        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 22, 0);
  }

  @override
  String get returnType {
    return _returnType ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 23, '');
  }

  @override
  String get typeParameters {
    return _typeParameters ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 24, '');
  }
}

abstract class _AvailableDeclarationMixin implements idl.AvailableDeclaration {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_children = children;
    if (local_children.isNotEmpty) {
      _result["children"] =
          local_children.map((_value) => _value.toJson()).toList();
    }
    var local_codeLength = codeLength;
    if (local_codeLength != 0) {
      _result["codeLength"] = local_codeLength;
    }
    var local_codeOffset = codeOffset;
    if (local_codeOffset != 0) {
      _result["codeOffset"] = local_codeOffset;
    }
    var local_defaultArgumentListString = defaultArgumentListString;
    if (local_defaultArgumentListString != '') {
      _result["defaultArgumentListString"] = local_defaultArgumentListString;
    }
    var local_defaultArgumentListTextRanges = defaultArgumentListTextRanges;
    if (local_defaultArgumentListTextRanges.isNotEmpty) {
      _result["defaultArgumentListTextRanges"] =
          local_defaultArgumentListTextRanges;
    }
    var local_docComplete = docComplete;
    if (local_docComplete != '') {
      _result["docComplete"] = local_docComplete;
    }
    var local_docSummary = docSummary;
    if (local_docSummary != '') {
      _result["docSummary"] = local_docSummary;
    }
    var local_fieldMask = fieldMask;
    if (local_fieldMask != 0) {
      _result["fieldMask"] = local_fieldMask;
    }
    var local_isAbstract = isAbstract;
    if (local_isAbstract != false) {
      _result["isAbstract"] = local_isAbstract;
    }
    var local_isConst = isConst;
    if (local_isConst != false) {
      _result["isConst"] = local_isConst;
    }
    var local_isDeprecated = isDeprecated;
    if (local_isDeprecated != false) {
      _result["isDeprecated"] = local_isDeprecated;
    }
    var local_isFinal = isFinal;
    if (local_isFinal != false) {
      _result["isFinal"] = local_isFinal;
    }
    var local_isStatic = isStatic;
    if (local_isStatic != false) {
      _result["isStatic"] = local_isStatic;
    }
    var local_kind = kind;
    if (local_kind != idl.AvailableDeclarationKind.CLASS) {
      _result["kind"] = local_kind.toString().split('.')[1];
    }
    var local_locationOffset = locationOffset;
    if (local_locationOffset != 0) {
      _result["locationOffset"] = local_locationOffset;
    }
    var local_locationStartColumn = locationStartColumn;
    if (local_locationStartColumn != 0) {
      _result["locationStartColumn"] = local_locationStartColumn;
    }
    var local_locationStartLine = locationStartLine;
    if (local_locationStartLine != 0) {
      _result["locationStartLine"] = local_locationStartLine;
    }
    var local_name = name;
    if (local_name != '') {
      _result["name"] = local_name;
    }
    var local_parameterNames = parameterNames;
    if (local_parameterNames.isNotEmpty) {
      _result["parameterNames"] = local_parameterNames;
    }
    var local_parameters = parameters;
    if (local_parameters != '') {
      _result["parameters"] = local_parameters;
    }
    var local_parameterTypes = parameterTypes;
    if (local_parameterTypes.isNotEmpty) {
      _result["parameterTypes"] = local_parameterTypes;
    }
    var local_relevanceTags = relevanceTags;
    if (local_relevanceTags.isNotEmpty) {
      _result["relevanceTags"] = local_relevanceTags;
    }
    var local_requiredParameterCount = requiredParameterCount;
    if (local_requiredParameterCount != 0) {
      _result["requiredParameterCount"] = local_requiredParameterCount;
    }
    var local_returnType = returnType;
    if (local_returnType != '') {
      _result["returnType"] = local_returnType;
    }
    var local_typeParameters = typeParameters;
    if (local_typeParameters != '') {
      _result["typeParameters"] = local_typeParameters;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "children": children,
        "codeLength": codeLength,
        "codeOffset": codeOffset,
        "defaultArgumentListString": defaultArgumentListString,
        "defaultArgumentListTextRanges": defaultArgumentListTextRanges,
        "docComplete": docComplete,
        "docSummary": docSummary,
        "fieldMask": fieldMask,
        "isAbstract": isAbstract,
        "isConst": isConst,
        "isDeprecated": isDeprecated,
        "isFinal": isFinal,
        "isStatic": isStatic,
        "kind": kind,
        "locationOffset": locationOffset,
        "locationStartColumn": locationStartColumn,
        "locationStartLine": locationStartLine,
        "name": name,
        "parameterNames": parameterNames,
        "parameters": parameters,
        "parameterTypes": parameterTypes,
        "relevanceTags": relevanceTags,
        "requiredParameterCount": requiredParameterCount,
        "returnType": returnType,
        "typeParameters": typeParameters,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AvailableFileBuilder extends Object
    with _AvailableFileMixin
    implements idl.AvailableFile {
  List<AvailableDeclarationBuilder>? _declarations;
  DirectiveInfoBuilder? _directiveInfo;
  List<AvailableFileExportBuilder>? _exports;
  bool? _isLibrary;
  bool? _isLibraryDeprecated;
  List<int>? _lineStarts;
  List<String>? _parts;

  @override
  List<AvailableDeclarationBuilder> get declarations =>
      _declarations ??= <AvailableDeclarationBuilder>[];

  /// Declarations of the file.
  set declarations(List<AvailableDeclarationBuilder> value) {
    this._declarations = value;
  }

  @override
  DirectiveInfoBuilder? get directiveInfo => _directiveInfo;

  /// The Dartdoc directives in the file.
  set directiveInfo(DirectiveInfoBuilder? value) {
    this._directiveInfo = value;
  }

  @override
  List<AvailableFileExportBuilder> get exports =>
      _exports ??= <AvailableFileExportBuilder>[];

  /// Exports directives of the file.
  set exports(List<AvailableFileExportBuilder> value) {
    this._exports = value;
  }

  @override
  bool get isLibrary => _isLibrary ??= false;

  /// Is `true` if this file is a library.
  set isLibrary(bool value) {
    this._isLibrary = value;
  }

  @override
  bool get isLibraryDeprecated => _isLibraryDeprecated ??= false;

  /// Is `true` if this file is a library, and it is deprecated.
  set isLibraryDeprecated(bool value) {
    this._isLibraryDeprecated = value;
  }

  @override
  List<int> get lineStarts => _lineStarts ??= <int>[];

  /// Offsets of the first character of each line in the source code.
  set lineStarts(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._lineStarts = value;
  }

  @override
  List<String> get parts => _parts ??= <String>[];

  /// URIs of `part` directives.
  set parts(List<String> value) {
    this._parts = value;
  }

  AvailableFileBuilder(
      {List<AvailableDeclarationBuilder>? declarations,
      DirectiveInfoBuilder? directiveInfo,
      List<AvailableFileExportBuilder>? exports,
      bool? isLibrary,
      bool? isLibraryDeprecated,
      List<int>? lineStarts,
      List<String>? parts})
      : _declarations = declarations,
        _directiveInfo = directiveInfo,
        _exports = exports,
        _isLibrary = isLibrary,
        _isLibraryDeprecated = isLibraryDeprecated,
        _lineStarts = lineStarts,
        _parts = parts;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _declarations?.forEach((b) => b.flushInformative());
    _directiveInfo?.flushInformative();
    _exports?.forEach((b) => b.flushInformative());
    _lineStarts = null;
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var declarations = this._declarations;
    if (declarations == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(declarations.length);
      for (var x in declarations) {
        x.collectApiSignature(signatureSink);
      }
    }
    signatureSink.addBool(this._directiveInfo != null);
    this._directiveInfo?.collectApiSignature(signatureSink);
    var exports = this._exports;
    if (exports == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(exports.length);
      for (var x in exports) {
        x.collectApiSignature(signatureSink);
      }
    }
    signatureSink.addBool(this._isLibrary == true);
    signatureSink.addBool(this._isLibraryDeprecated == true);
    var parts = this._parts;
    if (parts == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(parts.length);
      for (var x in parts) {
        signatureSink.addString(x);
      }
    }
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "UICF");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_declarations;
    fb.Offset? offset_directiveInfo;
    fb.Offset? offset_exports;
    fb.Offset? offset_lineStarts;
    fb.Offset? offset_parts;
    var declarations = _declarations;
    if (!(declarations == null || declarations.isEmpty)) {
      offset_declarations = fbBuilder
          .writeList(declarations.map((b) => b.finish(fbBuilder)).toList());
    }
    var directiveInfo = _directiveInfo;
    if (directiveInfo != null) {
      offset_directiveInfo = directiveInfo.finish(fbBuilder);
    }
    var exports = _exports;
    if (!(exports == null || exports.isEmpty)) {
      offset_exports =
          fbBuilder.writeList(exports.map((b) => b.finish(fbBuilder)).toList());
    }
    var lineStarts = _lineStarts;
    if (!(lineStarts == null || lineStarts.isEmpty)) {
      offset_lineStarts = fbBuilder.writeListUint32(lineStarts);
    }
    var parts = _parts;
    if (!(parts == null || parts.isEmpty)) {
      offset_parts = fbBuilder
          .writeList(parts.map((b) => fbBuilder.writeString(b)).toList());
    }
    fbBuilder.startTable();
    if (offset_declarations != null) {
      fbBuilder.addOffset(0, offset_declarations);
    }
    if (offset_directiveInfo != null) {
      fbBuilder.addOffset(1, offset_directiveInfo);
    }
    if (offset_exports != null) {
      fbBuilder.addOffset(2, offset_exports);
    }
    fbBuilder.addBool(3, _isLibrary == true);
    fbBuilder.addBool(4, _isLibraryDeprecated == true);
    if (offset_lineStarts != null) {
      fbBuilder.addOffset(5, offset_lineStarts);
    }
    if (offset_parts != null) {
      fbBuilder.addOffset(6, offset_parts);
    }
    return fbBuilder.endTable();
  }
}

idl.AvailableFile readAvailableFile(List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _AvailableFileReader().read(rootRef, 0);
}

class _AvailableFileReader extends fb.TableReader<_AvailableFileImpl> {
  const _AvailableFileReader();

  @override
  _AvailableFileImpl createObject(fb.BufferContext bc, int offset) =>
      _AvailableFileImpl(bc, offset);
}

class _AvailableFileImpl extends Object
    with _AvailableFileMixin
    implements idl.AvailableFile {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AvailableFileImpl(this._bc, this._bcOffset);

  List<idl.AvailableDeclaration>? _declarations;
  idl.DirectiveInfo? _directiveInfo;
  List<idl.AvailableFileExport>? _exports;
  bool? _isLibrary;
  bool? _isLibraryDeprecated;
  List<int>? _lineStarts;
  List<String>? _parts;

  @override
  List<idl.AvailableDeclaration> get declarations {
    return _declarations ??= const fb.ListReader<idl.AvailableDeclaration>(
            _AvailableDeclarationReader())
        .vTableGet(_bc, _bcOffset, 0, const <idl.AvailableDeclaration>[]);
  }

  @override
  idl.DirectiveInfo? get directiveInfo {
    return _directiveInfo ??=
        const _DirectiveInfoReader().vTableGetOrNull(_bc, _bcOffset, 1);
  }

  @override
  List<idl.AvailableFileExport> get exports {
    return _exports ??= const fb.ListReader<idl.AvailableFileExport>(
            _AvailableFileExportReader())
        .vTableGet(_bc, _bcOffset, 2, const <idl.AvailableFileExport>[]);
  }

  @override
  bool get isLibrary {
    return _isLibrary ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
  }

  @override
  bool get isLibraryDeprecated {
    return _isLibraryDeprecated ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
  }

  @override
  List<int> get lineStarts {
    return _lineStarts ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 5, const <int>[]);
  }

  @override
  List<String> get parts {
    return _parts ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 6, const <String>[]);
  }
}

abstract class _AvailableFileMixin implements idl.AvailableFile {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_declarations = declarations;
    if (local_declarations.isNotEmpty) {
      _result["declarations"] =
          local_declarations.map((_value) => _value.toJson()).toList();
    }
    var local_directiveInfo = directiveInfo;
    if (local_directiveInfo != null) {
      _result["directiveInfo"] = local_directiveInfo.toJson();
    }
    var local_exports = exports;
    if (local_exports.isNotEmpty) {
      _result["exports"] =
          local_exports.map((_value) => _value.toJson()).toList();
    }
    var local_isLibrary = isLibrary;
    if (local_isLibrary != false) {
      _result["isLibrary"] = local_isLibrary;
    }
    var local_isLibraryDeprecated = isLibraryDeprecated;
    if (local_isLibraryDeprecated != false) {
      _result["isLibraryDeprecated"] = local_isLibraryDeprecated;
    }
    var local_lineStarts = lineStarts;
    if (local_lineStarts.isNotEmpty) {
      _result["lineStarts"] = local_lineStarts;
    }
    var local_parts = parts;
    if (local_parts.isNotEmpty) {
      _result["parts"] = local_parts;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "declarations": declarations,
        "directiveInfo": directiveInfo,
        "exports": exports,
        "isLibrary": isLibrary,
        "isLibraryDeprecated": isLibraryDeprecated,
        "lineStarts": lineStarts,
        "parts": parts,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AvailableFileExportBuilder extends Object
    with _AvailableFileExportMixin
    implements idl.AvailableFileExport {
  List<AvailableFileExportCombinatorBuilder>? _combinators;
  String? _uri;

  @override
  List<AvailableFileExportCombinatorBuilder> get combinators =>
      _combinators ??= <AvailableFileExportCombinatorBuilder>[];

  /// Combinators contained in this export directive.
  set combinators(List<AvailableFileExportCombinatorBuilder> value) {
    this._combinators = value;
  }

  @override
  String get uri => _uri ??= '';

  /// URI of the exported library.
  set uri(String value) {
    this._uri = value;
  }

  AvailableFileExportBuilder(
      {List<AvailableFileExportCombinatorBuilder>? combinators, String? uri})
      : _combinators = combinators,
        _uri = uri;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _combinators?.forEach((b) => b.flushInformative());
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addString(this._uri ?? '');
    var combinators = this._combinators;
    if (combinators == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(combinators.length);
      for (var x in combinators) {
        x.collectApiSignature(signatureSink);
      }
    }
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_combinators;
    fb.Offset? offset_uri;
    var combinators = _combinators;
    if (!(combinators == null || combinators.isEmpty)) {
      offset_combinators = fbBuilder
          .writeList(combinators.map((b) => b.finish(fbBuilder)).toList());
    }
    var uri = _uri;
    if (uri != null) {
      offset_uri = fbBuilder.writeString(uri);
    }
    fbBuilder.startTable();
    if (offset_combinators != null) {
      fbBuilder.addOffset(1, offset_combinators);
    }
    if (offset_uri != null) {
      fbBuilder.addOffset(0, offset_uri);
    }
    return fbBuilder.endTable();
  }
}

class _AvailableFileExportReader
    extends fb.TableReader<_AvailableFileExportImpl> {
  const _AvailableFileExportReader();

  @override
  _AvailableFileExportImpl createObject(fb.BufferContext bc, int offset) =>
      _AvailableFileExportImpl(bc, offset);
}

class _AvailableFileExportImpl extends Object
    with _AvailableFileExportMixin
    implements idl.AvailableFileExport {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AvailableFileExportImpl(this._bc, this._bcOffset);

  List<idl.AvailableFileExportCombinator>? _combinators;
  String? _uri;

  @override
  List<idl.AvailableFileExportCombinator> get combinators {
    return _combinators ??=
        const fb.ListReader<idl.AvailableFileExportCombinator>(
                _AvailableFileExportCombinatorReader())
            .vTableGet(
                _bc, _bcOffset, 1, const <idl.AvailableFileExportCombinator>[]);
  }

  @override
  String get uri {
    return _uri ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
  }
}

abstract class _AvailableFileExportMixin implements idl.AvailableFileExport {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_combinators = combinators;
    if (local_combinators.isNotEmpty) {
      _result["combinators"] =
          local_combinators.map((_value) => _value.toJson()).toList();
    }
    var local_uri = uri;
    if (local_uri != '') {
      _result["uri"] = local_uri;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "combinators": combinators,
        "uri": uri,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class AvailableFileExportCombinatorBuilder extends Object
    with _AvailableFileExportCombinatorMixin
    implements idl.AvailableFileExportCombinator {
  List<String>? _hides;
  List<String>? _shows;

  @override
  List<String> get hides => _hides ??= <String>[];

  /// List of names which are hidden.  Empty if this is a `show` combinator.
  set hides(List<String> value) {
    this._hides = value;
  }

  @override
  List<String> get shows => _shows ??= <String>[];

  /// List of names which are shown.  Empty if this is a `hide` combinator.
  set shows(List<String> value) {
    this._shows = value;
  }

  AvailableFileExportCombinatorBuilder(
      {List<String>? hides, List<String>? shows})
      : _hides = hides,
        _shows = shows;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var shows = this._shows;
    if (shows == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(shows.length);
      for (var x in shows) {
        signatureSink.addString(x);
      }
    }
    var hides = this._hides;
    if (hides == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(hides.length);
      for (var x in hides) {
        signatureSink.addString(x);
      }
    }
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_hides;
    fb.Offset? offset_shows;
    var hides = _hides;
    if (!(hides == null || hides.isEmpty)) {
      offset_hides = fbBuilder
          .writeList(hides.map((b) => fbBuilder.writeString(b)).toList());
    }
    var shows = _shows;
    if (!(shows == null || shows.isEmpty)) {
      offset_shows = fbBuilder
          .writeList(shows.map((b) => fbBuilder.writeString(b)).toList());
    }
    fbBuilder.startTable();
    if (offset_hides != null) {
      fbBuilder.addOffset(1, offset_hides);
    }
    if (offset_shows != null) {
      fbBuilder.addOffset(0, offset_shows);
    }
    return fbBuilder.endTable();
  }
}

class _AvailableFileExportCombinatorReader
    extends fb.TableReader<_AvailableFileExportCombinatorImpl> {
  const _AvailableFileExportCombinatorReader();

  @override
  _AvailableFileExportCombinatorImpl createObject(
          fb.BufferContext bc, int offset) =>
      _AvailableFileExportCombinatorImpl(bc, offset);
}

class _AvailableFileExportCombinatorImpl extends Object
    with _AvailableFileExportCombinatorMixin
    implements idl.AvailableFileExportCombinator {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _AvailableFileExportCombinatorImpl(this._bc, this._bcOffset);

  List<String>? _hides;
  List<String>? _shows;

  @override
  List<String> get hides {
    return _hides ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 1, const <String>[]);
  }

  @override
  List<String> get shows {
    return _shows ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 0, const <String>[]);
  }
}

abstract class _AvailableFileExportCombinatorMixin
    implements idl.AvailableFileExportCombinator {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_hides = hides;
    if (local_hides.isNotEmpty) {
      _result["hides"] = local_hides;
    }
    var local_shows = shows;
    if (local_shows.isNotEmpty) {
      _result["shows"] = local_shows;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "hides": hides,
        "shows": shows,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class CiderUnitErrorsBuilder extends Object
    with _CiderUnitErrorsMixin
    implements idl.CiderUnitErrors {
  List<AnalysisDriverUnitErrorBuilder>? _errors;
  List<int>? _signature;

  @override
  List<AnalysisDriverUnitErrorBuilder> get errors =>
      _errors ??= <AnalysisDriverUnitErrorBuilder>[];

  set errors(List<AnalysisDriverUnitErrorBuilder> value) {
    this._errors = value;
  }

  @override
  List<int> get signature => _signature ??= <int>[];

  /// The hash signature of this data.
  set signature(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._signature = value;
  }

  CiderUnitErrorsBuilder(
      {List<AnalysisDriverUnitErrorBuilder>? errors, List<int>? signature})
      : _errors = errors,
        _signature = signature;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _errors?.forEach((b) => b.flushInformative());
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var signature = this._signature;
    if (signature == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(signature.length);
      for (var x in signature) {
        signatureSink.addInt(x);
      }
    }
    var errors = this._errors;
    if (errors == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(errors.length);
      for (var x in errors) {
        x.collectApiSignature(signatureSink);
      }
    }
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "CUEr");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_errors;
    fb.Offset? offset_signature;
    var errors = _errors;
    if (!(errors == null || errors.isEmpty)) {
      offset_errors =
          fbBuilder.writeList(errors.map((b) => b.finish(fbBuilder)).toList());
    }
    var signature = _signature;
    if (!(signature == null || signature.isEmpty)) {
      offset_signature = fbBuilder.writeListUint32(signature);
    }
    fbBuilder.startTable();
    if (offset_errors != null) {
      fbBuilder.addOffset(1, offset_errors);
    }
    if (offset_signature != null) {
      fbBuilder.addOffset(0, offset_signature);
    }
    return fbBuilder.endTable();
  }
}

idl.CiderUnitErrors readCiderUnitErrors(List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _CiderUnitErrorsReader().read(rootRef, 0);
}

class _CiderUnitErrorsReader extends fb.TableReader<_CiderUnitErrorsImpl> {
  const _CiderUnitErrorsReader();

  @override
  _CiderUnitErrorsImpl createObject(fb.BufferContext bc, int offset) =>
      _CiderUnitErrorsImpl(bc, offset);
}

class _CiderUnitErrorsImpl extends Object
    with _CiderUnitErrorsMixin
    implements idl.CiderUnitErrors {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _CiderUnitErrorsImpl(this._bc, this._bcOffset);

  List<idl.AnalysisDriverUnitError>? _errors;
  List<int>? _signature;

  @override
  List<idl.AnalysisDriverUnitError> get errors {
    return _errors ??= const fb.ListReader<idl.AnalysisDriverUnitError>(
            _AnalysisDriverUnitErrorReader())
        .vTableGet(_bc, _bcOffset, 1, const <idl.AnalysisDriverUnitError>[]);
  }

  @override
  List<int> get signature {
    return _signature ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 0, const <int>[]);
  }
}

abstract class _CiderUnitErrorsMixin implements idl.CiderUnitErrors {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_errors = errors;
    if (local_errors.isNotEmpty) {
      _result["errors"] =
          local_errors.map((_value) => _value.toJson()).toList();
    }
    var local_signature = signature;
    if (local_signature.isNotEmpty) {
      _result["signature"] = local_signature;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "errors": errors,
        "signature": signature,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class CiderUnitTopLevelDeclarationsBuilder extends Object
    with _CiderUnitTopLevelDeclarationsMixin
    implements idl.CiderUnitTopLevelDeclarations {
  List<String>? _extensionNames;
  List<String>? _functionNames;
  List<String>? _typeNames;
  List<String>? _variableNames;

  @override
  List<String> get extensionNames => _extensionNames ??= <String>[];

  set extensionNames(List<String> value) {
    this._extensionNames = value;
  }

  @override
  List<String> get functionNames => _functionNames ??= <String>[];

  set functionNames(List<String> value) {
    this._functionNames = value;
  }

  @override
  List<String> get typeNames => _typeNames ??= <String>[];

  set typeNames(List<String> value) {
    this._typeNames = value;
  }

  @override
  List<String> get variableNames => _variableNames ??= <String>[];

  set variableNames(List<String> value) {
    this._variableNames = value;
  }

  CiderUnitTopLevelDeclarationsBuilder(
      {List<String>? extensionNames,
      List<String>? functionNames,
      List<String>? typeNames,
      List<String>? variableNames})
      : _extensionNames = extensionNames,
        _functionNames = functionNames,
        _typeNames = typeNames,
        _variableNames = variableNames;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var extensionNames = this._extensionNames;
    if (extensionNames == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(extensionNames.length);
      for (var x in extensionNames) {
        signatureSink.addString(x);
      }
    }
    var functionNames = this._functionNames;
    if (functionNames == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(functionNames.length);
      for (var x in functionNames) {
        signatureSink.addString(x);
      }
    }
    var typeNames = this._typeNames;
    if (typeNames == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(typeNames.length);
      for (var x in typeNames) {
        signatureSink.addString(x);
      }
    }
    var variableNames = this._variableNames;
    if (variableNames == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(variableNames.length);
      for (var x in variableNames) {
        signatureSink.addString(x);
      }
    }
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_extensionNames;
    fb.Offset? offset_functionNames;
    fb.Offset? offset_typeNames;
    fb.Offset? offset_variableNames;
    var extensionNames = _extensionNames;
    if (!(extensionNames == null || extensionNames.isEmpty)) {
      offset_extensionNames = fbBuilder.writeList(
          extensionNames.map((b) => fbBuilder.writeString(b)).toList());
    }
    var functionNames = _functionNames;
    if (!(functionNames == null || functionNames.isEmpty)) {
      offset_functionNames = fbBuilder.writeList(
          functionNames.map((b) => fbBuilder.writeString(b)).toList());
    }
    var typeNames = _typeNames;
    if (!(typeNames == null || typeNames.isEmpty)) {
      offset_typeNames = fbBuilder
          .writeList(typeNames.map((b) => fbBuilder.writeString(b)).toList());
    }
    var variableNames = _variableNames;
    if (!(variableNames == null || variableNames.isEmpty)) {
      offset_variableNames = fbBuilder.writeList(
          variableNames.map((b) => fbBuilder.writeString(b)).toList());
    }
    fbBuilder.startTable();
    if (offset_extensionNames != null) {
      fbBuilder.addOffset(0, offset_extensionNames);
    }
    if (offset_functionNames != null) {
      fbBuilder.addOffset(1, offset_functionNames);
    }
    if (offset_typeNames != null) {
      fbBuilder.addOffset(2, offset_typeNames);
    }
    if (offset_variableNames != null) {
      fbBuilder.addOffset(3, offset_variableNames);
    }
    return fbBuilder.endTable();
  }
}

class _CiderUnitTopLevelDeclarationsReader
    extends fb.TableReader<_CiderUnitTopLevelDeclarationsImpl> {
  const _CiderUnitTopLevelDeclarationsReader();

  @override
  _CiderUnitTopLevelDeclarationsImpl createObject(
          fb.BufferContext bc, int offset) =>
      _CiderUnitTopLevelDeclarationsImpl(bc, offset);
}

class _CiderUnitTopLevelDeclarationsImpl extends Object
    with _CiderUnitTopLevelDeclarationsMixin
    implements idl.CiderUnitTopLevelDeclarations {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _CiderUnitTopLevelDeclarationsImpl(this._bc, this._bcOffset);

  List<String>? _extensionNames;
  List<String>? _functionNames;
  List<String>? _typeNames;
  List<String>? _variableNames;

  @override
  List<String> get extensionNames {
    return _extensionNames ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 0, const <String>[]);
  }

  @override
  List<String> get functionNames {
    return _functionNames ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 1, const <String>[]);
  }

  @override
  List<String> get typeNames {
    return _typeNames ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 2, const <String>[]);
  }

  @override
  List<String> get variableNames {
    return _variableNames ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 3, const <String>[]);
  }
}

abstract class _CiderUnitTopLevelDeclarationsMixin
    implements idl.CiderUnitTopLevelDeclarations {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_extensionNames = extensionNames;
    if (local_extensionNames.isNotEmpty) {
      _result["extensionNames"] = local_extensionNames;
    }
    var local_functionNames = functionNames;
    if (local_functionNames.isNotEmpty) {
      _result["functionNames"] = local_functionNames;
    }
    var local_typeNames = typeNames;
    if (local_typeNames.isNotEmpty) {
      _result["typeNames"] = local_typeNames;
    }
    var local_variableNames = variableNames;
    if (local_variableNames.isNotEmpty) {
      _result["variableNames"] = local_variableNames;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "extensionNames": extensionNames,
        "functionNames": functionNames,
        "typeNames": typeNames,
        "variableNames": variableNames,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class CiderUnlinkedUnitBuilder extends Object
    with _CiderUnlinkedUnitMixin
    implements idl.CiderUnlinkedUnit {
  List<int>? _contentDigest;
  CiderUnitTopLevelDeclarationsBuilder? _topLevelDeclarations;
  UnlinkedUnit2Builder? _unlinkedUnit;

  @override
  List<int> get contentDigest => _contentDigest ??= <int>[];

  /// The hash signature of the contents of the file.
  set contentDigest(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._contentDigest = value;
  }

  @override
  CiderUnitTopLevelDeclarationsBuilder? get topLevelDeclarations =>
      _topLevelDeclarations;

  /// Top-level declarations of the unit.
  set topLevelDeclarations(CiderUnitTopLevelDeclarationsBuilder? value) {
    this._topLevelDeclarations = value;
  }

  @override
  UnlinkedUnit2Builder? get unlinkedUnit => _unlinkedUnit;

  /// Unlinked summary of the compilation unit.
  set unlinkedUnit(UnlinkedUnit2Builder? value) {
    this._unlinkedUnit = value;
  }

  CiderUnlinkedUnitBuilder(
      {List<int>? contentDigest,
      CiderUnitTopLevelDeclarationsBuilder? topLevelDeclarations,
      UnlinkedUnit2Builder? unlinkedUnit})
      : _contentDigest = contentDigest,
        _topLevelDeclarations = topLevelDeclarations,
        _unlinkedUnit = unlinkedUnit;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _topLevelDeclarations?.flushInformative();
    _unlinkedUnit?.flushInformative();
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var contentDigest = this._contentDigest;
    if (contentDigest == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(contentDigest.length);
      for (var x in contentDigest) {
        signatureSink.addInt(x);
      }
    }
    signatureSink.addBool(this._topLevelDeclarations != null);
    this._topLevelDeclarations?.collectApiSignature(signatureSink);
    signatureSink.addBool(this._unlinkedUnit != null);
    this._unlinkedUnit?.collectApiSignature(signatureSink);
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "CUUN");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_contentDigest;
    fb.Offset? offset_topLevelDeclarations;
    fb.Offset? offset_unlinkedUnit;
    var contentDigest = _contentDigest;
    if (!(contentDigest == null || contentDigest.isEmpty)) {
      offset_contentDigest = fbBuilder.writeListUint32(contentDigest);
    }
    var topLevelDeclarations = _topLevelDeclarations;
    if (topLevelDeclarations != null) {
      offset_topLevelDeclarations = topLevelDeclarations.finish(fbBuilder);
    }
    var unlinkedUnit = _unlinkedUnit;
    if (unlinkedUnit != null) {
      offset_unlinkedUnit = unlinkedUnit.finish(fbBuilder);
    }
    fbBuilder.startTable();
    if (offset_contentDigest != null) {
      fbBuilder.addOffset(0, offset_contentDigest);
    }
    if (offset_topLevelDeclarations != null) {
      fbBuilder.addOffset(1, offset_topLevelDeclarations);
    }
    if (offset_unlinkedUnit != null) {
      fbBuilder.addOffset(2, offset_unlinkedUnit);
    }
    return fbBuilder.endTable();
  }
}

idl.CiderUnlinkedUnit readCiderUnlinkedUnit(List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _CiderUnlinkedUnitReader().read(rootRef, 0);
}

class _CiderUnlinkedUnitReader extends fb.TableReader<_CiderUnlinkedUnitImpl> {
  const _CiderUnlinkedUnitReader();

  @override
  _CiderUnlinkedUnitImpl createObject(fb.BufferContext bc, int offset) =>
      _CiderUnlinkedUnitImpl(bc, offset);
}

class _CiderUnlinkedUnitImpl extends Object
    with _CiderUnlinkedUnitMixin
    implements idl.CiderUnlinkedUnit {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _CiderUnlinkedUnitImpl(this._bc, this._bcOffset);

  List<int>? _contentDigest;
  idl.CiderUnitTopLevelDeclarations? _topLevelDeclarations;
  idl.UnlinkedUnit2? _unlinkedUnit;

  @override
  List<int> get contentDigest {
    return _contentDigest ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 0, const <int>[]);
  }

  @override
  idl.CiderUnitTopLevelDeclarations? get topLevelDeclarations {
    return _topLevelDeclarations ??=
        const _CiderUnitTopLevelDeclarationsReader()
            .vTableGetOrNull(_bc, _bcOffset, 1);
  }

  @override
  idl.UnlinkedUnit2? get unlinkedUnit {
    return _unlinkedUnit ??=
        const _UnlinkedUnit2Reader().vTableGetOrNull(_bc, _bcOffset, 2);
  }
}

abstract class _CiderUnlinkedUnitMixin implements idl.CiderUnlinkedUnit {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_contentDigest = contentDigest;
    if (local_contentDigest.isNotEmpty) {
      _result["contentDigest"] = local_contentDigest;
    }
    var local_topLevelDeclarations = topLevelDeclarations;
    if (local_topLevelDeclarations != null) {
      _result["topLevelDeclarations"] = local_topLevelDeclarations.toJson();
    }
    var local_unlinkedUnit = unlinkedUnit;
    if (local_unlinkedUnit != null) {
      _result["unlinkedUnit"] = local_unlinkedUnit.toJson();
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "contentDigest": contentDigest,
        "topLevelDeclarations": topLevelDeclarations,
        "unlinkedUnit": unlinkedUnit,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class DiagnosticMessageBuilder extends Object
    with _DiagnosticMessageMixin
    implements idl.DiagnosticMessage {
  String? _filePath;
  int? _length;
  String? _message;
  int? _offset;
  String? _url;

  @override
  String get filePath => _filePath ??= '';

  /// The absolute and normalized path of the file associated with this message.
  set filePath(String value) {
    this._filePath = value;
  }

  @override
  int get length => _length ??= 0;

  /// The length of the source range associated with this message.
  set length(int value) {
    assert(value >= 0);
    this._length = value;
  }

  @override
  String get message => _message ??= '';

  /// The text of the message.
  set message(String value) {
    this._message = value;
  }

  @override
  int get offset => _offset ??= 0;

  /// The zero-based offset from the start of the file to the beginning of the
  /// source range associated with this message.
  set offset(int value) {
    assert(value >= 0);
    this._offset = value;
  }

  @override
  String get url => _url ??= '';

  /// The URL of the message, if any.
  set url(String value) {
    this._url = value;
  }

  DiagnosticMessageBuilder(
      {String? filePath,
      int? length,
      String? message,
      int? offset,
      String? url})
      : _filePath = filePath,
        _length = length,
        _message = message,
        _offset = offset,
        _url = url;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addString(this._filePath ?? '');
    signatureSink.addInt(this._length ?? 0);
    signatureSink.addString(this._message ?? '');
    signatureSink.addInt(this._offset ?? 0);
    signatureSink.addString(this._url ?? '');
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_filePath;
    fb.Offset? offset_message;
    fb.Offset? offset_url;
    var filePath = _filePath;
    if (filePath != null) {
      offset_filePath = fbBuilder.writeString(filePath);
    }
    var message = _message;
    if (message != null) {
      offset_message = fbBuilder.writeString(message);
    }
    var url = _url;
    if (url != null) {
      offset_url = fbBuilder.writeString(url);
    }
    fbBuilder.startTable();
    if (offset_filePath != null) {
      fbBuilder.addOffset(0, offset_filePath);
    }
    fbBuilder.addUint32(1, _length, 0);
    if (offset_message != null) {
      fbBuilder.addOffset(2, offset_message);
    }
    fbBuilder.addUint32(3, _offset, 0);
    if (offset_url != null) {
      fbBuilder.addOffset(4, offset_url);
    }
    return fbBuilder.endTable();
  }
}

class _DiagnosticMessageReader extends fb.TableReader<_DiagnosticMessageImpl> {
  const _DiagnosticMessageReader();

  @override
  _DiagnosticMessageImpl createObject(fb.BufferContext bc, int offset) =>
      _DiagnosticMessageImpl(bc, offset);
}

class _DiagnosticMessageImpl extends Object
    with _DiagnosticMessageMixin
    implements idl.DiagnosticMessage {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _DiagnosticMessageImpl(this._bc, this._bcOffset);

  String? _filePath;
  int? _length;
  String? _message;
  int? _offset;
  String? _url;

  @override
  String get filePath {
    return _filePath ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
  }

  @override
  int get length {
    return _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
  }

  @override
  String get message {
    return _message ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
  }

  @override
  int get offset {
    return _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
  }

  @override
  String get url {
    return _url ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 4, '');
  }
}

abstract class _DiagnosticMessageMixin implements idl.DiagnosticMessage {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_filePath = filePath;
    if (local_filePath != '') {
      _result["filePath"] = local_filePath;
    }
    var local_length = length;
    if (local_length != 0) {
      _result["length"] = local_length;
    }
    var local_message = message;
    if (local_message != '') {
      _result["message"] = local_message;
    }
    var local_offset = offset;
    if (local_offset != 0) {
      _result["offset"] = local_offset;
    }
    var local_url = url;
    if (local_url != '') {
      _result["url"] = local_url;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "filePath": filePath,
        "length": length,
        "message": message,
        "offset": offset,
        "url": url,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class DirectiveInfoBuilder extends Object
    with _DirectiveInfoMixin
    implements idl.DirectiveInfo {
  List<String>? _templateNames;
  List<String>? _templateValues;

  @override
  List<String> get templateNames => _templateNames ??= <String>[];

  /// The names of the defined templates.
  set templateNames(List<String> value) {
    this._templateNames = value;
  }

  @override
  List<String> get templateValues => _templateValues ??= <String>[];

  /// The values of the defined templates.
  set templateValues(List<String> value) {
    this._templateValues = value;
  }

  DirectiveInfoBuilder(
      {List<String>? templateNames, List<String>? templateValues})
      : _templateNames = templateNames,
        _templateValues = templateValues;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var templateNames = this._templateNames;
    if (templateNames == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(templateNames.length);
      for (var x in templateNames) {
        signatureSink.addString(x);
      }
    }
    var templateValues = this._templateValues;
    if (templateValues == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(templateValues.length);
      for (var x in templateValues) {
        signatureSink.addString(x);
      }
    }
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_templateNames;
    fb.Offset? offset_templateValues;
    var templateNames = _templateNames;
    if (!(templateNames == null || templateNames.isEmpty)) {
      offset_templateNames = fbBuilder.writeList(
          templateNames.map((b) => fbBuilder.writeString(b)).toList());
    }
    var templateValues = _templateValues;
    if (!(templateValues == null || templateValues.isEmpty)) {
      offset_templateValues = fbBuilder.writeList(
          templateValues.map((b) => fbBuilder.writeString(b)).toList());
    }
    fbBuilder.startTable();
    if (offset_templateNames != null) {
      fbBuilder.addOffset(0, offset_templateNames);
    }
    if (offset_templateValues != null) {
      fbBuilder.addOffset(1, offset_templateValues);
    }
    return fbBuilder.endTable();
  }
}

class _DirectiveInfoReader extends fb.TableReader<_DirectiveInfoImpl> {
  const _DirectiveInfoReader();

  @override
  _DirectiveInfoImpl createObject(fb.BufferContext bc, int offset) =>
      _DirectiveInfoImpl(bc, offset);
}

class _DirectiveInfoImpl extends Object
    with _DirectiveInfoMixin
    implements idl.DirectiveInfo {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _DirectiveInfoImpl(this._bc, this._bcOffset);

  List<String>? _templateNames;
  List<String>? _templateValues;

  @override
  List<String> get templateNames {
    return _templateNames ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 0, const <String>[]);
  }

  @override
  List<String> get templateValues {
    return _templateValues ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 1, const <String>[]);
  }
}

abstract class _DirectiveInfoMixin implements idl.DirectiveInfo {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_templateNames = templateNames;
    if (local_templateNames.isNotEmpty) {
      _result["templateNames"] = local_templateNames;
    }
    var local_templateValues = templateValues;
    if (local_templateValues.isNotEmpty) {
      _result["templateValues"] = local_templateValues;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "templateNames": templateNames,
        "templateValues": templateValues,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class PackageBundleBuilder extends Object
    with _PackageBundleMixin
    implements idl.PackageBundle {
  int? _fake;

  @override
  int get fake => _fake ??= 0;

  /// The version 2 of the summary.
  set fake(int value) {
    assert(value >= 0);
    this._fake = value;
  }

  PackageBundleBuilder({int? fake}) : _fake = fake;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addInt(this._fake ?? 0);
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "PBdl");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fbBuilder.startTable();
    fbBuilder.addUint32(0, _fake, 0);
    return fbBuilder.endTable();
  }
}

idl.PackageBundle readPackageBundle(List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _PackageBundleReader().read(rootRef, 0);
}

class _PackageBundleReader extends fb.TableReader<_PackageBundleImpl> {
  const _PackageBundleReader();

  @override
  _PackageBundleImpl createObject(fb.BufferContext bc, int offset) =>
      _PackageBundleImpl(bc, offset);
}

class _PackageBundleImpl extends Object
    with _PackageBundleMixin
    implements idl.PackageBundle {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _PackageBundleImpl(this._bc, this._bcOffset);

  int? _fake;

  @override
  int get fake {
    return _fake ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
  }
}

abstract class _PackageBundleMixin implements idl.PackageBundle {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_fake = fake;
    if (local_fake != 0) {
      _result["fake"] = local_fake;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "fake": fake,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class UnlinkedNamespaceDirectiveBuilder extends Object
    with _UnlinkedNamespaceDirectiveMixin
    implements idl.UnlinkedNamespaceDirective {
  List<UnlinkedNamespaceDirectiveConfigurationBuilder>? _configurations;
  String? _uri;

  @override
  List<UnlinkedNamespaceDirectiveConfigurationBuilder> get configurations =>
      _configurations ??= <UnlinkedNamespaceDirectiveConfigurationBuilder>[];

  /// The configurations that control which library will actually be used.
  set configurations(
      List<UnlinkedNamespaceDirectiveConfigurationBuilder> value) {
    this._configurations = value;
  }

  @override
  String get uri => _uri ??= '';

  /// The URI referenced by this directive, nad used by default when none
  /// of the [configurations] matches.
  set uri(String value) {
    this._uri = value;
  }

  UnlinkedNamespaceDirectiveBuilder(
      {List<UnlinkedNamespaceDirectiveConfigurationBuilder>? configurations,
      String? uri})
      : _configurations = configurations,
        _uri = uri;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _configurations?.forEach((b) => b.flushInformative());
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var configurations = this._configurations;
    if (configurations == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(configurations.length);
      for (var x in configurations) {
        x.collectApiSignature(signatureSink);
      }
    }
    signatureSink.addString(this._uri ?? '');
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_configurations;
    fb.Offset? offset_uri;
    var configurations = _configurations;
    if (!(configurations == null || configurations.isEmpty)) {
      offset_configurations = fbBuilder
          .writeList(configurations.map((b) => b.finish(fbBuilder)).toList());
    }
    var uri = _uri;
    if (uri != null) {
      offset_uri = fbBuilder.writeString(uri);
    }
    fbBuilder.startTable();
    if (offset_configurations != null) {
      fbBuilder.addOffset(0, offset_configurations);
    }
    if (offset_uri != null) {
      fbBuilder.addOffset(1, offset_uri);
    }
    return fbBuilder.endTable();
  }
}

class _UnlinkedNamespaceDirectiveReader
    extends fb.TableReader<_UnlinkedNamespaceDirectiveImpl> {
  const _UnlinkedNamespaceDirectiveReader();

  @override
  _UnlinkedNamespaceDirectiveImpl createObject(
          fb.BufferContext bc, int offset) =>
      _UnlinkedNamespaceDirectiveImpl(bc, offset);
}

class _UnlinkedNamespaceDirectiveImpl extends Object
    with _UnlinkedNamespaceDirectiveMixin
    implements idl.UnlinkedNamespaceDirective {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _UnlinkedNamespaceDirectiveImpl(this._bc, this._bcOffset);

  List<idl.UnlinkedNamespaceDirectiveConfiguration>? _configurations;
  String? _uri;

  @override
  List<idl.UnlinkedNamespaceDirectiveConfiguration> get configurations {
    return _configurations ??=
        const fb.ListReader<idl.UnlinkedNamespaceDirectiveConfiguration>(
                _UnlinkedNamespaceDirectiveConfigurationReader())
            .vTableGet(_bc, _bcOffset, 0,
                const <idl.UnlinkedNamespaceDirectiveConfiguration>[]);
  }

  @override
  String get uri {
    return _uri ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
  }
}

abstract class _UnlinkedNamespaceDirectiveMixin
    implements idl.UnlinkedNamespaceDirective {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_configurations = configurations;
    if (local_configurations.isNotEmpty) {
      _result["configurations"] =
          local_configurations.map((_value) => _value.toJson()).toList();
    }
    var local_uri = uri;
    if (local_uri != '') {
      _result["uri"] = local_uri;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "configurations": configurations,
        "uri": uri,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class UnlinkedNamespaceDirectiveConfigurationBuilder extends Object
    with _UnlinkedNamespaceDirectiveConfigurationMixin
    implements idl.UnlinkedNamespaceDirectiveConfiguration {
  String? _name;
  String? _uri;
  String? _value;

  @override
  String get name => _name ??= '';

  /// The name of the declared variable used in the condition.
  set name(String value) {
    this._name = value;
  }

  @override
  String get uri => _uri ??= '';

  /// The URI to be used if the condition is true.
  set uri(String value) {
    this._uri = value;
  }

  @override
  String get value => _value ??= '';

  /// The value to which the value of the declared variable will be compared,
  /// or the empty string if the condition does not include an equality test.
  set value(String value) {
    this._value = value;
  }

  UnlinkedNamespaceDirectiveConfigurationBuilder(
      {String? name, String? uri, String? value})
      : _name = name,
        _uri = uri,
        _value = value;

  /// Flush [informative] data recursively.
  void flushInformative() {}

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    signatureSink.addString(this._name ?? '');
    signatureSink.addString(this._value ?? '');
    signatureSink.addString(this._uri ?? '');
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_name;
    fb.Offset? offset_uri;
    fb.Offset? offset_value;
    var name = _name;
    if (name != null) {
      offset_name = fbBuilder.writeString(name);
    }
    var uri = _uri;
    if (uri != null) {
      offset_uri = fbBuilder.writeString(uri);
    }
    var value = _value;
    if (value != null) {
      offset_value = fbBuilder.writeString(value);
    }
    fbBuilder.startTable();
    if (offset_name != null) {
      fbBuilder.addOffset(0, offset_name);
    }
    if (offset_uri != null) {
      fbBuilder.addOffset(2, offset_uri);
    }
    if (offset_value != null) {
      fbBuilder.addOffset(1, offset_value);
    }
    return fbBuilder.endTable();
  }
}

class _UnlinkedNamespaceDirectiveConfigurationReader
    extends fb.TableReader<_UnlinkedNamespaceDirectiveConfigurationImpl> {
  const _UnlinkedNamespaceDirectiveConfigurationReader();

  @override
  _UnlinkedNamespaceDirectiveConfigurationImpl createObject(
          fb.BufferContext bc, int offset) =>
      _UnlinkedNamespaceDirectiveConfigurationImpl(bc, offset);
}

class _UnlinkedNamespaceDirectiveConfigurationImpl extends Object
    with _UnlinkedNamespaceDirectiveConfigurationMixin
    implements idl.UnlinkedNamespaceDirectiveConfiguration {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _UnlinkedNamespaceDirectiveConfigurationImpl(this._bc, this._bcOffset);

  String? _name;
  String? _uri;
  String? _value;

  @override
  String get name {
    return _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
  }

  @override
  String get uri {
    return _uri ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
  }

  @override
  String get value {
    return _value ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
  }
}

abstract class _UnlinkedNamespaceDirectiveConfigurationMixin
    implements idl.UnlinkedNamespaceDirectiveConfiguration {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_name = name;
    if (local_name != '') {
      _result["name"] = local_name;
    }
    var local_uri = uri;
    if (local_uri != '') {
      _result["uri"] = local_uri;
    }
    var local_value = value;
    if (local_value != '') {
      _result["value"] = local_value;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "name": name,
        "uri": uri,
        "value": value,
      };

  @override
  String toString() => convert.json.encode(toJson());
}

class UnlinkedUnit2Builder extends Object
    with _UnlinkedUnit2Mixin
    implements idl.UnlinkedUnit2 {
  List<int>? _apiSignature;
  List<UnlinkedNamespaceDirectiveBuilder>? _exports;
  bool? _hasLibraryDirective;
  bool? _hasPartOfDirective;
  List<UnlinkedNamespaceDirectiveBuilder>? _imports;
  List<int>? _lineStarts;
  String? _partOfName;
  String? _partOfUri;
  List<String>? _parts;

  @override
  List<int> get apiSignature => _apiSignature ??= <int>[];

  /// The MD5 hash signature of the API portion of this unit. It depends on all
  /// tokens that might affect APIs of declarations in the unit.
  set apiSignature(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._apiSignature = value;
  }

  @override
  List<UnlinkedNamespaceDirectiveBuilder> get exports =>
      _exports ??= <UnlinkedNamespaceDirectiveBuilder>[];

  /// URIs of `export` directives.
  set exports(List<UnlinkedNamespaceDirectiveBuilder> value) {
    this._exports = value;
  }

  @override
  bool get hasLibraryDirective => _hasLibraryDirective ??= false;

  /// Is `true` if the unit contains a `library` directive.
  set hasLibraryDirective(bool value) {
    this._hasLibraryDirective = value;
  }

  @override
  bool get hasPartOfDirective => _hasPartOfDirective ??= false;

  /// Is `true` if the unit contains a `part of` directive.
  set hasPartOfDirective(bool value) {
    this._hasPartOfDirective = value;
  }

  @override
  List<UnlinkedNamespaceDirectiveBuilder> get imports =>
      _imports ??= <UnlinkedNamespaceDirectiveBuilder>[];

  /// URIs of `import` directives.
  set imports(List<UnlinkedNamespaceDirectiveBuilder> value) {
    this._imports = value;
  }

  @override
  List<int> get lineStarts => _lineStarts ??= <int>[];

  /// Offsets of the first character of each line in the source code.
  set lineStarts(List<int> value) {
    assert(value.every((e) => e >= 0));
    this._lineStarts = value;
  }

  @override
  String get partOfName => _partOfName ??= '';

  /// The library name of the `part of my.name;` directive.
  set partOfName(String value) {
    this._partOfName = value;
  }

  @override
  String get partOfUri => _partOfUri ??= '';

  /// URI of the `part of 'uri';` directive.
  set partOfUri(String value) {
    this._partOfUri = value;
  }

  @override
  List<String> get parts => _parts ??= <String>[];

  /// URIs of `part` directives.
  set parts(List<String> value) {
    this._parts = value;
  }

  UnlinkedUnit2Builder(
      {List<int>? apiSignature,
      List<UnlinkedNamespaceDirectiveBuilder>? exports,
      bool? hasLibraryDirective,
      bool? hasPartOfDirective,
      List<UnlinkedNamespaceDirectiveBuilder>? imports,
      List<int>? lineStarts,
      String? partOfName,
      String? partOfUri,
      List<String>? parts})
      : _apiSignature = apiSignature,
        _exports = exports,
        _hasLibraryDirective = hasLibraryDirective,
        _hasPartOfDirective = hasPartOfDirective,
        _imports = imports,
        _lineStarts = lineStarts,
        _partOfName = partOfName,
        _partOfUri = partOfUri,
        _parts = parts;

  /// Flush [informative] data recursively.
  void flushInformative() {
    _exports?.forEach((b) => b.flushInformative());
    _imports?.forEach((b) => b.flushInformative());
    _lineStarts = null;
  }

  /// Accumulate non-[informative] data into [signature].
  void collectApiSignature(api_sig.ApiSignature signatureSink) {
    var apiSignature = this._apiSignature;
    if (apiSignature == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(apiSignature.length);
      for (var x in apiSignature) {
        signatureSink.addInt(x);
      }
    }
    var exports = this._exports;
    if (exports == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(exports.length);
      for (var x in exports) {
        x.collectApiSignature(signatureSink);
      }
    }
    var imports = this._imports;
    if (imports == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(imports.length);
      for (var x in imports) {
        x.collectApiSignature(signatureSink);
      }
    }
    signatureSink.addBool(this._hasPartOfDirective == true);
    var parts = this._parts;
    if (parts == null) {
      signatureSink.addInt(0);
    } else {
      signatureSink.addInt(parts.length);
      for (var x in parts) {
        signatureSink.addString(x);
      }
    }
    signatureSink.addBool(this._hasLibraryDirective == true);
    signatureSink.addString(this._partOfUri ?? '');
    signatureSink.addString(this._partOfName ?? '');
  }

  List<int> toBuffer() {
    fb.Builder fbBuilder = fb.Builder();
    return fbBuilder.finish(finish(fbBuilder), "UUN2");
  }

  fb.Offset finish(fb.Builder fbBuilder) {
    fb.Offset? offset_apiSignature;
    fb.Offset? offset_exports;
    fb.Offset? offset_imports;
    fb.Offset? offset_lineStarts;
    fb.Offset? offset_partOfName;
    fb.Offset? offset_partOfUri;
    fb.Offset? offset_parts;
    var apiSignature = _apiSignature;
    if (!(apiSignature == null || apiSignature.isEmpty)) {
      offset_apiSignature = fbBuilder.writeListUint32(apiSignature);
    }
    var exports = _exports;
    if (!(exports == null || exports.isEmpty)) {
      offset_exports =
          fbBuilder.writeList(exports.map((b) => b.finish(fbBuilder)).toList());
    }
    var imports = _imports;
    if (!(imports == null || imports.isEmpty)) {
      offset_imports =
          fbBuilder.writeList(imports.map((b) => b.finish(fbBuilder)).toList());
    }
    var lineStarts = _lineStarts;
    if (!(lineStarts == null || lineStarts.isEmpty)) {
      offset_lineStarts = fbBuilder.writeListUint32(lineStarts);
    }
    var partOfName = _partOfName;
    if (partOfName != null) {
      offset_partOfName = fbBuilder.writeString(partOfName);
    }
    var partOfUri = _partOfUri;
    if (partOfUri != null) {
      offset_partOfUri = fbBuilder.writeString(partOfUri);
    }
    var parts = _parts;
    if (!(parts == null || parts.isEmpty)) {
      offset_parts = fbBuilder
          .writeList(parts.map((b) => fbBuilder.writeString(b)).toList());
    }
    fbBuilder.startTable();
    if (offset_apiSignature != null) {
      fbBuilder.addOffset(0, offset_apiSignature);
    }
    if (offset_exports != null) {
      fbBuilder.addOffset(1, offset_exports);
    }
    fbBuilder.addBool(6, _hasLibraryDirective == true);
    fbBuilder.addBool(3, _hasPartOfDirective == true);
    if (offset_imports != null) {
      fbBuilder.addOffset(2, offset_imports);
    }
    if (offset_lineStarts != null) {
      fbBuilder.addOffset(5, offset_lineStarts);
    }
    if (offset_partOfName != null) {
      fbBuilder.addOffset(8, offset_partOfName);
    }
    if (offset_partOfUri != null) {
      fbBuilder.addOffset(7, offset_partOfUri);
    }
    if (offset_parts != null) {
      fbBuilder.addOffset(4, offset_parts);
    }
    return fbBuilder.endTable();
  }
}

idl.UnlinkedUnit2 readUnlinkedUnit2(List<int> buffer) {
  fb.BufferContext rootRef = fb.BufferContext.fromBytes(buffer);
  return const _UnlinkedUnit2Reader().read(rootRef, 0);
}

class _UnlinkedUnit2Reader extends fb.TableReader<_UnlinkedUnit2Impl> {
  const _UnlinkedUnit2Reader();

  @override
  _UnlinkedUnit2Impl createObject(fb.BufferContext bc, int offset) =>
      _UnlinkedUnit2Impl(bc, offset);
}

class _UnlinkedUnit2Impl extends Object
    with _UnlinkedUnit2Mixin
    implements idl.UnlinkedUnit2 {
  final fb.BufferContext _bc;
  final int _bcOffset;

  _UnlinkedUnit2Impl(this._bc, this._bcOffset);

  List<int>? _apiSignature;
  List<idl.UnlinkedNamespaceDirective>? _exports;
  bool? _hasLibraryDirective;
  bool? _hasPartOfDirective;
  List<idl.UnlinkedNamespaceDirective>? _imports;
  List<int>? _lineStarts;
  String? _partOfName;
  String? _partOfUri;
  List<String>? _parts;

  @override
  List<int> get apiSignature {
    return _apiSignature ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 0, const <int>[]);
  }

  @override
  List<idl.UnlinkedNamespaceDirective> get exports {
    return _exports ??= const fb.ListReader<idl.UnlinkedNamespaceDirective>(
            _UnlinkedNamespaceDirectiveReader())
        .vTableGet(_bc, _bcOffset, 1, const <idl.UnlinkedNamespaceDirective>[]);
  }

  @override
  bool get hasLibraryDirective {
    return _hasLibraryDirective ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 6, false);
  }

  @override
  bool get hasPartOfDirective {
    return _hasPartOfDirective ??=
        const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
  }

  @override
  List<idl.UnlinkedNamespaceDirective> get imports {
    return _imports ??= const fb.ListReader<idl.UnlinkedNamespaceDirective>(
            _UnlinkedNamespaceDirectiveReader())
        .vTableGet(_bc, _bcOffset, 2, const <idl.UnlinkedNamespaceDirective>[]);
  }

  @override
  List<int> get lineStarts {
    return _lineStarts ??=
        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 5, const <int>[]);
  }

  @override
  String get partOfName {
    return _partOfName ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 8, '');
  }

  @override
  String get partOfUri {
    return _partOfUri ??=
        const fb.StringReader().vTableGet(_bc, _bcOffset, 7, '');
  }

  @override
  List<String> get parts {
    return _parts ??= const fb.ListReader<String>(fb.StringReader())
        .vTableGet(_bc, _bcOffset, 4, const <String>[]);
  }
}

abstract class _UnlinkedUnit2Mixin implements idl.UnlinkedUnit2 {
  @override
  Map<String, Object> toJson() {
    Map<String, Object> _result = <String, Object>{};
    var local_apiSignature = apiSignature;
    if (local_apiSignature.isNotEmpty) {
      _result["apiSignature"] = local_apiSignature;
    }
    var local_exports = exports;
    if (local_exports.isNotEmpty) {
      _result["exports"] =
          local_exports.map((_value) => _value.toJson()).toList();
    }
    var local_hasLibraryDirective = hasLibraryDirective;
    if (local_hasLibraryDirective != false) {
      _result["hasLibraryDirective"] = local_hasLibraryDirective;
    }
    var local_hasPartOfDirective = hasPartOfDirective;
    if (local_hasPartOfDirective != false) {
      _result["hasPartOfDirective"] = local_hasPartOfDirective;
    }
    var local_imports = imports;
    if (local_imports.isNotEmpty) {
      _result["imports"] =
          local_imports.map((_value) => _value.toJson()).toList();
    }
    var local_lineStarts = lineStarts;
    if (local_lineStarts.isNotEmpty) {
      _result["lineStarts"] = local_lineStarts;
    }
    var local_partOfName = partOfName;
    if (local_partOfName != '') {
      _result["partOfName"] = local_partOfName;
    }
    var local_partOfUri = partOfUri;
    if (local_partOfUri != '') {
      _result["partOfUri"] = local_partOfUri;
    }
    var local_parts = parts;
    if (local_parts.isNotEmpty) {
      _result["parts"] = local_parts;
    }
    return _result;
  }

  @override
  Map<String, Object?> toMap() => {
        "apiSignature": apiSignature,
        "exports": exports,
        "hasLibraryDirective": hasLibraryDirective,
        "hasPartOfDirective": hasPartOfDirective,
        "imports": imports,
        "lineStarts": lineStarts,
        "partOfName": partOfName,
        "partOfUri": partOfUri,
        "parts": parts,
      };

  @override
  String toString() => convert.json.encode(toJson());
}
