// Copyright (c) 2021, 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 code was auto-generated by tool/dap/generate_all.dart - do not hand-edit!

import 'protocol_common.dart';
import 'protocol_special.dart';

/// Arguments for 'attach' request. Additional attributes are implementation
/// specific.
class AttachRequestArguments extends RequestArguments {
  /// Optional data from the previous, restarted session.
  /// The data is sent as the 'restart' attribute of the 'terminated' event.
  /// The client should leave the data intact.
  final Object? restart;

  static AttachRequestArguments fromJson(Map<String, Object?> obj) =>
      AttachRequestArguments.fromMap(obj);

  AttachRequestArguments({
    this.restart,
  });

  AttachRequestArguments.fromMap(Map<String, Object?> obj)
      : restart = obj['__restart'];

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (restart != null) '__restart': restart,
      };
}

/// Response to 'attach' request. This is just an acknowledgement, so no body
/// field is required.
class AttachResponse extends Response {
  static AttachResponse fromJson(Map<String, Object?> obj) =>
      AttachResponse.fromMap(obj);

  AttachResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  AttachResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Information about a Breakpoint created in setBreakpoints,
/// setFunctionBreakpoints, setInstructionBreakpoints, or setDataBreakpoints.
class Breakpoint {
  /// An optional start column of the actual range covered by the breakpoint.
  final int? column;

  /// An optional end column of the actual range covered by the breakpoint.
  /// If no end line is given, then the end column is assumed to be in the start
  /// line.
  final int? endColumn;

  /// An optional end line of the actual range covered by the breakpoint.
  final int? endLine;

  /// An optional identifier for the breakpoint. It is needed if breakpoint
  /// events are used to update or remove breakpoints.
  final int? id;

  /// An optional memory reference to where the breakpoint is set.
  final String? instructionReference;

  /// The start line of the actual range covered by the breakpoint.
  final int? line;

  /// An optional message about the state of the breakpoint.
  /// This is shown to the user and can be used to explain why a breakpoint
  /// could not be verified.
  final String? message;

  /// An optional offset from the instruction reference.
  /// This can be negative.
  final int? offset;

  /// The source where the breakpoint is located.
  final Source? source;

  /// If true breakpoint could be set (but not necessarily at the desired
  /// location).
  final bool verified;

  static Breakpoint fromJson(Map<String, Object?> obj) =>
      Breakpoint.fromMap(obj);

  Breakpoint({
    this.column,
    this.endColumn,
    this.endLine,
    this.id,
    this.instructionReference,
    this.line,
    this.message,
    this.offset,
    this.source,
    required this.verified,
  });

  Breakpoint.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int?,
        endColumn = obj['endColumn'] as int?,
        endLine = obj['endLine'] as int?,
        id = obj['id'] as int?,
        instructionReference = obj['instructionReference'] as String?,
        line = obj['line'] as int?,
        message = obj['message'] as String?,
        offset = obj['offset'] as int?,
        source = obj['source'] == null
            ? null
            : Source.fromJson(obj['source'] as Map<String, Object?>),
        verified = obj['verified'] as bool;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['endColumn'] is! int?) {
      return false;
    }
    if (obj['endLine'] is! int?) {
      return false;
    }
    if (obj['id'] is! int?) {
      return false;
    }
    if (obj['instructionReference'] is! String?) {
      return false;
    }
    if (obj['line'] is! int?) {
      return false;
    }
    if (obj['message'] is! String?) {
      return false;
    }
    if (obj['offset'] is! int?) {
      return false;
    }
    if (!Source?.canParse(obj['source'])) {
      return false;
    }
    if (obj['verified'] is! bool) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (column != null) 'column': column,
        if (endColumn != null) 'endColumn': endColumn,
        if (endLine != null) 'endLine': endLine,
        if (id != null) 'id': id,
        if (instructionReference != null)
          'instructionReference': instructionReference,
        if (line != null) 'line': line,
        if (message != null) 'message': message,
        if (offset != null) 'offset': offset,
        if (source != null) 'source': source,
        'verified': verified,
      };
}

/// Properties of a breakpoint location returned from the 'breakpointLocations'
/// request.
class BreakpointLocation {
  /// Optional start column of breakpoint location.
  final int? column;

  /// Optional end column of breakpoint location if the location covers a range.
  final int? endColumn;

  /// Optional end line of breakpoint location if the location covers a range.
  final int? endLine;

  /// Start line of breakpoint location.
  final int line;

  static BreakpointLocation fromJson(Map<String, Object?> obj) =>
      BreakpointLocation.fromMap(obj);

  BreakpointLocation({
    this.column,
    this.endColumn,
    this.endLine,
    required this.line,
  });

  BreakpointLocation.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int?,
        endColumn = obj['endColumn'] as int?,
        endLine = obj['endLine'] as int?,
        line = obj['line'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['endColumn'] is! int?) {
      return false;
    }
    if (obj['endLine'] is! int?) {
      return false;
    }
    if (obj['line'] is! int) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (column != null) 'column': column,
        if (endColumn != null) 'endColumn': endColumn,
        if (endLine != null) 'endLine': endLine,
        'line': line,
      };
}

/// Arguments for 'breakpointLocations' request.
class BreakpointLocationsArguments extends RequestArguments {
  /// Optional start column of range to search possible breakpoint locations in.
  /// If no start column is given, the first column in the start line is
  /// assumed.
  final int? column;

  /// Optional end column of range to search possible breakpoint locations in.
  /// If no end column is given, then it is assumed to be in the last column of
  /// the end line.
  final int? endColumn;

  /// Optional end line of range to search possible breakpoint locations in. If
  /// no end line is given, then the end line is assumed to be the start line.
  final int? endLine;

  /// Start line of range to search possible breakpoint locations in. If only
  /// the line is specified, the request returns all possible locations in that
  /// line.
  final int line;

  /// The source location of the breakpoints; either 'source.path' or
  /// 'source.reference' must be specified.
  final Source source;

  static BreakpointLocationsArguments fromJson(Map<String, Object?> obj) =>
      BreakpointLocationsArguments.fromMap(obj);

  BreakpointLocationsArguments({
    this.column,
    this.endColumn,
    this.endLine,
    required this.line,
    required this.source,
  });

  BreakpointLocationsArguments.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int?,
        endColumn = obj['endColumn'] as int?,
        endLine = obj['endLine'] as int?,
        line = obj['line'] as int,
        source = Source.fromJson(obj['source'] as Map<String, Object?>);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['endColumn'] is! int?) {
      return false;
    }
    if (obj['endLine'] is! int?) {
      return false;
    }
    if (obj['line'] is! int) {
      return false;
    }
    if (!Source.canParse(obj['source'])) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (column != null) 'column': column,
        if (endColumn != null) 'endColumn': endColumn,
        if (endLine != null) 'endLine': endLine,
        'line': line,
        'source': source,
      };
}

/// Response to 'breakpointLocations' request.
/// Contains possible locations for source breakpoints.
class BreakpointLocationsResponse extends Response {
  static BreakpointLocationsResponse fromJson(Map<String, Object?> obj) =>
      BreakpointLocationsResponse.fromMap(obj);

  BreakpointLocationsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  BreakpointLocationsResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'cancel' request.
class CancelArguments extends RequestArguments {
  /// The ID (attribute 'progressId') of the progress to cancel. If missing no
  /// progress is cancelled.
  /// Both a 'requestId' and a 'progressId' can be specified in one request.
  final String? progressId;

  /// The ID (attribute 'seq') of the request to cancel. If missing no request
  /// is cancelled.
  /// Both a 'requestId' and a 'progressId' can be specified in one request.
  final int? requestId;

  static CancelArguments fromJson(Map<String, Object?> obj) =>
      CancelArguments.fromMap(obj);

  CancelArguments({
    this.progressId,
    this.requestId,
  });

  CancelArguments.fromMap(Map<String, Object?> obj)
      : progressId = obj['progressId'] as String?,
        requestId = obj['requestId'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['progressId'] is! String?) {
      return false;
    }
    if (obj['requestId'] is! int?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (progressId != null) 'progressId': progressId,
        if (requestId != null) 'requestId': requestId,
      };
}

/// Response to 'cancel' request. This is just an acknowledgement, so no body
/// field is required.
class CancelResponse extends Response {
  static CancelResponse fromJson(Map<String, Object?> obj) =>
      CancelResponse.fromMap(obj);

  CancelResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  CancelResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Information about the capabilities of a debug adapter.
class Capabilities {
  /// The set of additional module information exposed by the debug adapter.
  final List<ColumnDescriptor>? additionalModuleColumns;

  /// The set of characters that should trigger completion in a REPL. If not
  /// specified, the UI should assume the '.' character.
  final List<String>? completionTriggerCharacters;

  /// Available exception filter options for the 'setExceptionBreakpoints'
  /// request.
  final List<ExceptionBreakpointsFilter>? exceptionBreakpointFilters;

  /// The debug adapter supports the 'suspendDebuggee' attribute on the
  /// 'disconnect' request.
  final bool? supportSuspendDebuggee;

  /// The debug adapter supports the 'terminateDebuggee' attribute on the
  /// 'disconnect' request.
  final bool? supportTerminateDebuggee;

  /// Checksum algorithms supported by the debug adapter.
  final List<ChecksumAlgorithm>? supportedChecksumAlgorithms;

  /// The debug adapter supports the 'breakpointLocations' request.
  final bool? supportsBreakpointLocationsRequest;

  /// The debug adapter supports the 'cancel' request.
  final bool? supportsCancelRequest;

  /// The debug adapter supports the 'clipboard' context value in the 'evaluate'
  /// request.
  final bool? supportsClipboardContext;

  /// The debug adapter supports the 'completions' request.
  final bool? supportsCompletionsRequest;

  /// The debug adapter supports conditional breakpoints.
  final bool? supportsConditionalBreakpoints;

  /// The debug adapter supports the 'configurationDone' request.
  final bool? supportsConfigurationDoneRequest;

  /// The debug adapter supports data breakpoints.
  final bool? supportsDataBreakpoints;

  /// The debug adapter supports the delayed loading of parts of the stack,
  /// which requires that both the 'startFrame' and 'levels' arguments and an
  /// optional 'totalFrames' result of the 'StackTrace' request are supported.
  final bool? supportsDelayedStackTraceLoading;

  /// The debug adapter supports the 'disassemble' request.
  final bool? supportsDisassembleRequest;

  /// The debug adapter supports a (side effect free) evaluate request for data
  /// hovers.
  final bool? supportsEvaluateForHovers;

  /// The debug adapter supports 'filterOptions' as an argument on the
  /// 'setExceptionBreakpoints' request.
  final bool? supportsExceptionFilterOptions;

  /// The debug adapter supports the 'exceptionInfo' request.
  final bool? supportsExceptionInfoRequest;

  /// The debug adapter supports 'exceptionOptions' on the
  /// setExceptionBreakpoints request.
  final bool? supportsExceptionOptions;

  /// The debug adapter supports function breakpoints.
  final bool? supportsFunctionBreakpoints;

  /// The debug adapter supports the 'gotoTargets' request.
  final bool? supportsGotoTargetsRequest;

  /// The debug adapter supports breakpoints that break execution after a
  /// specified number of hits.
  final bool? supportsHitConditionalBreakpoints;

  /// The debug adapter supports adding breakpoints based on instruction
  /// references.
  final bool? supportsInstructionBreakpoints;

  /// The debug adapter supports the 'loadedSources' request.
  final bool? supportsLoadedSourcesRequest;

  /// The debug adapter supports logpoints by interpreting the 'logMessage'
  /// attribute of the SourceBreakpoint.
  final bool? supportsLogPoints;

  /// The debug adapter supports the 'modules' request.
  final bool? supportsModulesRequest;

  /// The debug adapter supports the 'readMemory' request.
  final bool? supportsReadMemoryRequest;

  /// The debug adapter supports restarting a frame.
  final bool? supportsRestartFrame;

  /// The debug adapter supports the 'restart' request. In this case a client
  /// should not implement 'restart' by terminating and relaunching the adapter
  /// but by calling the RestartRequest.
  final bool? supportsRestartRequest;

  /// The debug adapter supports the 'setExpression' request.
  final bool? supportsSetExpression;

  /// The debug adapter supports setting a variable to a value.
  final bool? supportsSetVariable;

  /// The debug adapter supports stepping back via the 'stepBack' and
  /// 'reverseContinue' requests.
  final bool? supportsStepBack;

  /// The debug adapter supports the 'stepInTargets' request.
  final bool? supportsStepInTargetsRequest;

  /// The debug adapter supports stepping granularities (argument 'granularity')
  /// for the stepping requests.
  final bool? supportsSteppingGranularity;

  /// The debug adapter supports the 'terminate' request.
  final bool? supportsTerminateRequest;

  /// The debug adapter supports the 'terminateThreads' request.
  final bool? supportsTerminateThreadsRequest;

  /// The debug adapter supports a 'format' attribute on the stackTraceRequest,
  /// variablesRequest, and evaluateRequest.
  final bool? supportsValueFormattingOptions;

  static Capabilities fromJson(Map<String, Object?> obj) =>
      Capabilities.fromMap(obj);

  Capabilities({
    this.additionalModuleColumns,
    this.completionTriggerCharacters,
    this.exceptionBreakpointFilters,
    this.supportSuspendDebuggee,
    this.supportTerminateDebuggee,
    this.supportedChecksumAlgorithms,
    this.supportsBreakpointLocationsRequest,
    this.supportsCancelRequest,
    this.supportsClipboardContext,
    this.supportsCompletionsRequest,
    this.supportsConditionalBreakpoints,
    this.supportsConfigurationDoneRequest,
    this.supportsDataBreakpoints,
    this.supportsDelayedStackTraceLoading,
    this.supportsDisassembleRequest,
    this.supportsEvaluateForHovers,
    this.supportsExceptionFilterOptions,
    this.supportsExceptionInfoRequest,
    this.supportsExceptionOptions,
    this.supportsFunctionBreakpoints,
    this.supportsGotoTargetsRequest,
    this.supportsHitConditionalBreakpoints,
    this.supportsInstructionBreakpoints,
    this.supportsLoadedSourcesRequest,
    this.supportsLogPoints,
    this.supportsModulesRequest,
    this.supportsReadMemoryRequest,
    this.supportsRestartFrame,
    this.supportsRestartRequest,
    this.supportsSetExpression,
    this.supportsSetVariable,
    this.supportsStepBack,
    this.supportsStepInTargetsRequest,
    this.supportsSteppingGranularity,
    this.supportsTerminateRequest,
    this.supportsTerminateThreadsRequest,
    this.supportsValueFormattingOptions,
  });

  Capabilities.fromMap(Map<String, Object?> obj)
      : additionalModuleColumns = (obj['additionalModuleColumns'] as List?)
            ?.map((item) =>
                ColumnDescriptor.fromJson(item as Map<String, Object?>))
            .toList(),
        completionTriggerCharacters =
            (obj['completionTriggerCharacters'] as List?)
                ?.map((item) => item as String)
                .toList(),
        exceptionBreakpointFilters =
            (obj['exceptionBreakpointFilters'] as List?)
                ?.map((item) => ExceptionBreakpointsFilter.fromJson(
                    item as Map<String, Object?>))
                .toList(),
        supportSuspendDebuggee = obj['supportSuspendDebuggee'] as bool?,
        supportTerminateDebuggee = obj['supportTerminateDebuggee'] as bool?,
        supportedChecksumAlgorithms =
            (obj['supportedChecksumAlgorithms'] as List?)
                ?.map((item) =>
                    ChecksumAlgorithm.fromJson(item as Map<String, Object?>))
                .toList(),
        supportsBreakpointLocationsRequest =
            obj['supportsBreakpointLocationsRequest'] as bool?,
        supportsCancelRequest = obj['supportsCancelRequest'] as bool?,
        supportsClipboardContext = obj['supportsClipboardContext'] as bool?,
        supportsCompletionsRequest = obj['supportsCompletionsRequest'] as bool?,
        supportsConditionalBreakpoints =
            obj['supportsConditionalBreakpoints'] as bool?,
        supportsConfigurationDoneRequest =
            obj['supportsConfigurationDoneRequest'] as bool?,
        supportsDataBreakpoints = obj['supportsDataBreakpoints'] as bool?,
        supportsDelayedStackTraceLoading =
            obj['supportsDelayedStackTraceLoading'] as bool?,
        supportsDisassembleRequest = obj['supportsDisassembleRequest'] as bool?,
        supportsEvaluateForHovers = obj['supportsEvaluateForHovers'] as bool?,
        supportsExceptionFilterOptions =
            obj['supportsExceptionFilterOptions'] as bool?,
        supportsExceptionInfoRequest =
            obj['supportsExceptionInfoRequest'] as bool?,
        supportsExceptionOptions = obj['supportsExceptionOptions'] as bool?,
        supportsFunctionBreakpoints =
            obj['supportsFunctionBreakpoints'] as bool?,
        supportsGotoTargetsRequest = obj['supportsGotoTargetsRequest'] as bool?,
        supportsHitConditionalBreakpoints =
            obj['supportsHitConditionalBreakpoints'] as bool?,
        supportsInstructionBreakpoints =
            obj['supportsInstructionBreakpoints'] as bool?,
        supportsLoadedSourcesRequest =
            obj['supportsLoadedSourcesRequest'] as bool?,
        supportsLogPoints = obj['supportsLogPoints'] as bool?,
        supportsModulesRequest = obj['supportsModulesRequest'] as bool?,
        supportsReadMemoryRequest = obj['supportsReadMemoryRequest'] as bool?,
        supportsRestartFrame = obj['supportsRestartFrame'] as bool?,
        supportsRestartRequest = obj['supportsRestartRequest'] as bool?,
        supportsSetExpression = obj['supportsSetExpression'] as bool?,
        supportsSetVariable = obj['supportsSetVariable'] as bool?,
        supportsStepBack = obj['supportsStepBack'] as bool?,
        supportsStepInTargetsRequest =
            obj['supportsStepInTargetsRequest'] as bool?,
        supportsSteppingGranularity =
            obj['supportsSteppingGranularity'] as bool?,
        supportsTerminateRequest = obj['supportsTerminateRequest'] as bool?,
        supportsTerminateThreadsRequest =
            obj['supportsTerminateThreadsRequest'] as bool?,
        supportsValueFormattingOptions =
            obj['supportsValueFormattingOptions'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['additionalModuleColumns'] is! List ||
        (obj['additionalModuleColumns']
            .any((item) => !ColumnDescriptor.canParse(item))))) {
      return false;
    }
    if ((obj['completionTriggerCharacters'] is! List ||
        (obj['completionTriggerCharacters'].any((item) => item is! String)))) {
      return false;
    }
    if ((obj['exceptionBreakpointFilters'] is! List ||
        (obj['exceptionBreakpointFilters']
            .any((item) => !ExceptionBreakpointsFilter.canParse(item))))) {
      return false;
    }
    if (obj['supportSuspendDebuggee'] is! bool?) {
      return false;
    }
    if (obj['supportTerminateDebuggee'] is! bool?) {
      return false;
    }
    if ((obj['supportedChecksumAlgorithms'] is! List ||
        (obj['supportedChecksumAlgorithms']
            .any((item) => !ChecksumAlgorithm.canParse(item))))) {
      return false;
    }
    if (obj['supportsBreakpointLocationsRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsCancelRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsClipboardContext'] is! bool?) {
      return false;
    }
    if (obj['supportsCompletionsRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsConditionalBreakpoints'] is! bool?) {
      return false;
    }
    if (obj['supportsConfigurationDoneRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsDataBreakpoints'] is! bool?) {
      return false;
    }
    if (obj['supportsDelayedStackTraceLoading'] is! bool?) {
      return false;
    }
    if (obj['supportsDisassembleRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsEvaluateForHovers'] is! bool?) {
      return false;
    }
    if (obj['supportsExceptionFilterOptions'] is! bool?) {
      return false;
    }
    if (obj['supportsExceptionInfoRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsExceptionOptions'] is! bool?) {
      return false;
    }
    if (obj['supportsFunctionBreakpoints'] is! bool?) {
      return false;
    }
    if (obj['supportsGotoTargetsRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsHitConditionalBreakpoints'] is! bool?) {
      return false;
    }
    if (obj['supportsInstructionBreakpoints'] is! bool?) {
      return false;
    }
    if (obj['supportsLoadedSourcesRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsLogPoints'] is! bool?) {
      return false;
    }
    if (obj['supportsModulesRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsReadMemoryRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsRestartFrame'] is! bool?) {
      return false;
    }
    if (obj['supportsRestartRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsSetExpression'] is! bool?) {
      return false;
    }
    if (obj['supportsSetVariable'] is! bool?) {
      return false;
    }
    if (obj['supportsStepBack'] is! bool?) {
      return false;
    }
    if (obj['supportsStepInTargetsRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsSteppingGranularity'] is! bool?) {
      return false;
    }
    if (obj['supportsTerminateRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsTerminateThreadsRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsValueFormattingOptions'] is! bool?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (additionalModuleColumns != null)
          'additionalModuleColumns': additionalModuleColumns,
        if (completionTriggerCharacters != null)
          'completionTriggerCharacters': completionTriggerCharacters,
        if (exceptionBreakpointFilters != null)
          'exceptionBreakpointFilters': exceptionBreakpointFilters,
        if (supportSuspendDebuggee != null)
          'supportSuspendDebuggee': supportSuspendDebuggee,
        if (supportTerminateDebuggee != null)
          'supportTerminateDebuggee': supportTerminateDebuggee,
        if (supportedChecksumAlgorithms != null)
          'supportedChecksumAlgorithms': supportedChecksumAlgorithms,
        if (supportsBreakpointLocationsRequest != null)
          'supportsBreakpointLocationsRequest':
              supportsBreakpointLocationsRequest,
        if (supportsCancelRequest != null)
          'supportsCancelRequest': supportsCancelRequest,
        if (supportsClipboardContext != null)
          'supportsClipboardContext': supportsClipboardContext,
        if (supportsCompletionsRequest != null)
          'supportsCompletionsRequest': supportsCompletionsRequest,
        if (supportsConditionalBreakpoints != null)
          'supportsConditionalBreakpoints': supportsConditionalBreakpoints,
        if (supportsConfigurationDoneRequest != null)
          'supportsConfigurationDoneRequest': supportsConfigurationDoneRequest,
        if (supportsDataBreakpoints != null)
          'supportsDataBreakpoints': supportsDataBreakpoints,
        if (supportsDelayedStackTraceLoading != null)
          'supportsDelayedStackTraceLoading': supportsDelayedStackTraceLoading,
        if (supportsDisassembleRequest != null)
          'supportsDisassembleRequest': supportsDisassembleRequest,
        if (supportsEvaluateForHovers != null)
          'supportsEvaluateForHovers': supportsEvaluateForHovers,
        if (supportsExceptionFilterOptions != null)
          'supportsExceptionFilterOptions': supportsExceptionFilterOptions,
        if (supportsExceptionInfoRequest != null)
          'supportsExceptionInfoRequest': supportsExceptionInfoRequest,
        if (supportsExceptionOptions != null)
          'supportsExceptionOptions': supportsExceptionOptions,
        if (supportsFunctionBreakpoints != null)
          'supportsFunctionBreakpoints': supportsFunctionBreakpoints,
        if (supportsGotoTargetsRequest != null)
          'supportsGotoTargetsRequest': supportsGotoTargetsRequest,
        if (supportsHitConditionalBreakpoints != null)
          'supportsHitConditionalBreakpoints':
              supportsHitConditionalBreakpoints,
        if (supportsInstructionBreakpoints != null)
          'supportsInstructionBreakpoints': supportsInstructionBreakpoints,
        if (supportsLoadedSourcesRequest != null)
          'supportsLoadedSourcesRequest': supportsLoadedSourcesRequest,
        if (supportsLogPoints != null) 'supportsLogPoints': supportsLogPoints,
        if (supportsModulesRequest != null)
          'supportsModulesRequest': supportsModulesRequest,
        if (supportsReadMemoryRequest != null)
          'supportsReadMemoryRequest': supportsReadMemoryRequest,
        if (supportsRestartFrame != null)
          'supportsRestartFrame': supportsRestartFrame,
        if (supportsRestartRequest != null)
          'supportsRestartRequest': supportsRestartRequest,
        if (supportsSetExpression != null)
          'supportsSetExpression': supportsSetExpression,
        if (supportsSetVariable != null)
          'supportsSetVariable': supportsSetVariable,
        if (supportsStepBack != null) 'supportsStepBack': supportsStepBack,
        if (supportsStepInTargetsRequest != null)
          'supportsStepInTargetsRequest': supportsStepInTargetsRequest,
        if (supportsSteppingGranularity != null)
          'supportsSteppingGranularity': supportsSteppingGranularity,
        if (supportsTerminateRequest != null)
          'supportsTerminateRequest': supportsTerminateRequest,
        if (supportsTerminateThreadsRequest != null)
          'supportsTerminateThreadsRequest': supportsTerminateThreadsRequest,
        if (supportsValueFormattingOptions != null)
          'supportsValueFormattingOptions': supportsValueFormattingOptions,
      };
}

/// The checksum of an item calculated by the specified algorithm.
class Checksum {
  /// The algorithm used to calculate this checksum.
  final ChecksumAlgorithm algorithm;

  /// Value of the checksum.
  final String checksum;

  static Checksum fromJson(Map<String, Object?> obj) => Checksum.fromMap(obj);

  Checksum({
    required this.algorithm,
    required this.checksum,
  });

  Checksum.fromMap(Map<String, Object?> obj)
      : algorithm = ChecksumAlgorithm.fromJson(
            obj['algorithm'] as Map<String, Object?>),
        checksum = obj['checksum'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!ChecksumAlgorithm.canParse(obj['algorithm'])) {
      return false;
    }
    if (obj['checksum'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'algorithm': algorithm,
        'checksum': checksum,
      };
}

/// Names of checksum algorithms that may be supported by a debug adapter.
class ChecksumAlgorithm {
  static ChecksumAlgorithm fromJson(Map<String, Object?> obj) =>
      ChecksumAlgorithm.fromMap(obj);

  ChecksumAlgorithm();

  ChecksumAlgorithm.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// A ColumnDescriptor specifies what module attribute to show in a column of
/// the ModulesView, how to format it,
/// and what the column's label should be.
/// It is only used if the underlying UI actually supports this level of
/// customization.
class ColumnDescriptor {
  /// Name of the attribute rendered in this column.
  final String attributeName;

  /// Format to use for the rendered values in this column. TBD how the format
  /// strings looks like.
  final String? format;

  /// Header UI label of column.
  final String label;

  /// Datatype of values in this column.  Defaults to 'string' if not specified.
  final String? type;

  /// Width of this column in characters (hint only).
  final int? width;

  static ColumnDescriptor fromJson(Map<String, Object?> obj) =>
      ColumnDescriptor.fromMap(obj);

  ColumnDescriptor({
    required this.attributeName,
    this.format,
    required this.label,
    this.type,
    this.width,
  });

  ColumnDescriptor.fromMap(Map<String, Object?> obj)
      : attributeName = obj['attributeName'] as String,
        format = obj['format'] as String?,
        label = obj['label'] as String,
        type = obj['type'] as String?,
        width = obj['width'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['attributeName'] is! String) {
      return false;
    }
    if (obj['format'] is! String?) {
      return false;
    }
    if (obj['label'] is! String) {
      return false;
    }
    if (obj['type'] is! String?) {
      return false;
    }
    if (obj['width'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'attributeName': attributeName,
        if (format != null) 'format': format,
        'label': label,
        if (type != null) 'type': type,
        if (width != null) 'width': width,
      };
}

/// CompletionItems are the suggestions returned from the CompletionsRequest.
class CompletionItem {
  /// The label of this completion item. By default this is also the text that
  /// is inserted when selecting this completion.
  final String label;

  /// This value determines how many characters are overwritten by the
  /// completion text.
  /// If missing the value 0 is assumed which results in the completion text
  /// being inserted.
  final int? length;

  /// Determines the length of the new selection after the text has been
  /// inserted (or replaced).
  /// The selection can not extend beyond the bounds of the completion text.
  /// If omitted the length is assumed to be 0.
  final int? selectionLength;

  /// Determines the start of the new selection after the text has been inserted
  /// (or replaced).
  /// The start position must in the range 0 and length of the completion text.
  /// If omitted the selection starts at the end of the completion text.
  final int? selectionStart;

  /// A string that should be used when comparing this item with other items.
  /// When `falsy` the label is used.
  final String? sortText;

  /// This value determines the location (in the CompletionsRequest's 'text'
  /// attribute) where the completion text is added.
  /// If missing the text is added at the location specified by the
  /// CompletionsRequest's 'column' attribute.
  final int? start;

  /// If text is not falsy then it is inserted instead of the label.
  final String? text;

  /// The item's type. Typically the client uses this information to render the
  /// item in the UI with an icon.
  final CompletionItemType? type;

  static CompletionItem fromJson(Map<String, Object?> obj) =>
      CompletionItem.fromMap(obj);

  CompletionItem({
    required this.label,
    this.length,
    this.selectionLength,
    this.selectionStart,
    this.sortText,
    this.start,
    this.text,
    this.type,
  });

  CompletionItem.fromMap(Map<String, Object?> obj)
      : label = obj['label'] as String,
        length = obj['length'] as int?,
        selectionLength = obj['selectionLength'] as int?,
        selectionStart = obj['selectionStart'] as int?,
        sortText = obj['sortText'] as String?,
        start = obj['start'] as int?,
        text = obj['text'] as String?,
        type = obj['type'] == null
            ? null
            : CompletionItemType.fromJson(obj['type'] as Map<String, Object?>);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['label'] is! String) {
      return false;
    }
    if (obj['length'] is! int?) {
      return false;
    }
    if (obj['selectionLength'] is! int?) {
      return false;
    }
    if (obj['selectionStart'] is! int?) {
      return false;
    }
    if (obj['sortText'] is! String?) {
      return false;
    }
    if (obj['start'] is! int?) {
      return false;
    }
    if (obj['text'] is! String?) {
      return false;
    }
    if (!CompletionItemType?.canParse(obj['type'])) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'label': label,
        if (length != null) 'length': length,
        if (selectionLength != null) 'selectionLength': selectionLength,
        if (selectionStart != null) 'selectionStart': selectionStart,
        if (sortText != null) 'sortText': sortText,
        if (start != null) 'start': start,
        if (text != null) 'text': text,
        if (type != null) 'type': type,
      };
}

/// Some predefined types for the CompletionItem. Please note that not all
/// clients have specific icons for all of them.
class CompletionItemType {
  static CompletionItemType fromJson(Map<String, Object?> obj) =>
      CompletionItemType.fromMap(obj);

  CompletionItemType();

  CompletionItemType.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Arguments for 'completions' request.
class CompletionsArguments extends RequestArguments {
  /// The character position for which to determine the completion proposals.
  final int column;

  /// Returns completions in the scope of this stack frame. If not specified,
  /// the completions are returned for the global scope.
  final int? frameId;

  /// An optional line for which to determine the completion proposals. If
  /// missing the first line of the text is assumed.
  final int? line;

  /// One or more source lines. Typically this is the text a user has typed into
  /// the debug console before he asked for completion.
  final String text;

  static CompletionsArguments fromJson(Map<String, Object?> obj) =>
      CompletionsArguments.fromMap(obj);

  CompletionsArguments({
    required this.column,
    this.frameId,
    this.line,
    required this.text,
  });

  CompletionsArguments.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int,
        frameId = obj['frameId'] as int?,
        line = obj['line'] as int?,
        text = obj['text'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int) {
      return false;
    }
    if (obj['frameId'] is! int?) {
      return false;
    }
    if (obj['line'] is! int?) {
      return false;
    }
    if (obj['text'] is! String) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'column': column,
        if (frameId != null) 'frameId': frameId,
        if (line != null) 'line': line,
        'text': text,
      };
}

/// Response to 'completions' request.
class CompletionsResponse extends Response {
  static CompletionsResponse fromJson(Map<String, Object?> obj) =>
      CompletionsResponse.fromMap(obj);

  CompletionsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  CompletionsResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'configurationDone' request.
class ConfigurationDoneArguments extends RequestArguments {
  static ConfigurationDoneArguments fromJson(Map<String, Object?> obj) =>
      ConfigurationDoneArguments.fromMap(obj);

  ConfigurationDoneArguments();

  ConfigurationDoneArguments.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {};
}

/// Response to 'configurationDone' request. This is just an acknowledgement, so
/// no body field is required.
class ConfigurationDoneResponse extends Response {
  static ConfigurationDoneResponse fromJson(Map<String, Object?> obj) =>
      ConfigurationDoneResponse.fromMap(obj);

  ConfigurationDoneResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ConfigurationDoneResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'continue' request.
class ContinueArguments extends RequestArguments {
  /// Continue execution for the specified thread (if possible).
  /// If the backend cannot continue on a single thread but will continue on all
  /// threads, it should set the 'allThreadsContinued' attribute in the response
  /// to true.
  final int threadId;

  static ContinueArguments fromJson(Map<String, Object?> obj) =>
      ContinueArguments.fromMap(obj);

  ContinueArguments({
    required this.threadId,
  });

  ContinueArguments.fromMap(Map<String, Object?> obj)
      : threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'threadId': threadId,
      };
}

/// Response to 'continue' request.
class ContinueResponse extends Response {
  static ContinueResponse fromJson(Map<String, Object?> obj) =>
      ContinueResponse.fromMap(obj);

  ContinueResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ContinueResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Properties of a data breakpoint passed to the setDataBreakpoints request.
class DataBreakpoint {
  /// The access type of the data.
  final DataBreakpointAccessType? accessType;

  /// An optional expression for conditional breakpoints.
  final String? condition;

  /// An id representing the data. This id is returned from the
  /// dataBreakpointInfo request.
  final String dataId;

  /// An optional expression that controls how many hits of the breakpoint are
  /// ignored.
  /// The backend is expected to interpret the expression as needed.
  final String? hitCondition;

  static DataBreakpoint fromJson(Map<String, Object?> obj) =>
      DataBreakpoint.fromMap(obj);

  DataBreakpoint({
    this.accessType,
    this.condition,
    required this.dataId,
    this.hitCondition,
  });

  DataBreakpoint.fromMap(Map<String, Object?> obj)
      : accessType = obj['accessType'] == null
            ? null
            : DataBreakpointAccessType.fromJson(
                obj['accessType'] as Map<String, Object?>),
        condition = obj['condition'] as String?,
        dataId = obj['dataId'] as String,
        hitCondition = obj['hitCondition'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!DataBreakpointAccessType?.canParse(obj['accessType'])) {
      return false;
    }
    if (obj['condition'] is! String?) {
      return false;
    }
    if (obj['dataId'] is! String) {
      return false;
    }
    if (obj['hitCondition'] is! String?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (accessType != null) 'accessType': accessType,
        if (condition != null) 'condition': condition,
        'dataId': dataId,
        if (hitCondition != null) 'hitCondition': hitCondition,
      };
}

/// This enumeration defines all possible access types for data breakpoints.
class DataBreakpointAccessType {
  static DataBreakpointAccessType fromJson(Map<String, Object?> obj) =>
      DataBreakpointAccessType.fromMap(obj);

  DataBreakpointAccessType();

  DataBreakpointAccessType.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Arguments for 'dataBreakpointInfo' request.
class DataBreakpointInfoArguments extends RequestArguments {
  /// The name of the Variable's child to obtain data breakpoint information
  /// for.
  /// If variablesReference isn’t provided, this can be an expression.
  final String name;

  /// Reference to the Variable container if the data breakpoint is requested
  /// for a child of the container.
  final int? variablesReference;

  static DataBreakpointInfoArguments fromJson(Map<String, Object?> obj) =>
      DataBreakpointInfoArguments.fromMap(obj);

  DataBreakpointInfoArguments({
    required this.name,
    this.variablesReference,
  });

  DataBreakpointInfoArguments.fromMap(Map<String, Object?> obj)
      : name = obj['name'] as String,
        variablesReference = obj['variablesReference'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    if (obj['variablesReference'] is! int?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'name': name,
        if (variablesReference != null)
          'variablesReference': variablesReference,
      };
}

/// Response to 'dataBreakpointInfo' request.
class DataBreakpointInfoResponse extends Response {
  static DataBreakpointInfoResponse fromJson(Map<String, Object?> obj) =>
      DataBreakpointInfoResponse.fromMap(obj);

  DataBreakpointInfoResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  DataBreakpointInfoResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'disassemble' request.
class DisassembleArguments extends RequestArguments {
  /// Number of instructions to disassemble starting at the specified location
  /// and offset.
  /// An adapter must return exactly this number of instructions - any
  /// unavailable instructions should be replaced with an implementation-defined
  /// 'invalid instruction' value.
  final int instructionCount;

  /// Optional offset (in instructions) to be applied after the byte offset (if
  /// any) before disassembling. Can be negative.
  final int? instructionOffset;

  /// Memory reference to the base location containing the instructions to
  /// disassemble.
  final String memoryReference;

  /// Optional offset (in bytes) to be applied to the reference location before
  /// disassembling. Can be negative.
  final int? offset;

  /// If true, the adapter should attempt to resolve memory addresses and other
  /// values to symbolic names.
  final bool? resolveSymbols;

  static DisassembleArguments fromJson(Map<String, Object?> obj) =>
      DisassembleArguments.fromMap(obj);

  DisassembleArguments({
    required this.instructionCount,
    this.instructionOffset,
    required this.memoryReference,
    this.offset,
    this.resolveSymbols,
  });

  DisassembleArguments.fromMap(Map<String, Object?> obj)
      : instructionCount = obj['instructionCount'] as int,
        instructionOffset = obj['instructionOffset'] as int?,
        memoryReference = obj['memoryReference'] as String,
        offset = obj['offset'] as int?,
        resolveSymbols = obj['resolveSymbols'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['instructionCount'] is! int) {
      return false;
    }
    if (obj['instructionOffset'] is! int?) {
      return false;
    }
    if (obj['memoryReference'] is! String) {
      return false;
    }
    if (obj['offset'] is! int?) {
      return false;
    }
    if (obj['resolveSymbols'] is! bool?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'instructionCount': instructionCount,
        if (instructionOffset != null) 'instructionOffset': instructionOffset,
        'memoryReference': memoryReference,
        if (offset != null) 'offset': offset,
        if (resolveSymbols != null) 'resolveSymbols': resolveSymbols,
      };
}

/// Response to 'disassemble' request.
class DisassembleResponse extends Response {
  static DisassembleResponse fromJson(Map<String, Object?> obj) =>
      DisassembleResponse.fromMap(obj);

  DisassembleResponse({
    Map<String, Object?>? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  DisassembleResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>?) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Represents a single disassembled instruction.
class DisassembledInstruction {
  /// The address of the instruction. Treated as a hex value if prefixed with
  /// '0x', or as a decimal value otherwise.
  final String address;

  /// The column within the line that corresponds to this instruction, if any.
  final int? column;

  /// The end column of the range that corresponds to this instruction, if any.
  final int? endColumn;

  /// The end line of the range that corresponds to this instruction, if any.
  final int? endLine;

  /// Text representing the instruction and its operands, in an
  /// implementation-defined format.
  final String instruction;

  /// Optional raw bytes representing the instruction and its operands, in an
  /// implementation-defined format.
  final String? instructionBytes;

  /// The line within the source location that corresponds to this instruction,
  /// if any.
  final int? line;

  /// Source location that corresponds to this instruction, if any.
  /// Should always be set (if available) on the first instruction returned,
  /// but can be omitted afterwards if this instruction maps to the same source
  /// file as the previous instruction.
  final Source? location;

  /// Name of the symbol that corresponds with the location of this instruction,
  /// if any.
  final String? symbol;

  static DisassembledInstruction fromJson(Map<String, Object?> obj) =>
      DisassembledInstruction.fromMap(obj);

  DisassembledInstruction({
    required this.address,
    this.column,
    this.endColumn,
    this.endLine,
    required this.instruction,
    this.instructionBytes,
    this.line,
    this.location,
    this.symbol,
  });

  DisassembledInstruction.fromMap(Map<String, Object?> obj)
      : address = obj['address'] as String,
        column = obj['column'] as int?,
        endColumn = obj['endColumn'] as int?,
        endLine = obj['endLine'] as int?,
        instruction = obj['instruction'] as String,
        instructionBytes = obj['instructionBytes'] as String?,
        line = obj['line'] as int?,
        location = obj['location'] == null
            ? null
            : Source.fromJson(obj['location'] as Map<String, Object?>),
        symbol = obj['symbol'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['address'] is! String) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['endColumn'] is! int?) {
      return false;
    }
    if (obj['endLine'] is! int?) {
      return false;
    }
    if (obj['instruction'] is! String) {
      return false;
    }
    if (obj['instructionBytes'] is! String?) {
      return false;
    }
    if (obj['line'] is! int?) {
      return false;
    }
    if (!Source?.canParse(obj['location'])) {
      return false;
    }
    if (obj['symbol'] is! String?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'address': address,
        if (column != null) 'column': column,
        if (endColumn != null) 'endColumn': endColumn,
        if (endLine != null) 'endLine': endLine,
        'instruction': instruction,
        if (instructionBytes != null) 'instructionBytes': instructionBytes,
        if (line != null) 'line': line,
        if (location != null) 'location': location,
        if (symbol != null) 'symbol': symbol,
      };
}

/// Arguments for 'disconnect' request.
class DisconnectArguments extends RequestArguments {
  /// A value of true indicates that this 'disconnect' request is part of a
  /// restart sequence.
  final bool? restart;

  /// Indicates whether the debuggee should stay suspended when the debugger is
  /// disconnected.
  /// If unspecified, the debuggee should resume execution.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportSuspendDebuggee' is true.
  final bool? suspendDebuggee;

  /// Indicates whether the debuggee should be terminated when the debugger is
  /// disconnected.
  /// If unspecified, the debug adapter is free to do whatever it thinks is
  /// best.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportTerminateDebuggee' is true.
  final bool? terminateDebuggee;

  static DisconnectArguments fromJson(Map<String, Object?> obj) =>
      DisconnectArguments.fromMap(obj);

  DisconnectArguments({
    this.restart,
    this.suspendDebuggee,
    this.terminateDebuggee,
  });

  DisconnectArguments.fromMap(Map<String, Object?> obj)
      : restart = obj['restart'] as bool?,
        suspendDebuggee = obj['suspendDebuggee'] as bool?,
        terminateDebuggee = obj['terminateDebuggee'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['restart'] is! bool?) {
      return false;
    }
    if (obj['suspendDebuggee'] is! bool?) {
      return false;
    }
    if (obj['terminateDebuggee'] is! bool?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (restart != null) 'restart': restart,
        if (suspendDebuggee != null) 'suspendDebuggee': suspendDebuggee,
        if (terminateDebuggee != null) 'terminateDebuggee': terminateDebuggee,
      };
}

/// Response to 'disconnect' request. This is just an acknowledgement, so no
/// body field is required.
class DisconnectResponse extends Response {
  static DisconnectResponse fromJson(Map<String, Object?> obj) =>
      DisconnectResponse.fromMap(obj);

  DisconnectResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  DisconnectResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// On error (whenever 'success' is false), the body can provide more details.
class ErrorResponse extends Response {
  static ErrorResponse fromJson(Map<String, Object?> obj) =>
      ErrorResponse.fromMap(obj);

  ErrorResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ErrorResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'evaluate' request.
class EvaluateArguments extends RequestArguments {
  /// The context in which the evaluate request is run.
  final String? context;

  /// The expression to evaluate.
  final String expression;

  /// Specifies details on how to format the Evaluate result.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsValueFormattingOptions' is true.
  final ValueFormat? format;

  /// Evaluate the expression in the scope of this stack frame. If not
  /// specified, the expression is evaluated in the global scope.
  final int? frameId;

  static EvaluateArguments fromJson(Map<String, Object?> obj) =>
      EvaluateArguments.fromMap(obj);

  EvaluateArguments({
    this.context,
    required this.expression,
    this.format,
    this.frameId,
  });

  EvaluateArguments.fromMap(Map<String, Object?> obj)
      : context = obj['context'] as String?,
        expression = obj['expression'] as String,
        format = obj['format'] == null
            ? null
            : ValueFormat.fromJson(obj['format'] as Map<String, Object?>),
        frameId = obj['frameId'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['context'] is! String?) {
      return false;
    }
    if (obj['expression'] is! String) {
      return false;
    }
    if (!ValueFormat?.canParse(obj['format'])) {
      return false;
    }
    if (obj['frameId'] is! int?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (context != null) 'context': context,
        'expression': expression,
        if (format != null) 'format': format,
        if (frameId != null) 'frameId': frameId,
      };
}

/// Response to 'evaluate' request.
class EvaluateResponse extends Response {
  static EvaluateResponse fromJson(Map<String, Object?> obj) =>
      EvaluateResponse.fromMap(obj);

  EvaluateResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  EvaluateResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A debug adapter initiated event.
class Event extends ProtocolMessage {
  /// Event-specific information.
  final Object? body;

  /// Type of event.
  final String event;

  static Event fromJson(Map<String, Object?> obj) => Event.fromMap(obj);

  Event({
    this.body,
    required this.event,
    required int seq,
  }) : super(
          seq: seq,
          type: 'event',
        );

  Event.fromMap(Map<String, Object?> obj)
      : body = obj['body'],
        event = obj['event'] as String,
        super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['event'] is! String) {
      return false;
    }
    if (obj['type'] is! String) {
      return false;
    }
    return ProtocolMessage.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
        if (body != null) 'body': body,
        'event': event,
      };
}

/// This enumeration defines all possible conditions when a thrown exception
/// should result in a break.
/// never: never breaks,
/// always: always breaks,
/// unhandled: breaks when exception unhandled,
/// userUnhandled: breaks if the exception is not handled by user code.
class ExceptionBreakMode {
  static ExceptionBreakMode fromJson(Map<String, Object?> obj) =>
      ExceptionBreakMode.fromMap(obj);

  ExceptionBreakMode();

  ExceptionBreakMode.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// An ExceptionBreakpointsFilter is shown in the UI as an filter option for
/// configuring how exceptions are dealt with.
class ExceptionBreakpointsFilter {
  /// An optional help text providing information about the condition. This
  /// string is shown as the placeholder text for a text box and must be
  /// translated.
  final String? conditionDescription;

  /// Initial value of the filter option. If not specified a value 'false' is
  /// assumed.
  final bool? defaultValue;

  /// An optional help text providing additional information about the exception
  /// filter. This string is typically shown as a hover and must be translated.
  final String? description;

  /// The internal ID of the filter option. This value is passed to the
  /// 'setExceptionBreakpoints' request.
  final String filter;

  /// The name of the filter option. This will be shown in the UI.
  final String label;

  /// Controls whether a condition can be specified for this filter option. If
  /// false or missing, a condition can not be set.
  final bool? supportsCondition;

  static ExceptionBreakpointsFilter fromJson(Map<String, Object?> obj) =>
      ExceptionBreakpointsFilter.fromMap(obj);

  ExceptionBreakpointsFilter({
    this.conditionDescription,
    this.defaultValue,
    this.description,
    required this.filter,
    required this.label,
    this.supportsCondition,
  });

  ExceptionBreakpointsFilter.fromMap(Map<String, Object?> obj)
      : conditionDescription = obj['conditionDescription'] as String?,
        defaultValue = obj['default'] as bool?,
        description = obj['description'] as String?,
        filter = obj['filter'] as String,
        label = obj['label'] as String,
        supportsCondition = obj['supportsCondition'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['conditionDescription'] is! String?) {
      return false;
    }
    if (obj['default'] is! bool?) {
      return false;
    }
    if (obj['description'] is! String?) {
      return false;
    }
    if (obj['filter'] is! String) {
      return false;
    }
    if (obj['label'] is! String) {
      return false;
    }
    if (obj['supportsCondition'] is! bool?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (conditionDescription != null)
          'conditionDescription': conditionDescription,
        if (defaultValue != null) 'default': defaultValue,
        if (description != null) 'description': description,
        'filter': filter,
        'label': label,
        if (supportsCondition != null) 'supportsCondition': supportsCondition,
      };
}

/// Detailed information about an exception that has occurred.
class ExceptionDetails {
  /// Optional expression that can be evaluated in the current scope to obtain
  /// the exception object.
  final String? evaluateName;

  /// Fully-qualified type name of the exception object.
  final String? fullTypeName;

  /// Details of the exception contained by this exception, if any.
  final List<ExceptionDetails>? innerException;

  /// Message contained in the exception.
  final String? message;

  /// Stack trace at the time the exception was thrown.
  final String? stackTrace;

  /// Short type name of the exception object.
  final String? typeName;

  static ExceptionDetails fromJson(Map<String, Object?> obj) =>
      ExceptionDetails.fromMap(obj);

  ExceptionDetails({
    this.evaluateName,
    this.fullTypeName,
    this.innerException,
    this.message,
    this.stackTrace,
    this.typeName,
  });

  ExceptionDetails.fromMap(Map<String, Object?> obj)
      : evaluateName = obj['evaluateName'] as String?,
        fullTypeName = obj['fullTypeName'] as String?,
        innerException = (obj['innerException'] as List?)
            ?.map((item) =>
                ExceptionDetails.fromJson(item as Map<String, Object?>))
            .toList(),
        message = obj['message'] as String?,
        stackTrace = obj['stackTrace'] as String?,
        typeName = obj['typeName'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['evaluateName'] is! String?) {
      return false;
    }
    if (obj['fullTypeName'] is! String?) {
      return false;
    }
    if ((obj['innerException'] is! List ||
        (obj['innerException']
            .any((item) => !ExceptionDetails.canParse(item))))) {
      return false;
    }
    if (obj['message'] is! String?) {
      return false;
    }
    if (obj['stackTrace'] is! String?) {
      return false;
    }
    if (obj['typeName'] is! String?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (evaluateName != null) 'evaluateName': evaluateName,
        if (fullTypeName != null) 'fullTypeName': fullTypeName,
        if (innerException != null) 'innerException': innerException,
        if (message != null) 'message': message,
        if (stackTrace != null) 'stackTrace': stackTrace,
        if (typeName != null) 'typeName': typeName,
      };
}

/// An ExceptionFilterOptions is used to specify an exception filter together
/// with a condition for the setExceptionsFilter request.
class ExceptionFilterOptions {
  /// An optional expression for conditional exceptions.
  /// The exception will break into the debugger if the result of the condition
  /// is true.
  final String? condition;

  /// ID of an exception filter returned by the 'exceptionBreakpointFilters'
  /// capability.
  final String filterId;

  static ExceptionFilterOptions fromJson(Map<String, Object?> obj) =>
      ExceptionFilterOptions.fromMap(obj);

  ExceptionFilterOptions({
    this.condition,
    required this.filterId,
  });

  ExceptionFilterOptions.fromMap(Map<String, Object?> obj)
      : condition = obj['condition'] as String?,
        filterId = obj['filterId'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['condition'] is! String?) {
      return false;
    }
    if (obj['filterId'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (condition != null) 'condition': condition,
        'filterId': filterId,
      };
}

/// Arguments for 'exceptionInfo' request.
class ExceptionInfoArguments extends RequestArguments {
  /// Thread for which exception information should be retrieved.
  final int threadId;

  static ExceptionInfoArguments fromJson(Map<String, Object?> obj) =>
      ExceptionInfoArguments.fromMap(obj);

  ExceptionInfoArguments({
    required this.threadId,
  });

  ExceptionInfoArguments.fromMap(Map<String, Object?> obj)
      : threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'threadId': threadId,
      };
}

/// Response to 'exceptionInfo' request.
class ExceptionInfoResponse extends Response {
  static ExceptionInfoResponse fromJson(Map<String, Object?> obj) =>
      ExceptionInfoResponse.fromMap(obj);

  ExceptionInfoResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ExceptionInfoResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// An ExceptionOptions assigns configuration options to a set of exceptions.
class ExceptionOptions {
  /// Condition when a thrown exception should result in a break.
  final ExceptionBreakMode breakMode;

  /// A path that selects a single or multiple exceptions in a tree. If 'path'
  /// is missing, the whole tree is selected.
  /// By convention the first segment of the path is a category that is used to
  /// group exceptions in the UI.
  final List<ExceptionPathSegment>? path;

  static ExceptionOptions fromJson(Map<String, Object?> obj) =>
      ExceptionOptions.fromMap(obj);

  ExceptionOptions({
    required this.breakMode,
    this.path,
  });

  ExceptionOptions.fromMap(Map<String, Object?> obj)
      : breakMode = ExceptionBreakMode.fromJson(
            obj['breakMode'] as Map<String, Object?>),
        path = (obj['path'] as List?)
            ?.map((item) =>
                ExceptionPathSegment.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!ExceptionBreakMode.canParse(obj['breakMode'])) {
      return false;
    }
    if ((obj['path'] is! List ||
        (obj['path'].any((item) => !ExceptionPathSegment.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'breakMode': breakMode,
        if (path != null) 'path': path,
      };
}

/// An ExceptionPathSegment represents a segment in a path that is used to match
/// leafs or nodes in a tree of exceptions.
/// If a segment consists of more than one name, it matches the names provided
/// if 'negate' is false or missing or
/// it matches anything except the names provided if 'negate' is true.
class ExceptionPathSegment {
  /// Depending on the value of 'negate' the names that should match or not
  /// match.
  final List<String> names;

  /// If false or missing this segment matches the names provided, otherwise it
  /// matches anything except the names provided.
  final bool? negate;

  static ExceptionPathSegment fromJson(Map<String, Object?> obj) =>
      ExceptionPathSegment.fromMap(obj);

  ExceptionPathSegment({
    required this.names,
    this.negate,
  });

  ExceptionPathSegment.fromMap(Map<String, Object?> obj)
      : names = (obj['names'] as List).map((item) => item as String).toList(),
        negate = obj['negate'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['names'] is! List ||
        (obj['names'].any((item) => item is! String)))) {
      return false;
    }
    if (obj['negate'] is! bool?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'names': names,
        if (negate != null) 'negate': negate,
      };
}

/// Properties of a breakpoint passed to the setFunctionBreakpoints request.
class FunctionBreakpoint {
  /// An optional expression for conditional breakpoints.
  /// It is only honored by a debug adapter if the capability
  /// 'supportsConditionalBreakpoints' is true.
  final String? condition;

  /// An optional expression that controls how many hits of the breakpoint are
  /// ignored.
  /// The backend is expected to interpret the expression as needed.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsHitConditionalBreakpoints' is true.
  final String? hitCondition;

  /// The name of the function.
  final String name;

  static FunctionBreakpoint fromJson(Map<String, Object?> obj) =>
      FunctionBreakpoint.fromMap(obj);

  FunctionBreakpoint({
    this.condition,
    this.hitCondition,
    required this.name,
  });

  FunctionBreakpoint.fromMap(Map<String, Object?> obj)
      : condition = obj['condition'] as String?,
        hitCondition = obj['hitCondition'] as String?,
        name = obj['name'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['condition'] is! String?) {
      return false;
    }
    if (obj['hitCondition'] is! String?) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (condition != null) 'condition': condition,
        if (hitCondition != null) 'hitCondition': hitCondition,
        'name': name,
      };
}

/// Arguments for 'goto' request.
class GotoArguments extends RequestArguments {
  /// The location where the debuggee will continue to run.
  final int targetId;

  /// Set the goto target for this thread.
  final int threadId;

  static GotoArguments fromJson(Map<String, Object?> obj) =>
      GotoArguments.fromMap(obj);

  GotoArguments({
    required this.targetId,
    required this.threadId,
  });

  GotoArguments.fromMap(Map<String, Object?> obj)
      : targetId = obj['targetId'] as int,
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['targetId'] is! int) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'targetId': targetId,
        'threadId': threadId,
      };
}

/// Response to 'goto' request. This is just an acknowledgement, so no body
/// field is required.
class GotoResponse extends Response {
  static GotoResponse fromJson(Map<String, Object?> obj) =>
      GotoResponse.fromMap(obj);

  GotoResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  GotoResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A GotoTarget describes a code location that can be used as a target in the
/// 'goto' request.
/// The possible goto targets can be determined via the 'gotoTargets' request.
class GotoTarget {
  /// An optional column of the goto target.
  final int? column;

  /// An optional end column of the range covered by the goto target.
  final int? endColumn;

  /// An optional end line of the range covered by the goto target.
  final int? endLine;

  /// Unique identifier for a goto target. This is used in the goto request.
  final int id;

  /// Optional memory reference for the instruction pointer value represented by
  /// this target.
  final String? instructionPointerReference;

  /// The name of the goto target (shown in the UI).
  final String label;

  /// The line of the goto target.
  final int line;

  static GotoTarget fromJson(Map<String, Object?> obj) =>
      GotoTarget.fromMap(obj);

  GotoTarget({
    this.column,
    this.endColumn,
    this.endLine,
    required this.id,
    this.instructionPointerReference,
    required this.label,
    required this.line,
  });

  GotoTarget.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int?,
        endColumn = obj['endColumn'] as int?,
        endLine = obj['endLine'] as int?,
        id = obj['id'] as int,
        instructionPointerReference =
            obj['instructionPointerReference'] as String?,
        label = obj['label'] as String,
        line = obj['line'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['endColumn'] is! int?) {
      return false;
    }
    if (obj['endLine'] is! int?) {
      return false;
    }
    if (obj['id'] is! int) {
      return false;
    }
    if (obj['instructionPointerReference'] is! String?) {
      return false;
    }
    if (obj['label'] is! String) {
      return false;
    }
    if (obj['line'] is! int) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (column != null) 'column': column,
        if (endColumn != null) 'endColumn': endColumn,
        if (endLine != null) 'endLine': endLine,
        'id': id,
        if (instructionPointerReference != null)
          'instructionPointerReference': instructionPointerReference,
        'label': label,
        'line': line,
      };
}

/// Arguments for 'gotoTargets' request.
class GotoTargetsArguments extends RequestArguments {
  /// An optional column location for which the goto targets are determined.
  final int? column;

  /// The line location for which the goto targets are determined.
  final int line;

  /// The source location for which the goto targets are determined.
  final Source source;

  static GotoTargetsArguments fromJson(Map<String, Object?> obj) =>
      GotoTargetsArguments.fromMap(obj);

  GotoTargetsArguments({
    this.column,
    required this.line,
    required this.source,
  });

  GotoTargetsArguments.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int?,
        line = obj['line'] as int,
        source = Source.fromJson(obj['source'] as Map<String, Object?>);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['line'] is! int) {
      return false;
    }
    if (!Source.canParse(obj['source'])) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (column != null) 'column': column,
        'line': line,
        'source': source,
      };
}

/// Response to 'gotoTargets' request.
class GotoTargetsResponse extends Response {
  static GotoTargetsResponse fromJson(Map<String, Object?> obj) =>
      GotoTargetsResponse.fromMap(obj);

  GotoTargetsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  GotoTargetsResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'initialize' request.
class InitializeRequestArguments extends RequestArguments {
  /// The ID of the debug adapter.
  final String adapterID;

  /// The ID of the (frontend) client using this adapter.
  final String? clientID;

  /// The human readable name of the (frontend) client using this adapter.
  final String? clientName;

  /// If true all column numbers are 1-based (default).
  final bool? columnsStartAt1;

  /// If true all line numbers are 1-based (default).
  final bool? linesStartAt1;

  /// The ISO-639 locale of the (frontend) client using this adapter, e.g. en-US
  /// or de-CH.
  final String? locale;

  /// Determines in what format paths are specified. The default is 'path',
  /// which is the native format.
  final String? pathFormat;

  /// Client supports the invalidated event.
  final bool? supportsInvalidatedEvent;

  /// Client supports memory references.
  final bool? supportsMemoryReferences;

  /// Client supports progress reporting.
  final bool? supportsProgressReporting;

  /// Client supports the runInTerminal request.
  final bool? supportsRunInTerminalRequest;

  /// Client supports the paging of variables.
  final bool? supportsVariablePaging;

  /// Client supports the optional type attribute for variables.
  final bool? supportsVariableType;

  static InitializeRequestArguments fromJson(Map<String, Object?> obj) =>
      InitializeRequestArguments.fromMap(obj);

  InitializeRequestArguments({
    required this.adapterID,
    this.clientID,
    this.clientName,
    this.columnsStartAt1,
    this.linesStartAt1,
    this.locale,
    this.pathFormat,
    this.supportsInvalidatedEvent,
    this.supportsMemoryReferences,
    this.supportsProgressReporting,
    this.supportsRunInTerminalRequest,
    this.supportsVariablePaging,
    this.supportsVariableType,
  });

  InitializeRequestArguments.fromMap(Map<String, Object?> obj)
      : adapterID = obj['adapterID'] as String,
        clientID = obj['clientID'] as String?,
        clientName = obj['clientName'] as String?,
        columnsStartAt1 = obj['columnsStartAt1'] as bool?,
        linesStartAt1 = obj['linesStartAt1'] as bool?,
        locale = obj['locale'] as String?,
        pathFormat = obj['pathFormat'] as String?,
        supportsInvalidatedEvent = obj['supportsInvalidatedEvent'] as bool?,
        supportsMemoryReferences = obj['supportsMemoryReferences'] as bool?,
        supportsProgressReporting = obj['supportsProgressReporting'] as bool?,
        supportsRunInTerminalRequest =
            obj['supportsRunInTerminalRequest'] as bool?,
        supportsVariablePaging = obj['supportsVariablePaging'] as bool?,
        supportsVariableType = obj['supportsVariableType'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['adapterID'] is! String) {
      return false;
    }
    if (obj['clientID'] is! String?) {
      return false;
    }
    if (obj['clientName'] is! String?) {
      return false;
    }
    if (obj['columnsStartAt1'] is! bool?) {
      return false;
    }
    if (obj['linesStartAt1'] is! bool?) {
      return false;
    }
    if (obj['locale'] is! String?) {
      return false;
    }
    if (obj['pathFormat'] is! String?) {
      return false;
    }
    if (obj['supportsInvalidatedEvent'] is! bool?) {
      return false;
    }
    if (obj['supportsMemoryReferences'] is! bool?) {
      return false;
    }
    if (obj['supportsProgressReporting'] is! bool?) {
      return false;
    }
    if (obj['supportsRunInTerminalRequest'] is! bool?) {
      return false;
    }
    if (obj['supportsVariablePaging'] is! bool?) {
      return false;
    }
    if (obj['supportsVariableType'] is! bool?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'adapterID': adapterID,
        if (clientID != null) 'clientID': clientID,
        if (clientName != null) 'clientName': clientName,
        if (columnsStartAt1 != null) 'columnsStartAt1': columnsStartAt1,
        if (linesStartAt1 != null) 'linesStartAt1': linesStartAt1,
        if (locale != null) 'locale': locale,
        if (pathFormat != null) 'pathFormat': pathFormat,
        if (supportsInvalidatedEvent != null)
          'supportsInvalidatedEvent': supportsInvalidatedEvent,
        if (supportsMemoryReferences != null)
          'supportsMemoryReferences': supportsMemoryReferences,
        if (supportsProgressReporting != null)
          'supportsProgressReporting': supportsProgressReporting,
        if (supportsRunInTerminalRequest != null)
          'supportsRunInTerminalRequest': supportsRunInTerminalRequest,
        if (supportsVariablePaging != null)
          'supportsVariablePaging': supportsVariablePaging,
        if (supportsVariableType != null)
          'supportsVariableType': supportsVariableType,
      };
}

/// Response to 'initialize' request.
class InitializeResponse extends Response {
  static InitializeResponse fromJson(Map<String, Object?> obj) =>
      InitializeResponse.fromMap(obj);

  InitializeResponse({
    Capabilities? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  InitializeResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!Capabilities?.canParse(obj['body'])) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Properties of a breakpoint passed to the setInstructionBreakpoints request
class InstructionBreakpoint {
  /// An optional expression for conditional breakpoints.
  /// It is only honored by a debug adapter if the capability
  /// 'supportsConditionalBreakpoints' is true.
  final String? condition;

  /// An optional expression that controls how many hits of the breakpoint are
  /// ignored.
  /// The backend is expected to interpret the expression as needed.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsHitConditionalBreakpoints' is true.
  final String? hitCondition;

  /// The instruction reference of the breakpoint.
  /// This should be a memory or instruction pointer reference from an
  /// EvaluateResponse, Variable, StackFrame, GotoTarget, or Breakpoint.
  final String instructionReference;

  /// An optional offset from the instruction reference.
  /// This can be negative.
  final int? offset;

  static InstructionBreakpoint fromJson(Map<String, Object?> obj) =>
      InstructionBreakpoint.fromMap(obj);

  InstructionBreakpoint({
    this.condition,
    this.hitCondition,
    required this.instructionReference,
    this.offset,
  });

  InstructionBreakpoint.fromMap(Map<String, Object?> obj)
      : condition = obj['condition'] as String?,
        hitCondition = obj['hitCondition'] as String?,
        instructionReference = obj['instructionReference'] as String,
        offset = obj['offset'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['condition'] is! String?) {
      return false;
    }
    if (obj['hitCondition'] is! String?) {
      return false;
    }
    if (obj['instructionReference'] is! String) {
      return false;
    }
    if (obj['offset'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (condition != null) 'condition': condition,
        if (hitCondition != null) 'hitCondition': hitCondition,
        'instructionReference': instructionReference,
        if (offset != null) 'offset': offset,
      };
}

/// Logical areas that can be invalidated by the 'invalidated' event.
class InvalidatedAreas {
  static InvalidatedAreas fromJson(Map<String, Object?> obj) =>
      InvalidatedAreas.fromMap(obj);

  InvalidatedAreas();

  InvalidatedAreas.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Arguments for 'launch' request. Additional attributes are implementation
/// specific.
class LaunchRequestArguments extends RequestArguments {
  /// Optional data from the previous, restarted session.
  /// The data is sent as the 'restart' attribute of the 'terminated' event.
  /// The client should leave the data intact.
  final Object? restart;

  /// If noDebug is true the launch request should launch the program without
  /// enabling debugging.
  final bool? noDebug;

  static LaunchRequestArguments fromJson(Map<String, Object?> obj) =>
      LaunchRequestArguments.fromMap(obj);

  LaunchRequestArguments({
    this.restart,
    this.noDebug,
  });

  LaunchRequestArguments.fromMap(Map<String, Object?> obj)
      : restart = obj['__restart'],
        noDebug = obj['noDebug'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['noDebug'] is! bool?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (restart != null) '__restart': restart,
        if (noDebug != null) 'noDebug': noDebug,
      };
}

/// Response to 'launch' request. This is just an acknowledgement, so no body
/// field is required.
class LaunchResponse extends Response {
  static LaunchResponse fromJson(Map<String, Object?> obj) =>
      LaunchResponse.fromMap(obj);

  LaunchResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  LaunchResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'loadedSources' request.
class LoadedSourcesArguments extends RequestArguments {
  static LoadedSourcesArguments fromJson(Map<String, Object?> obj) =>
      LoadedSourcesArguments.fromMap(obj);

  LoadedSourcesArguments();

  LoadedSourcesArguments.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {};
}

/// Response to 'loadedSources' request.
class LoadedSourcesResponse extends Response {
  static LoadedSourcesResponse fromJson(Map<String, Object?> obj) =>
      LoadedSourcesResponse.fromMap(obj);

  LoadedSourcesResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  LoadedSourcesResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A structured message object. Used to return errors from requests.
class Message {
  /// A format string for the message. Embedded variables have the form
  /// '{name}'.
  /// If variable name starts with an underscore character, the variable does
  /// not contain user data (PII) and can be safely used for telemetry purposes.
  final String format;

  /// Unique identifier for the message.
  final int id;

  /// If true send to telemetry.
  final bool? sendTelemetry;

  /// If true show user.
  final bool? showUser;

  /// An optional url where additional information about this message can be
  /// found.
  final String? url;

  /// An optional label that is presented to the user as the UI for opening the
  /// url.
  final String? urlLabel;

  /// An object used as a dictionary for looking up the variables in the format
  /// string.
  final Map<String, Object?>? variables;

  static Message fromJson(Map<String, Object?> obj) => Message.fromMap(obj);

  Message({
    required this.format,
    required this.id,
    this.sendTelemetry,
    this.showUser,
    this.url,
    this.urlLabel,
    this.variables,
  });

  Message.fromMap(Map<String, Object?> obj)
      : format = obj['format'] as String,
        id = obj['id'] as int,
        sendTelemetry = obj['sendTelemetry'] as bool?,
        showUser = obj['showUser'] as bool?,
        url = obj['url'] as String?,
        urlLabel = obj['urlLabel'] as String?,
        variables = obj['variables'] as Map<String, Object?>?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['format'] is! String) {
      return false;
    }
    if (obj['id'] is! int) {
      return false;
    }
    if (obj['sendTelemetry'] is! bool?) {
      return false;
    }
    if (obj['showUser'] is! bool?) {
      return false;
    }
    if (obj['url'] is! String?) {
      return false;
    }
    if (obj['urlLabel'] is! String?) {
      return false;
    }
    if (obj['variables'] is! Map<String, Object?>?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'format': format,
        'id': id,
        if (sendTelemetry != null) 'sendTelemetry': sendTelemetry,
        if (showUser != null) 'showUser': showUser,
        if (url != null) 'url': url,
        if (urlLabel != null) 'urlLabel': urlLabel,
        if (variables != null) 'variables': variables,
      };
}

/// A Module object represents a row in the modules view.
/// Two attributes are mandatory: an id identifies a module in the modules view
/// and is used in a ModuleEvent for identifying a module for adding, updating
/// or deleting.
/// The name is used to minimally render the module in the UI.
///
/// Additional attributes can be added to the module. They will show up in the
/// module View if they have a corresponding ColumnDescriptor.
///
/// To avoid an unnecessary proliferation of additional attributes with similar
/// semantics but different names
/// we recommend to re-use attributes from the 'recommended' list below first,
/// and only introduce new attributes if nothing appropriate could be found.
class Module {
  /// Address range covered by this module.
  final String? addressRange;

  /// Module created or modified.
  final String? dateTimeStamp;

  /// Unique identifier for the module.
  final Either2<int, String> id;

  /// True if the module is optimized.
  final bool? isOptimized;

  /// True if the module is considered 'user code' by a debugger that supports
  /// 'Just My Code'.
  final bool? isUserCode;

  /// A name of the module.
  final String name;

  /// optional but recommended attributes.
  /// always try to use these first before introducing additional attributes.
  ///
  /// Logical full path to the module. The exact definition is implementation
  /// defined, but usually this would be a full path to the on-disk file for the
  /// module.
  final String? path;

  /// Logical full path to the symbol file. The exact definition is
  /// implementation defined.
  final String? symbolFilePath;

  /// User understandable description of if symbols were found for the module
  /// (ex: 'Symbols Loaded', 'Symbols not found', etc.
  final String? symbolStatus;

  /// Version of Module.
  final String? version;

  static Module fromJson(Map<String, Object?> obj) => Module.fromMap(obj);

  Module({
    this.addressRange,
    this.dateTimeStamp,
    required this.id,
    this.isOptimized,
    this.isUserCode,
    required this.name,
    this.path,
    this.symbolFilePath,
    this.symbolStatus,
    this.version,
  });

  Module.fromMap(Map<String, Object?> obj)
      : addressRange = obj['addressRange'] as String?,
        dateTimeStamp = obj['dateTimeStamp'] as String?,
        id = obj['id'] is int
            ? Either2<int, String>.t1(obj['id'] as int)
            : Either2<int, String>.t2(obj['id'] as String),
        isOptimized = obj['isOptimized'] as bool?,
        isUserCode = obj['isUserCode'] as bool?,
        name = obj['name'] as String,
        path = obj['path'] as String?,
        symbolFilePath = obj['symbolFilePath'] as String?,
        symbolStatus = obj['symbolStatus'] as String?,
        version = obj['version'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['addressRange'] is! String?) {
      return false;
    }
    if (obj['dateTimeStamp'] is! String?) {
      return false;
    }
    if ((obj['id'] is! int && obj['id'] is! String)) {
      return false;
    }
    if (obj['isOptimized'] is! bool?) {
      return false;
    }
    if (obj['isUserCode'] is! bool?) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    if (obj['path'] is! String?) {
      return false;
    }
    if (obj['symbolFilePath'] is! String?) {
      return false;
    }
    if (obj['symbolStatus'] is! String?) {
      return false;
    }
    if (obj['version'] is! String?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (addressRange != null) 'addressRange': addressRange,
        if (dateTimeStamp != null) 'dateTimeStamp': dateTimeStamp,
        'id': id,
        if (isOptimized != null) 'isOptimized': isOptimized,
        if (isUserCode != null) 'isUserCode': isUserCode,
        'name': name,
        if (path != null) 'path': path,
        if (symbolFilePath != null) 'symbolFilePath': symbolFilePath,
        if (symbolStatus != null) 'symbolStatus': symbolStatus,
        if (version != null) 'version': version,
      };
}

/// Arguments for 'modules' request.
class ModulesArguments extends RequestArguments {
  /// The number of modules to return. If moduleCount is not specified or 0, all
  /// modules are returned.
  final int? moduleCount;

  /// The index of the first module to return; if omitted modules start at 0.
  final int? startModule;

  static ModulesArguments fromJson(Map<String, Object?> obj) =>
      ModulesArguments.fromMap(obj);

  ModulesArguments({
    this.moduleCount,
    this.startModule,
  });

  ModulesArguments.fromMap(Map<String, Object?> obj)
      : moduleCount = obj['moduleCount'] as int?,
        startModule = obj['startModule'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['moduleCount'] is! int?) {
      return false;
    }
    if (obj['startModule'] is! int?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (moduleCount != null) 'moduleCount': moduleCount,
        if (startModule != null) 'startModule': startModule,
      };
}

/// Response to 'modules' request.
class ModulesResponse extends Response {
  static ModulesResponse fromJson(Map<String, Object?> obj) =>
      ModulesResponse.fromMap(obj);

  ModulesResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ModulesResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// The ModulesViewDescriptor is the container for all declarative configuration
/// options of a ModuleView.
/// For now it only specifies the columns to be shown in the modules view.
class ModulesViewDescriptor {
  final List<ColumnDescriptor> columns;

  static ModulesViewDescriptor fromJson(Map<String, Object?> obj) =>
      ModulesViewDescriptor.fromMap(obj);

  ModulesViewDescriptor({
    required this.columns,
  });

  ModulesViewDescriptor.fromMap(Map<String, Object?> obj)
      : columns = (obj['columns'] as List)
            .map((item) =>
                ColumnDescriptor.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['columns'] is! List ||
        (obj['columns'].any((item) => !ColumnDescriptor.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'columns': columns,
      };
}

/// Arguments for 'next' request.
class NextArguments extends RequestArguments {
  /// Optional granularity to step. If no granularity is specified, a
  /// granularity of 'statement' is assumed.
  final SteppingGranularity? granularity;

  /// Execute 'next' for this thread.
  final int threadId;

  static NextArguments fromJson(Map<String, Object?> obj) =>
      NextArguments.fromMap(obj);

  NextArguments({
    this.granularity,
    required this.threadId,
  });

  NextArguments.fromMap(Map<String, Object?> obj)
      : granularity = obj['granularity'] == null
            ? null
            : SteppingGranularity.fromJson(
                obj['granularity'] as Map<String, Object?>),
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!SteppingGranularity?.canParse(obj['granularity'])) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (granularity != null) 'granularity': granularity,
        'threadId': threadId,
      };
}

/// Response to 'next' request. This is just an acknowledgement, so no body
/// field is required.
class NextResponse extends Response {
  static NextResponse fromJson(Map<String, Object?> obj) =>
      NextResponse.fromMap(obj);

  NextResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  NextResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'pause' request.
class PauseArguments extends RequestArguments {
  /// Pause execution for this thread.
  final int threadId;

  static PauseArguments fromJson(Map<String, Object?> obj) =>
      PauseArguments.fromMap(obj);

  PauseArguments({
    required this.threadId,
  });

  PauseArguments.fromMap(Map<String, Object?> obj)
      : threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'threadId': threadId,
      };
}

/// Response to 'pause' request. This is just an acknowledgement, so no body
/// field is required.
class PauseResponse extends Response {
  static PauseResponse fromJson(Map<String, Object?> obj) =>
      PauseResponse.fromMap(obj);

  PauseResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  PauseResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Base class of requests, responses, and events.
class ProtocolMessage {
  /// Sequence number (also known as message ID). For protocol messages of type
  /// 'request' this ID can be used to cancel the request.
  final int seq;

  /// Message type.
  final String type;

  static ProtocolMessage fromJson(Map<String, Object?> obj) =>
      ProtocolMessage.fromMap(obj);

  ProtocolMessage({
    required this.seq,
    required this.type,
  });

  ProtocolMessage.fromMap(Map<String, Object?> obj)
      : seq = obj['seq'] as int,
        type = obj['type'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['seq'] is! int) {
      return false;
    }
    if (obj['type'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'seq': seq,
        'type': type,
      };
}

/// Arguments for 'readMemory' request.
class ReadMemoryArguments extends RequestArguments {
  /// Number of bytes to read at the specified location and offset.
  final int count;

  /// Memory reference to the base location from which data should be read.
  final String memoryReference;

  /// Optional offset (in bytes) to be applied to the reference location before
  /// reading data. Can be negative.
  final int? offset;

  static ReadMemoryArguments fromJson(Map<String, Object?> obj) =>
      ReadMemoryArguments.fromMap(obj);

  ReadMemoryArguments({
    required this.count,
    required this.memoryReference,
    this.offset,
  });

  ReadMemoryArguments.fromMap(Map<String, Object?> obj)
      : count = obj['count'] as int,
        memoryReference = obj['memoryReference'] as String,
        offset = obj['offset'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['count'] is! int) {
      return false;
    }
    if (obj['memoryReference'] is! String) {
      return false;
    }
    if (obj['offset'] is! int?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'count': count,
        'memoryReference': memoryReference,
        if (offset != null) 'offset': offset,
      };
}

/// Response to 'readMemory' request.
class ReadMemoryResponse extends Response {
  static ReadMemoryResponse fromJson(Map<String, Object?> obj) =>
      ReadMemoryResponse.fromMap(obj);

  ReadMemoryResponse({
    Map<String, Object?>? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ReadMemoryResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>?) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A client or debug adapter initiated request.
class Request extends ProtocolMessage {
  /// Object containing arguments for the command.
  final Object? arguments;

  /// The command to execute.
  final String command;

  static Request fromJson(Map<String, Object?> obj) => Request.fromMap(obj);

  Request({
    this.arguments,
    required this.command,
    required int seq,
  }) : super(
          seq: seq,
          type: 'request',
        );

  Request.fromMap(Map<String, Object?> obj)
      : arguments = obj['arguments'],
        command = obj['command'] as String,
        super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['command'] is! String) {
      return false;
    }
    if (obj['type'] is! String) {
      return false;
    }
    return ProtocolMessage.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
        if (arguments != null) 'arguments': arguments,
        'command': command,
      };
}

/// Response for a request.
class Response extends ProtocolMessage {
  /// Contains request result if success is true and optional error details if
  /// success is false.
  final Object? body;

  /// The command requested.
  final String command;

  /// Contains the raw error in short form if 'success' is false.
  /// This raw error might be interpreted by the frontend and is not shown in
  /// the UI.
  /// Some predefined values exist.
  final String? message;

  /// Sequence number of the corresponding request.
  final int requestSeq;

  /// Outcome of the request.
  /// If true, the request was successful and the 'body' attribute may contain
  /// the result of the request.
  /// If the value is false, the attribute 'message' contains the error in short
  /// form and the 'body' may contain additional information (see
  /// 'ErrorResponse.body.error').
  final bool success;

  static Response fromJson(Map<String, Object?> obj) => Response.fromMap(obj);

  Response({
    this.body,
    required this.command,
    this.message,
    required this.requestSeq,
    required this.success,
    required int seq,
  }) : super(
          seq: seq,
          type: 'response',
        );

  Response.fromMap(Map<String, Object?> obj)
      : body = obj['body'],
        command = obj['command'] as String,
        message = obj['message'] as String?,
        requestSeq = obj['request_seq'] as int,
        success = obj['success'] as bool,
        super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['command'] is! String) {
      return false;
    }
    if (obj['message'] is! String?) {
      return false;
    }
    if (obj['request_seq'] is! int) {
      return false;
    }
    if (obj['success'] is! bool) {
      return false;
    }
    if (obj['type'] is! String) {
      return false;
    }
    return ProtocolMessage.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
        if (body != null) 'body': body,
        'command': command,
        if (message != null) 'message': message,
        'request_seq': requestSeq,
        'success': success,
      };
}

/// Arguments for 'restart' request.
class RestartArguments extends RequestArguments {
  /// The latest version of the 'launch' or 'attach' configuration.
  final Either2<LaunchRequestArguments, AttachRequestArguments>? arguments;

  static RestartArguments fromJson(Map<String, Object?> obj) =>
      RestartArguments.fromMap(obj);

  RestartArguments({
    this.arguments,
  });

  RestartArguments.fromMap(Map<String, Object?> obj)
      : arguments = LaunchRequestArguments.canParse(obj['arguments'])
            ? Either2<LaunchRequestArguments, AttachRequestArguments>.t1(
                LaunchRequestArguments.fromJson(
                    obj['arguments'] as Map<String, Object?>))
            : AttachRequestArguments.canParse(obj['arguments'])
                ? Either2<LaunchRequestArguments, AttachRequestArguments>.t2(
                    AttachRequestArguments.fromJson(
                        obj['arguments'] as Map<String, Object?>))
                : null;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((!LaunchRequestArguments.canParse(obj['arguments']) &&
        !AttachRequestArguments.canParse(obj['arguments']) &&
        obj['arguments'] != null)) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (arguments != null) 'arguments': arguments,
      };
}

/// Arguments for 'restartFrame' request.
class RestartFrameArguments extends RequestArguments {
  /// Restart this stackframe.
  final int frameId;

  static RestartFrameArguments fromJson(Map<String, Object?> obj) =>
      RestartFrameArguments.fromMap(obj);

  RestartFrameArguments({
    required this.frameId,
  });

  RestartFrameArguments.fromMap(Map<String, Object?> obj)
      : frameId = obj['frameId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['frameId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'frameId': frameId,
      };
}

/// Response to 'restartFrame' request. This is just an acknowledgement, so no
/// body field is required.
class RestartFrameResponse extends Response {
  static RestartFrameResponse fromJson(Map<String, Object?> obj) =>
      RestartFrameResponse.fromMap(obj);

  RestartFrameResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  RestartFrameResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Response to 'restart' request. This is just an acknowledgement, so no body
/// field is required.
class RestartResponse extends Response {
  static RestartResponse fromJson(Map<String, Object?> obj) =>
      RestartResponse.fromMap(obj);

  RestartResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  RestartResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'reverseContinue' request.
class ReverseContinueArguments extends RequestArguments {
  /// Execute 'reverseContinue' for this thread.
  final int threadId;

  static ReverseContinueArguments fromJson(Map<String, Object?> obj) =>
      ReverseContinueArguments.fromMap(obj);

  ReverseContinueArguments({
    required this.threadId,
  });

  ReverseContinueArguments.fromMap(Map<String, Object?> obj)
      : threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'threadId': threadId,
      };
}

/// Response to 'reverseContinue' request. This is just an acknowledgement, so
/// no body field is required.
class ReverseContinueResponse extends Response {
  static ReverseContinueResponse fromJson(Map<String, Object?> obj) =>
      ReverseContinueResponse.fromMap(obj);

  ReverseContinueResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ReverseContinueResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'runInTerminal' request.
class RunInTerminalRequestArguments extends RequestArguments {
  /// List of arguments. The first argument is the command to run.
  final List<String> args;

  /// Working directory for the command. For non-empty, valid paths this
  /// typically results in execution of a change directory command.
  final String cwd;

  /// Environment key-value pairs that are added to or removed from the default
  /// environment.
  final Map<String, Object?>? env;

  /// What kind of terminal to launch.
  final String? kind;

  /// Optional title of the terminal.
  final String? title;

  static RunInTerminalRequestArguments fromJson(Map<String, Object?> obj) =>
      RunInTerminalRequestArguments.fromMap(obj);

  RunInTerminalRequestArguments({
    required this.args,
    required this.cwd,
    this.env,
    this.kind,
    this.title,
  });

  RunInTerminalRequestArguments.fromMap(Map<String, Object?> obj)
      : args = (obj['args'] as List).map((item) => item as String).toList(),
        cwd = obj['cwd'] as String,
        env = obj['env'] as Map<String, Object?>?,
        kind = obj['kind'] as String?,
        title = obj['title'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['args'] is! List ||
        (obj['args'].any((item) => item is! String)))) {
      return false;
    }
    if (obj['cwd'] is! String) {
      return false;
    }
    if (obj['env'] is! Map<String, Object?>?) {
      return false;
    }
    if (obj['kind'] is! String?) {
      return false;
    }
    if (obj['title'] is! String?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'args': args,
        'cwd': cwd,
        if (env != null) 'env': env,
        if (kind != null) 'kind': kind,
        if (title != null) 'title': title,
      };
}

/// Response to 'runInTerminal' request.
class RunInTerminalResponse extends Response {
  static RunInTerminalResponse fromJson(Map<String, Object?> obj) =>
      RunInTerminalResponse.fromMap(obj);

  RunInTerminalResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  RunInTerminalResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A Scope is a named container for variables. Optionally a scope can map to a
/// source or a range within a source.
class Scope {
  /// Optional start column of the range covered by this scope.
  final int? column;

  /// Optional end column of the range covered by this scope.
  final int? endColumn;

  /// Optional end line of the range covered by this scope.
  final int? endLine;

  /// If true, the number of variables in this scope is large or expensive to
  /// retrieve.
  final bool expensive;

  /// The number of indexed variables in this scope.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  final int? indexedVariables;

  /// Optional start line of the range covered by this scope.
  final int? line;

  /// Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This
  /// string is shown in the UI as is and can be translated.
  final String name;

  /// The number of named variables in this scope.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  final int? namedVariables;

  /// An optional hint for how to present this scope in the UI. If this
  /// attribute is missing, the scope is shown with a generic UI.
  final String? presentationHint;

  /// Optional source for this scope.
  final Source? source;

  /// The variables of this scope can be retrieved by passing the value of
  /// variablesReference to the VariablesRequest.
  final int variablesReference;

  static Scope fromJson(Map<String, Object?> obj) => Scope.fromMap(obj);

  Scope({
    this.column,
    this.endColumn,
    this.endLine,
    required this.expensive,
    this.indexedVariables,
    this.line,
    required this.name,
    this.namedVariables,
    this.presentationHint,
    this.source,
    required this.variablesReference,
  });

  Scope.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int?,
        endColumn = obj['endColumn'] as int?,
        endLine = obj['endLine'] as int?,
        expensive = obj['expensive'] as bool,
        indexedVariables = obj['indexedVariables'] as int?,
        line = obj['line'] as int?,
        name = obj['name'] as String,
        namedVariables = obj['namedVariables'] as int?,
        presentationHint = obj['presentationHint'] as String?,
        source = obj['source'] == null
            ? null
            : Source.fromJson(obj['source'] as Map<String, Object?>),
        variablesReference = obj['variablesReference'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['endColumn'] is! int?) {
      return false;
    }
    if (obj['endLine'] is! int?) {
      return false;
    }
    if (obj['expensive'] is! bool) {
      return false;
    }
    if (obj['indexedVariables'] is! int?) {
      return false;
    }
    if (obj['line'] is! int?) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    if (obj['namedVariables'] is! int?) {
      return false;
    }
    if (obj['presentationHint'] is! String?) {
      return false;
    }
    if (!Source?.canParse(obj['source'])) {
      return false;
    }
    if (obj['variablesReference'] is! int) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (column != null) 'column': column,
        if (endColumn != null) 'endColumn': endColumn,
        if (endLine != null) 'endLine': endLine,
        'expensive': expensive,
        if (indexedVariables != null) 'indexedVariables': indexedVariables,
        if (line != null) 'line': line,
        'name': name,
        if (namedVariables != null) 'namedVariables': namedVariables,
        if (presentationHint != null) 'presentationHint': presentationHint,
        if (source != null) 'source': source,
        'variablesReference': variablesReference,
      };
}

/// Arguments for 'scopes' request.
class ScopesArguments extends RequestArguments {
  /// Retrieve the scopes for this stackframe.
  final int frameId;

  static ScopesArguments fromJson(Map<String, Object?> obj) =>
      ScopesArguments.fromMap(obj);

  ScopesArguments({
    required this.frameId,
  });

  ScopesArguments.fromMap(Map<String, Object?> obj)
      : frameId = obj['frameId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['frameId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'frameId': frameId,
      };
}

/// Response to 'scopes' request.
class ScopesResponse extends Response {
  static ScopesResponse fromJson(Map<String, Object?> obj) =>
      ScopesResponse.fromMap(obj);

  ScopesResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ScopesResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'setBreakpoints' request.
class SetBreakpointsArguments extends RequestArguments {
  /// The code locations of the breakpoints.
  final List<SourceBreakpoint>? breakpoints;

  /// Deprecated: The code locations of the breakpoints.
  final List<int>? lines;

  /// The source location of the breakpoints; either 'source.path' or
  /// 'source.reference' must be specified.
  final Source source;

  /// A value of true indicates that the underlying source has been modified
  /// which results in new breakpoint locations.
  final bool? sourceModified;

  static SetBreakpointsArguments fromJson(Map<String, Object?> obj) =>
      SetBreakpointsArguments.fromMap(obj);

  SetBreakpointsArguments({
    this.breakpoints,
    this.lines,
    required this.source,
    this.sourceModified,
  });

  SetBreakpointsArguments.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List?)
            ?.map((item) =>
                SourceBreakpoint.fromJson(item as Map<String, Object?>))
            .toList(),
        lines = (obj['lines'] as List?)?.map((item) => item as int).toList(),
        source = Source.fromJson(obj['source'] as Map<String, Object?>),
        sourceModified = obj['sourceModified'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints'].any((item) => !SourceBreakpoint.canParse(item))))) {
      return false;
    }
    if ((obj['lines'] is! List || (obj['lines'].any((item) => item is! int)))) {
      return false;
    }
    if (!Source.canParse(obj['source'])) {
      return false;
    }
    if (obj['sourceModified'] is! bool?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (breakpoints != null) 'breakpoints': breakpoints,
        if (lines != null) 'lines': lines,
        'source': source,
        if (sourceModified != null) 'sourceModified': sourceModified,
      };
}

/// Response to 'setBreakpoints' request.
/// Returned is information about each breakpoint created by this request.
/// This includes the actual code location and whether the breakpoint could be
/// verified.
/// The breakpoints returned are in the same order as the elements of the
/// 'breakpoints'
/// (or the deprecated 'lines') array in the arguments.
class SetBreakpointsResponse extends Response {
  static SetBreakpointsResponse fromJson(Map<String, Object?> obj) =>
      SetBreakpointsResponse.fromMap(obj);

  SetBreakpointsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SetBreakpointsResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'setDataBreakpoints' request.
class SetDataBreakpointsArguments extends RequestArguments {
  /// The contents of this array replaces all existing data breakpoints. An
  /// empty array clears all data breakpoints.
  final List<DataBreakpoint> breakpoints;

  static SetDataBreakpointsArguments fromJson(Map<String, Object?> obj) =>
      SetDataBreakpointsArguments.fromMap(obj);

  SetDataBreakpointsArguments({
    required this.breakpoints,
  });

  SetDataBreakpointsArguments.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map(
                (item) => DataBreakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints'].any((item) => !DataBreakpoint.canParse(item))))) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

/// Response to 'setDataBreakpoints' request.
/// Returned is information about each breakpoint created by this request.
class SetDataBreakpointsResponse extends Response {
  static SetDataBreakpointsResponse fromJson(Map<String, Object?> obj) =>
      SetDataBreakpointsResponse.fromMap(obj);

  SetDataBreakpointsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SetDataBreakpointsResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'setExceptionBreakpoints' request.
class SetExceptionBreakpointsArguments extends RequestArguments {
  /// Configuration options for selected exceptions.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsExceptionOptions' is true.
  final List<ExceptionOptions>? exceptionOptions;

  /// Set of exception filters and their options. The set of all possible
  /// exception filters is defined by the 'exceptionBreakpointFilters'
  /// capability. This attribute is only honored by a debug adapter if the
  /// capability 'supportsExceptionFilterOptions' is true. The 'filter' and
  /// 'filterOptions' sets are additive.
  final List<ExceptionFilterOptions>? filterOptions;

  /// Set of exception filters specified by their ID. The set of all possible
  /// exception filters is defined by the 'exceptionBreakpointFilters'
  /// capability. The 'filter' and 'filterOptions' sets are additive.
  final List<String> filters;

  static SetExceptionBreakpointsArguments fromJson(Map<String, Object?> obj) =>
      SetExceptionBreakpointsArguments.fromMap(obj);

  SetExceptionBreakpointsArguments({
    this.exceptionOptions,
    this.filterOptions,
    required this.filters,
  });

  SetExceptionBreakpointsArguments.fromMap(Map<String, Object?> obj)
      : exceptionOptions = (obj['exceptionOptions'] as List?)
            ?.map((item) =>
                ExceptionOptions.fromJson(item as Map<String, Object?>))
            .toList(),
        filterOptions = (obj['filterOptions'] as List?)
            ?.map((item) =>
                ExceptionFilterOptions.fromJson(item as Map<String, Object?>))
            .toList(),
        filters =
            (obj['filters'] as List).map((item) => item as String).toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['exceptionOptions'] is! List ||
        (obj['exceptionOptions']
            .any((item) => !ExceptionOptions.canParse(item))))) {
      return false;
    }
    if ((obj['filterOptions'] is! List ||
        (obj['filterOptions']
            .any((item) => !ExceptionFilterOptions.canParse(item))))) {
      return false;
    }
    if ((obj['filters'] is! List ||
        (obj['filters'].any((item) => item is! String)))) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (exceptionOptions != null) 'exceptionOptions': exceptionOptions,
        if (filterOptions != null) 'filterOptions': filterOptions,
        'filters': filters,
      };
}

/// Response to 'setExceptionBreakpoints' request.
/// The response contains an array of Breakpoint objects with information about
/// each exception breakpoint or filter. The Breakpoint objects are in the same
/// order as the elements of the 'filters', 'filterOptions', 'exceptionOptions'
/// arrays given as arguments. If both 'filters' and 'filterOptions' are given,
/// the returned array must start with 'filters' information first, followed by
/// 'filterOptions' information.
/// The mandatory 'verified' property of a Breakpoint object signals whether the
/// exception breakpoint or filter could be successfully created and whether the
/// optional condition or hit count expressions are valid. In case of an error
/// the 'message' property explains the problem. An optional 'id' property can
/// be used to introduce a unique ID for the exception breakpoint or filter so
/// that it can be updated subsequently by sending breakpoint events.
/// For backward compatibility both the 'breakpoints' array and the enclosing
/// 'body' are optional. If these elements are missing a client will not be able
/// to show problems for individual exception breakpoints or filters.
class SetExceptionBreakpointsResponse extends Response {
  static SetExceptionBreakpointsResponse fromJson(Map<String, Object?> obj) =>
      SetExceptionBreakpointsResponse.fromMap(obj);

  SetExceptionBreakpointsResponse({
    Map<String, Object?>? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SetExceptionBreakpointsResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>?) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'setExpression' request.
class SetExpressionArguments extends RequestArguments {
  /// The l-value expression to assign to.
  final String expression;

  /// Specifies how the resulting value should be formatted.
  final ValueFormat? format;

  /// Evaluate the expressions in the scope of this stack frame. If not
  /// specified, the expressions are evaluated in the global scope.
  final int? frameId;

  /// The value expression to assign to the l-value expression.
  final String value;

  static SetExpressionArguments fromJson(Map<String, Object?> obj) =>
      SetExpressionArguments.fromMap(obj);

  SetExpressionArguments({
    required this.expression,
    this.format,
    this.frameId,
    required this.value,
  });

  SetExpressionArguments.fromMap(Map<String, Object?> obj)
      : expression = obj['expression'] as String,
        format = obj['format'] == null
            ? null
            : ValueFormat.fromJson(obj['format'] as Map<String, Object?>),
        frameId = obj['frameId'] as int?,
        value = obj['value'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['expression'] is! String) {
      return false;
    }
    if (!ValueFormat?.canParse(obj['format'])) {
      return false;
    }
    if (obj['frameId'] is! int?) {
      return false;
    }
    if (obj['value'] is! String) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'expression': expression,
        if (format != null) 'format': format,
        if (frameId != null) 'frameId': frameId,
        'value': value,
      };
}

/// Response to 'setExpression' request.
class SetExpressionResponse extends Response {
  static SetExpressionResponse fromJson(Map<String, Object?> obj) =>
      SetExpressionResponse.fromMap(obj);

  SetExpressionResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SetExpressionResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'setFunctionBreakpoints' request.
class SetFunctionBreakpointsArguments extends RequestArguments {
  /// The function names of the breakpoints.
  final List<FunctionBreakpoint> breakpoints;

  static SetFunctionBreakpointsArguments fromJson(Map<String, Object?> obj) =>
      SetFunctionBreakpointsArguments.fromMap(obj);

  SetFunctionBreakpointsArguments({
    required this.breakpoints,
  });

  SetFunctionBreakpointsArguments.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map((item) =>
                FunctionBreakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints']
            .any((item) => !FunctionBreakpoint.canParse(item))))) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

/// Response to 'setFunctionBreakpoints' request.
/// Returned is information about each breakpoint created by this request.
class SetFunctionBreakpointsResponse extends Response {
  static SetFunctionBreakpointsResponse fromJson(Map<String, Object?> obj) =>
      SetFunctionBreakpointsResponse.fromMap(obj);

  SetFunctionBreakpointsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SetFunctionBreakpointsResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'setInstructionBreakpoints' request
class SetInstructionBreakpointsArguments extends RequestArguments {
  /// The instruction references of the breakpoints
  final List<InstructionBreakpoint> breakpoints;

  static SetInstructionBreakpointsArguments fromJson(
          Map<String, Object?> obj) =>
      SetInstructionBreakpointsArguments.fromMap(obj);

  SetInstructionBreakpointsArguments({
    required this.breakpoints,
  });

  SetInstructionBreakpointsArguments.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map((item) =>
                InstructionBreakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints']
            .any((item) => !InstructionBreakpoint.canParse(item))))) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

/// Response to 'setInstructionBreakpoints' request
class SetInstructionBreakpointsResponse extends Response {
  static SetInstructionBreakpointsResponse fromJson(Map<String, Object?> obj) =>
      SetInstructionBreakpointsResponse.fromMap(obj);

  SetInstructionBreakpointsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SetInstructionBreakpointsResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'setVariable' request.
class SetVariableArguments extends RequestArguments {
  /// Specifies details on how to format the response value.
  final ValueFormat? format;

  /// The name of the variable in the container.
  final String name;

  /// The value of the variable.
  final String value;

  /// The reference of the variable container.
  final int variablesReference;

  static SetVariableArguments fromJson(Map<String, Object?> obj) =>
      SetVariableArguments.fromMap(obj);

  SetVariableArguments({
    this.format,
    required this.name,
    required this.value,
    required this.variablesReference,
  });

  SetVariableArguments.fromMap(Map<String, Object?> obj)
      : format = obj['format'] == null
            ? null
            : ValueFormat.fromJson(obj['format'] as Map<String, Object?>),
        name = obj['name'] as String,
        value = obj['value'] as String,
        variablesReference = obj['variablesReference'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!ValueFormat?.canParse(obj['format'])) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    if (obj['value'] is! String) {
      return false;
    }
    if (obj['variablesReference'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (format != null) 'format': format,
        'name': name,
        'value': value,
        'variablesReference': variablesReference,
      };
}

/// Response to 'setVariable' request.
class SetVariableResponse extends Response {
  static SetVariableResponse fromJson(Map<String, Object?> obj) =>
      SetVariableResponse.fromMap(obj);

  SetVariableResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SetVariableResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A Source is a descriptor for source code.
/// It is returned from the debug adapter as part of a StackFrame and it is used
/// by clients when specifying breakpoints.
class Source {
  /// Optional data that a debug adapter might want to loop through the client.
  /// The client should leave the data intact and persist it across sessions.
  /// The client should not interpret the data.
  final Object? adapterData;

  /// The checksums associated with this file.
  final List<Checksum>? checksums;

  /// The short name of the source. Every source returned from the debug adapter
  /// has a name.
  /// When sending a source to the debug adapter this name is optional.
  final String? name;

  /// The (optional) origin of this source: possible values 'internal module',
  /// 'inlined content from source map', etc.
  final String? origin;

  /// The path of the source to be shown in the UI.
  /// It is only used to locate and load the content of the source if no
  /// sourceReference is specified (or its value is 0).
  final String? path;

  /// An optional hint for how to present the source in the UI.
  /// A value of 'deemphasize' can be used to indicate that the source is not
  /// available or that it is skipped on stepping.
  final String? presentationHint;

  /// If sourceReference > 0 the contents of the source must be retrieved
  /// through the SourceRequest (even if a path is specified).
  /// A sourceReference is only valid for a session, so it must not be used to
  /// persist a source.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? sourceReference;

  /// An optional list of sources that are related to this source. These may be
  /// the source that generated this source.
  final List<Source>? sources;

  static Source fromJson(Map<String, Object?> obj) => Source.fromMap(obj);

  Source({
    this.adapterData,
    this.checksums,
    this.name,
    this.origin,
    this.path,
    this.presentationHint,
    this.sourceReference,
    this.sources,
  });

  Source.fromMap(Map<String, Object?> obj)
      : adapterData = obj['adapterData'],
        checksums = (obj['checksums'] as List?)
            ?.map((item) => Checksum.fromJson(item as Map<String, Object?>))
            .toList(),
        name = obj['name'] as String?,
        origin = obj['origin'] as String?,
        path = obj['path'] as String?,
        presentationHint = obj['presentationHint'] as String?,
        sourceReference = obj['sourceReference'] as int?,
        sources = (obj['sources'] as List?)
            ?.map((item) => Source.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['checksums'] is! List ||
        (obj['checksums'].any((item) => !Checksum.canParse(item))))) {
      return false;
    }
    if (obj['name'] is! String?) {
      return false;
    }
    if (obj['origin'] is! String?) {
      return false;
    }
    if (obj['path'] is! String?) {
      return false;
    }
    if (obj['presentationHint'] is! String?) {
      return false;
    }
    if (obj['sourceReference'] is! int?) {
      return false;
    }
    if ((obj['sources'] is! List ||
        (obj['sources'].any((item) => !Source.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (adapterData != null) 'adapterData': adapterData,
        if (checksums != null) 'checksums': checksums,
        if (name != null) 'name': name,
        if (origin != null) 'origin': origin,
        if (path != null) 'path': path,
        if (presentationHint != null) 'presentationHint': presentationHint,
        if (sourceReference != null) 'sourceReference': sourceReference,
        if (sources != null) 'sources': sources,
      };
}

/// Arguments for 'source' request.
class SourceArguments extends RequestArguments {
  /// Specifies the source content to load. Either source.path or
  /// source.sourceReference must be specified.
  final Source? source;

  /// The reference to the source. This is the same as source.sourceReference.
  /// This is provided for backward compatibility since old backends do not
  /// understand the 'source' attribute.
  final int sourceReference;

  static SourceArguments fromJson(Map<String, Object?> obj) =>
      SourceArguments.fromMap(obj);

  SourceArguments({
    this.source,
    required this.sourceReference,
  });

  SourceArguments.fromMap(Map<String, Object?> obj)
      : source = obj['source'] == null
            ? null
            : Source.fromJson(obj['source'] as Map<String, Object?>),
        sourceReference = obj['sourceReference'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!Source?.canParse(obj['source'])) {
      return false;
    }
    if (obj['sourceReference'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (source != null) 'source': source,
        'sourceReference': sourceReference,
      };
}

/// Properties of a breakpoint or logpoint passed to the setBreakpoints request.
class SourceBreakpoint {
  /// An optional source column of the breakpoint.
  final int? column;

  /// An optional expression for conditional breakpoints.
  /// It is only honored by a debug adapter if the capability
  /// 'supportsConditionalBreakpoints' is true.
  final String? condition;

  /// An optional expression that controls how many hits of the breakpoint are
  /// ignored.
  /// The backend is expected to interpret the expression as needed.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsHitConditionalBreakpoints' is true.
  final String? hitCondition;

  /// The source line of the breakpoint or logpoint.
  final int line;

  /// If this attribute exists and is non-empty, the backend must not 'break'
  /// (stop)
  /// but log the message instead. Expressions within {} are interpolated.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsLogPoints' is true.
  final String? logMessage;

  static SourceBreakpoint fromJson(Map<String, Object?> obj) =>
      SourceBreakpoint.fromMap(obj);

  SourceBreakpoint({
    this.column,
    this.condition,
    this.hitCondition,
    required this.line,
    this.logMessage,
  });

  SourceBreakpoint.fromMap(Map<String, Object?> obj)
      : column = obj['column'] as int?,
        condition = obj['condition'] as String?,
        hitCondition = obj['hitCondition'] as String?,
        line = obj['line'] as int,
        logMessage = obj['logMessage'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['condition'] is! String?) {
      return false;
    }
    if (obj['hitCondition'] is! String?) {
      return false;
    }
    if (obj['line'] is! int) {
      return false;
    }
    if (obj['logMessage'] is! String?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (column != null) 'column': column,
        if (condition != null) 'condition': condition,
        if (hitCondition != null) 'hitCondition': hitCondition,
        'line': line,
        if (logMessage != null) 'logMessage': logMessage,
      };
}

/// Response to 'source' request.
class SourceResponse extends Response {
  static SourceResponse fromJson(Map<String, Object?> obj) =>
      SourceResponse.fromMap(obj);

  SourceResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  SourceResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A Stackframe contains the source location.
class StackFrame {
  /// Indicates whether this frame can be restarted with the 'restart' request.
  /// Clients should only use this if the debug adapter supports the 'restart'
  /// request (capability 'supportsRestartRequest' is true).
  final bool? canRestart;

  /// The column within the line. If source is null or doesn't exist, column is
  /// 0 and must be ignored.
  final int column;

  /// An optional end column of the range covered by the stack frame.
  final int? endColumn;

  /// An optional end line of the range covered by the stack frame.
  final int? endLine;

  /// An identifier for the stack frame. It must be unique across all threads.
  /// This id can be used to retrieve the scopes of the frame with the
  /// 'scopesRequest' or to restart the execution of a stackframe.
  final int id;

  /// Optional memory reference for the current instruction pointer in this
  /// frame.
  final String? instructionPointerReference;

  /// The line within the file of the frame. If source is null or doesn't exist,
  /// line is 0 and must be ignored.
  final int line;

  /// The module associated with this frame, if any.
  final Either2<int, String>? moduleId;

  /// The name of the stack frame, typically a method name.
  final String name;

  /// An optional hint for how to present this frame in the UI.
  /// A value of 'label' can be used to indicate that the frame is an artificial
  /// frame that is used as a visual label or separator. A value of 'subtle' can
  /// be used to change the appearance of a frame in a 'subtle' way.
  final String? presentationHint;

  /// The optional source of the frame.
  final Source? source;

  static StackFrame fromJson(Map<String, Object?> obj) =>
      StackFrame.fromMap(obj);

  StackFrame({
    this.canRestart,
    required this.column,
    this.endColumn,
    this.endLine,
    required this.id,
    this.instructionPointerReference,
    required this.line,
    this.moduleId,
    required this.name,
    this.presentationHint,
    this.source,
  });

  StackFrame.fromMap(Map<String, Object?> obj)
      : canRestart = obj['canRestart'] as bool?,
        column = obj['column'] as int,
        endColumn = obj['endColumn'] as int?,
        endLine = obj['endLine'] as int?,
        id = obj['id'] as int,
        instructionPointerReference =
            obj['instructionPointerReference'] as String?,
        line = obj['line'] as int,
        moduleId = obj['moduleId'] is int
            ? Either2<int, String>.t1(obj['moduleId'] as int)
            : obj['moduleId'] is String
                ? Either2<int, String>.t2(obj['moduleId'] as String)
                : null,
        name = obj['name'] as String,
        presentationHint = obj['presentationHint'] as String?,
        source = obj['source'] == null
            ? null
            : Source.fromJson(obj['source'] as Map<String, Object?>);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['canRestart'] is! bool?) {
      return false;
    }
    if (obj['column'] is! int) {
      return false;
    }
    if (obj['endColumn'] is! int?) {
      return false;
    }
    if (obj['endLine'] is! int?) {
      return false;
    }
    if (obj['id'] is! int) {
      return false;
    }
    if (obj['instructionPointerReference'] is! String?) {
      return false;
    }
    if (obj['line'] is! int) {
      return false;
    }
    if ((obj['moduleId'] is! int &&
        obj['moduleId'] is! String &&
        obj['moduleId'] != null)) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    if (obj['presentationHint'] is! String?) {
      return false;
    }
    if (!Source?.canParse(obj['source'])) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (canRestart != null) 'canRestart': canRestart,
        'column': column,
        if (endColumn != null) 'endColumn': endColumn,
        if (endLine != null) 'endLine': endLine,
        'id': id,
        if (instructionPointerReference != null)
          'instructionPointerReference': instructionPointerReference,
        'line': line,
        if (moduleId != null) 'moduleId': moduleId,
        'name': name,
        if (presentationHint != null) 'presentationHint': presentationHint,
        if (source != null) 'source': source,
      };
}

/// Provides formatting information for a stack frame.
class StackFrameFormat extends ValueFormat {
  /// Includes all stack frames, including those the debug adapter might
  /// otherwise hide.
  final bool? includeAll;

  /// Displays the line number of the stack frame.
  final bool? line;

  /// Displays the module of the stack frame.
  final bool? module;

  /// Displays the names of parameters for the stack frame.
  final bool? parameterNames;

  /// Displays the types of parameters for the stack frame.
  final bool? parameterTypes;

  /// Displays the values of parameters for the stack frame.
  final bool? parameterValues;

  /// Displays parameters for the stack frame.
  final bool? parameters;

  static StackFrameFormat fromJson(Map<String, Object?> obj) =>
      StackFrameFormat.fromMap(obj);

  StackFrameFormat({
    this.includeAll,
    this.line,
    this.module,
    this.parameterNames,
    this.parameterTypes,
    this.parameterValues,
    this.parameters,
    bool? hex,
  }) : super(
          hex: hex,
        );

  StackFrameFormat.fromMap(Map<String, Object?> obj)
      : includeAll = obj['includeAll'] as bool?,
        line = obj['line'] as bool?,
        module = obj['module'] as bool?,
        parameterNames = obj['parameterNames'] as bool?,
        parameterTypes = obj['parameterTypes'] as bool?,
        parameterValues = obj['parameterValues'] as bool?,
        parameters = obj['parameters'] as bool?,
        super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['includeAll'] is! bool?) {
      return false;
    }
    if (obj['line'] is! bool?) {
      return false;
    }
    if (obj['module'] is! bool?) {
      return false;
    }
    if (obj['parameterNames'] is! bool?) {
      return false;
    }
    if (obj['parameterTypes'] is! bool?) {
      return false;
    }
    if (obj['parameterValues'] is! bool?) {
      return false;
    }
    if (obj['parameters'] is! bool?) {
      return false;
    }
    return ValueFormat.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
        if (includeAll != null) 'includeAll': includeAll,
        if (line != null) 'line': line,
        if (module != null) 'module': module,
        if (parameterNames != null) 'parameterNames': parameterNames,
        if (parameterTypes != null) 'parameterTypes': parameterTypes,
        if (parameterValues != null) 'parameterValues': parameterValues,
        if (parameters != null) 'parameters': parameters,
      };
}

/// Arguments for 'stackTrace' request.
class StackTraceArguments extends RequestArguments {
  /// Specifies details on how to format the stack frames.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsValueFormattingOptions' is true.
  final StackFrameFormat? format;

  /// The maximum number of frames to return. If levels is not specified or 0,
  /// all frames are returned.
  final int? levels;

  /// The index of the first frame to return; if omitted frames start at 0.
  final int? startFrame;

  /// Retrieve the stacktrace for this thread.
  final int threadId;

  static StackTraceArguments fromJson(Map<String, Object?> obj) =>
      StackTraceArguments.fromMap(obj);

  StackTraceArguments({
    this.format,
    this.levels,
    this.startFrame,
    required this.threadId,
  });

  StackTraceArguments.fromMap(Map<String, Object?> obj)
      : format = obj['format'] == null
            ? null
            : StackFrameFormat.fromJson(obj['format'] as Map<String, Object?>),
        levels = obj['levels'] as int?,
        startFrame = obj['startFrame'] as int?,
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!StackFrameFormat?.canParse(obj['format'])) {
      return false;
    }
    if (obj['levels'] is! int?) {
      return false;
    }
    if (obj['startFrame'] is! int?) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (format != null) 'format': format,
        if (levels != null) 'levels': levels,
        if (startFrame != null) 'startFrame': startFrame,
        'threadId': threadId,
      };
}

/// Response to 'stackTrace' request.
class StackTraceResponse extends Response {
  static StackTraceResponse fromJson(Map<String, Object?> obj) =>
      StackTraceResponse.fromMap(obj);

  StackTraceResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  StackTraceResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'stepBack' request.
class StepBackArguments extends RequestArguments {
  /// Optional granularity to step. If no granularity is specified, a
  /// granularity of 'statement' is assumed.
  final SteppingGranularity? granularity;

  /// Execute 'stepBack' for this thread.
  final int threadId;

  static StepBackArguments fromJson(Map<String, Object?> obj) =>
      StepBackArguments.fromMap(obj);

  StepBackArguments({
    this.granularity,
    required this.threadId,
  });

  StepBackArguments.fromMap(Map<String, Object?> obj)
      : granularity = obj['granularity'] == null
            ? null
            : SteppingGranularity.fromJson(
                obj['granularity'] as Map<String, Object?>),
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!SteppingGranularity?.canParse(obj['granularity'])) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (granularity != null) 'granularity': granularity,
        'threadId': threadId,
      };
}

/// Response to 'stepBack' request. This is just an acknowledgement, so no body
/// field is required.
class StepBackResponse extends Response {
  static StepBackResponse fromJson(Map<String, Object?> obj) =>
      StepBackResponse.fromMap(obj);

  StepBackResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  StepBackResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'stepIn' request.
class StepInArguments extends RequestArguments {
  /// Optional granularity to step. If no granularity is specified, a
  /// granularity of 'statement' is assumed.
  final SteppingGranularity? granularity;

  /// Optional id of the target to step into.
  final int? targetId;

  /// Execute 'stepIn' for this thread.
  final int threadId;

  static StepInArguments fromJson(Map<String, Object?> obj) =>
      StepInArguments.fromMap(obj);

  StepInArguments({
    this.granularity,
    this.targetId,
    required this.threadId,
  });

  StepInArguments.fromMap(Map<String, Object?> obj)
      : granularity = obj['granularity'] == null
            ? null
            : SteppingGranularity.fromJson(
                obj['granularity'] as Map<String, Object?>),
        targetId = obj['targetId'] as int?,
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!SteppingGranularity?.canParse(obj['granularity'])) {
      return false;
    }
    if (obj['targetId'] is! int?) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (granularity != null) 'granularity': granularity,
        if (targetId != null) 'targetId': targetId,
        'threadId': threadId,
      };
}

/// Response to 'stepIn' request. This is just an acknowledgement, so no body
/// field is required.
class StepInResponse extends Response {
  static StepInResponse fromJson(Map<String, Object?> obj) =>
      StepInResponse.fromMap(obj);

  StepInResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  StepInResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A StepInTarget can be used in the 'stepIn' request and determines into which
/// single target the stepIn request should step.
class StepInTarget {
  /// Unique identifier for a stepIn target.
  final int id;

  /// The name of the stepIn target (shown in the UI).
  final String label;

  static StepInTarget fromJson(Map<String, Object?> obj) =>
      StepInTarget.fromMap(obj);

  StepInTarget({
    required this.id,
    required this.label,
  });

  StepInTarget.fromMap(Map<String, Object?> obj)
      : id = obj['id'] as int,
        label = obj['label'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['id'] is! int) {
      return false;
    }
    if (obj['label'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'id': id,
        'label': label,
      };
}

/// Arguments for 'stepInTargets' request.
class StepInTargetsArguments extends RequestArguments {
  /// The stack frame for which to retrieve the possible stepIn targets.
  final int frameId;

  static StepInTargetsArguments fromJson(Map<String, Object?> obj) =>
      StepInTargetsArguments.fromMap(obj);

  StepInTargetsArguments({
    required this.frameId,
  });

  StepInTargetsArguments.fromMap(Map<String, Object?> obj)
      : frameId = obj['frameId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['frameId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'frameId': frameId,
      };
}

/// Response to 'stepInTargets' request.
class StepInTargetsResponse extends Response {
  static StepInTargetsResponse fromJson(Map<String, Object?> obj) =>
      StepInTargetsResponse.fromMap(obj);

  StepInTargetsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  StepInTargetsResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'stepOut' request.
class StepOutArguments extends RequestArguments {
  /// Optional granularity to step. If no granularity is specified, a
  /// granularity of 'statement' is assumed.
  final SteppingGranularity? granularity;

  /// Execute 'stepOut' for this thread.
  final int threadId;

  static StepOutArguments fromJson(Map<String, Object?> obj) =>
      StepOutArguments.fromMap(obj);

  StepOutArguments({
    this.granularity,
    required this.threadId,
  });

  StepOutArguments.fromMap(Map<String, Object?> obj)
      : granularity = obj['granularity'] == null
            ? null
            : SteppingGranularity.fromJson(
                obj['granularity'] as Map<String, Object?>),
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!SteppingGranularity?.canParse(obj['granularity'])) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (granularity != null) 'granularity': granularity,
        'threadId': threadId,
      };
}

/// Response to 'stepOut' request. This is just an acknowledgement, so no body
/// field is required.
class StepOutResponse extends Response {
  static StepOutResponse fromJson(Map<String, Object?> obj) =>
      StepOutResponse.fromMap(obj);

  StepOutResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  StepOutResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// The granularity of one 'step' in the stepping requests 'next', 'stepIn',
/// 'stepOut', and 'stepBack'.
class SteppingGranularity {
  static SteppingGranularity fromJson(Map<String, Object?> obj) =>
      SteppingGranularity.fromMap(obj);

  SteppingGranularity();

  SteppingGranularity.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Arguments for 'terminate' request.
class TerminateArguments extends RequestArguments {
  /// A value of true indicates that this 'terminate' request is part of a
  /// restart sequence.
  final bool? restart;

  static TerminateArguments fromJson(Map<String, Object?> obj) =>
      TerminateArguments.fromMap(obj);

  TerminateArguments({
    this.restart,
  });

  TerminateArguments.fromMap(Map<String, Object?> obj)
      : restart = obj['restart'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['restart'] is! bool?) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (restart != null) 'restart': restart,
      };
}

/// Response to 'terminate' request. This is just an acknowledgement, so no body
/// field is required.
class TerminateResponse extends Response {
  static TerminateResponse fromJson(Map<String, Object?> obj) =>
      TerminateResponse.fromMap(obj);

  TerminateResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  TerminateResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Arguments for 'terminateThreads' request.
class TerminateThreadsArguments extends RequestArguments {
  /// Ids of threads to be terminated.
  final List<int>? threadIds;

  static TerminateThreadsArguments fromJson(Map<String, Object?> obj) =>
      TerminateThreadsArguments.fromMap(obj);

  TerminateThreadsArguments({
    this.threadIds,
  });

  TerminateThreadsArguments.fromMap(Map<String, Object?> obj)
      : threadIds =
            (obj['threadIds'] as List?)?.map((item) => item as int).toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['threadIds'] is! List ||
        (obj['threadIds'].any((item) => item is! int)))) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (threadIds != null) 'threadIds': threadIds,
      };
}

/// Response to 'terminateThreads' request. This is just an acknowledgement, so
/// no body field is required.
class TerminateThreadsResponse extends Response {
  static TerminateThreadsResponse fromJson(Map<String, Object?> obj) =>
      TerminateThreadsResponse.fromMap(obj);

  TerminateThreadsResponse({
    Object? body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  TerminateThreadsResponse.fromMap(Map<String, Object?> obj)
      : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// A Thread
class Thread {
  /// Unique identifier for the thread.
  final int id;

  /// A name of the thread.
  final String name;

  static Thread fromJson(Map<String, Object?> obj) => Thread.fromMap(obj);

  Thread({
    required this.id,
    required this.name,
  });

  Thread.fromMap(Map<String, Object?> obj)
      : id = obj['id'] as int,
        name = obj['name'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['id'] is! int) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'id': id,
        'name': name,
      };
}

/// Response to 'threads' request.
class ThreadsResponse extends Response {
  static ThreadsResponse fromJson(Map<String, Object?> obj) =>
      ThreadsResponse.fromMap(obj);

  ThreadsResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  ThreadsResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Provides formatting information for a value.
class ValueFormat {
  /// Display the value in hex.
  final bool? hex;

  static ValueFormat fromJson(Map<String, Object?> obj) =>
      ValueFormat.fromMap(obj);

  ValueFormat({
    this.hex,
  });

  ValueFormat.fromMap(Map<String, Object?> obj) : hex = obj['hex'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['hex'] is! bool?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (hex != null) 'hex': hex,
      };
}

/// A Variable is a name/value pair.
/// Optionally a variable can have a 'type' that is shown if space permits or
/// when hovering over the variable's name.
/// An optional 'kind' is used to render additional properties of the variable,
/// e.g. different icons can be used to indicate that a variable is public or
/// private.
/// If the value is structured (has children), a handle is provided to retrieve
/// the children with the VariablesRequest.
/// If the number of named or indexed children is large, the numbers should be
/// returned via the optional 'namedVariables' and 'indexedVariables'
/// attributes.
/// The client can use this optional information to present the children in a
/// paged UI and fetch them in chunks.
class Variable {
  /// Optional evaluatable name of this variable which can be passed to the
  /// 'EvaluateRequest' to fetch the variable's value.
  final String? evaluateName;

  /// The number of indexed child variables.
  /// The client can use this optional information to present the children in a
  /// paged UI and fetch them in chunks.
  final int? indexedVariables;

  /// Optional memory reference for the variable if the variable represents
  /// executable code, such as a function pointer.
  /// This attribute is only required if the client has passed the value true
  /// for the 'supportsMemoryReferences' capability of the 'initialize' request.
  final String? memoryReference;

  /// The variable's name.
  final String name;

  /// The number of named child variables.
  /// The client can use this optional information to present the children in a
  /// paged UI and fetch them in chunks.
  final int? namedVariables;

  /// Properties of a variable that can be used to determine how to render the
  /// variable in the UI.
  final VariablePresentationHint? presentationHint;

  /// The type of the variable's value. Typically shown in the UI when hovering
  /// over the value.
  /// This attribute should only be returned by a debug adapter if the client
  /// has passed the value true for the 'supportsVariableType' capability of the
  /// 'initialize' request.
  final String? type;

  /// The variable's value. This can be a multi-line text, e.g. for a function
  /// the body of a function.
  final String value;

  /// If variablesReference is > 0, the variable is structured and its children
  /// can be retrieved by passing variablesReference to the VariablesRequest.
  final int variablesReference;

  static Variable fromJson(Map<String, Object?> obj) => Variable.fromMap(obj);

  Variable({
    this.evaluateName,
    this.indexedVariables,
    this.memoryReference,
    required this.name,
    this.namedVariables,
    this.presentationHint,
    this.type,
    required this.value,
    required this.variablesReference,
  });

  Variable.fromMap(Map<String, Object?> obj)
      : evaluateName = obj['evaluateName'] as String?,
        indexedVariables = obj['indexedVariables'] as int?,
        memoryReference = obj['memoryReference'] as String?,
        name = obj['name'] as String,
        namedVariables = obj['namedVariables'] as int?,
        presentationHint = obj['presentationHint'] == null
            ? null
            : VariablePresentationHint.fromJson(
                obj['presentationHint'] as Map<String, Object?>),
        type = obj['type'] as String?,
        value = obj['value'] as String,
        variablesReference = obj['variablesReference'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['evaluateName'] is! String?) {
      return false;
    }
    if (obj['indexedVariables'] is! int?) {
      return false;
    }
    if (obj['memoryReference'] is! String?) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    if (obj['namedVariables'] is! int?) {
      return false;
    }
    if (!VariablePresentationHint?.canParse(obj['presentationHint'])) {
      return false;
    }
    if (obj['type'] is! String?) {
      return false;
    }
    if (obj['value'] is! String) {
      return false;
    }
    if (obj['variablesReference'] is! int) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (evaluateName != null) 'evaluateName': evaluateName,
        if (indexedVariables != null) 'indexedVariables': indexedVariables,
        if (memoryReference != null) 'memoryReference': memoryReference,
        'name': name,
        if (namedVariables != null) 'namedVariables': namedVariables,
        if (presentationHint != null) 'presentationHint': presentationHint,
        if (type != null) 'type': type,
        'value': value,
        'variablesReference': variablesReference,
      };
}

/// Optional properties of a variable that can be used to determine how to
/// render the variable in the UI.
class VariablePresentationHint {
  /// Set of attributes represented as an array of strings. Before introducing
  /// additional values, try to use the listed values.
  final List<String>? attributes;

  /// The kind of variable. Before introducing additional values, try to use the
  /// listed values.
  final String? kind;

  /// Visibility of variable. Before introducing additional values, try to use
  /// the listed values.
  final String? visibility;

  static VariablePresentationHint fromJson(Map<String, Object?> obj) =>
      VariablePresentationHint.fromMap(obj);

  VariablePresentationHint({
    this.attributes,
    this.kind,
    this.visibility,
  });

  VariablePresentationHint.fromMap(Map<String, Object?> obj)
      : attributes = (obj['attributes'] as List?)
            ?.map((item) => item as String)
            .toList(),
        kind = obj['kind'] as String?,
        visibility = obj['visibility'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['attributes'] is! List ||
        (obj['attributes'].any((item) => item is! String)))) {
      return false;
    }
    if (obj['kind'] is! String?) {
      return false;
    }
    if (obj['visibility'] is! String?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (attributes != null) 'attributes': attributes,
        if (kind != null) 'kind': kind,
        if (visibility != null) 'visibility': visibility,
      };
}

/// Arguments for 'variables' request.
class VariablesArguments extends RequestArguments {
  /// The number of variables to return. If count is missing or 0, all variables
  /// are returned.
  final int? count;

  /// Optional filter to limit the child variables to either named or indexed.
  /// If omitted, both types are fetched.
  final String? filter;

  /// Specifies details on how to format the Variable values.
  /// The attribute is only honored by a debug adapter if the capability
  /// 'supportsValueFormattingOptions' is true.
  final ValueFormat? format;

  /// The index of the first variable to return; if omitted children start at 0.
  final int? start;

  /// The Variable reference.
  final int variablesReference;

  static VariablesArguments fromJson(Map<String, Object?> obj) =>
      VariablesArguments.fromMap(obj);

  VariablesArguments({
    this.count,
    this.filter,
    this.format,
    this.start,
    required this.variablesReference,
  });

  VariablesArguments.fromMap(Map<String, Object?> obj)
      : count = obj['count'] as int?,
        filter = obj['filter'] as String?,
        format = obj['format'] == null
            ? null
            : ValueFormat.fromJson(obj['format'] as Map<String, Object?>),
        start = obj['start'] as int?,
        variablesReference = obj['variablesReference'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['count'] is! int?) {
      return false;
    }
    if (obj['filter'] is! String?) {
      return false;
    }
    if (!ValueFormat?.canParse(obj['format'])) {
      return false;
    }
    if (obj['start'] is! int?) {
      return false;
    }
    if (obj['variablesReference'] is! int) {
      return false;
    }
    return RequestArguments.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (count != null) 'count': count,
        if (filter != null) 'filter': filter,
        if (format != null) 'format': format,
        if (start != null) 'start': start,
        'variablesReference': variablesReference,
      };
}

/// Response to 'variables' request.
class VariablesResponse extends Response {
  static VariablesResponse fromJson(Map<String, Object?> obj) =>
      VariablesResponse.fromMap(obj);

  VariablesResponse({
    required Map<String, Object?> body,
    required String command,
    String? message,
    required int requestSeq,
    required int seq,
    required bool success,
  }) : super(
          seq: seq,
          requestSeq: requestSeq,
          success: success,
          command: command,
          message: message,
          body: body,
        );

  VariablesResponse.fromMap(Map<String, Object?> obj) : super.fromMap(obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['body'] is! Map<String, Object?>) {
      return false;
    }
    return Response.canParse(obj);
  }

  @override
  Map<String, Object?> toJson() => {
        ...super.toJson(),
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class AttachResponseBody {
  static AttachResponseBody fromJson(Map<String, Object?> obj) =>
      AttachResponseBody.fromMap(obj);

  AttachResponseBody();

  AttachResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class BreakpointEventBody extends EventBody {
  /// The 'id' attribute is used to find the target breakpoint and the other
  /// attributes are used as the new values.
  final Breakpoint breakpoint;

  /// The reason for the event.
  final String reason;

  static BreakpointEventBody fromJson(Map<String, Object?> obj) =>
      BreakpointEventBody.fromMap(obj);

  BreakpointEventBody({
    required this.breakpoint,
    required this.reason,
  });

  BreakpointEventBody.fromMap(Map<String, Object?> obj)
      : breakpoint =
            Breakpoint.fromJson(obj['breakpoint'] as Map<String, Object?>),
        reason = obj['reason'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!Breakpoint.canParse(obj['breakpoint'])) {
      return false;
    }
    if (obj['reason'] is! String) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'breakpoint': breakpoint,
        'reason': reason,
      };
}

class BreakpointLocationsResponseBody {
  /// Sorted set of possible breakpoint locations.
  final List<BreakpointLocation> breakpoints;

  static BreakpointLocationsResponseBody fromJson(Map<String, Object?> obj) =>
      BreakpointLocationsResponseBody.fromMap(obj);

  BreakpointLocationsResponseBody({
    required this.breakpoints,
  });

  BreakpointLocationsResponseBody.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map((item) =>
                BreakpointLocation.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints']
            .any((item) => !BreakpointLocation.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class CancelResponseBody {
  static CancelResponseBody fromJson(Map<String, Object?> obj) =>
      CancelResponseBody.fromMap(obj);

  CancelResponseBody();

  CancelResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class CapabilitiesEventBody extends EventBody {
  /// The set of updated capabilities.
  final Capabilities capabilities;

  static CapabilitiesEventBody fromJson(Map<String, Object?> obj) =>
      CapabilitiesEventBody.fromMap(obj);

  CapabilitiesEventBody({
    required this.capabilities,
  });

  CapabilitiesEventBody.fromMap(Map<String, Object?> obj)
      : capabilities =
            Capabilities.fromJson(obj['capabilities'] as Map<String, Object?>);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!Capabilities.canParse(obj['capabilities'])) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'capabilities': capabilities,
      };
}

class CompletionsResponseBody {
  /// The possible completions for .
  final List<CompletionItem> targets;

  static CompletionsResponseBody fromJson(Map<String, Object?> obj) =>
      CompletionsResponseBody.fromMap(obj);

  CompletionsResponseBody({
    required this.targets,
  });

  CompletionsResponseBody.fromMap(Map<String, Object?> obj)
      : targets = (obj['targets'] as List)
            .map(
                (item) => CompletionItem.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['targets'] is! List ||
        (obj['targets'].any((item) => !CompletionItem.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'targets': targets,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class ConfigurationDoneResponseBody {
  static ConfigurationDoneResponseBody fromJson(Map<String, Object?> obj) =>
      ConfigurationDoneResponseBody.fromMap(obj);

  ConfigurationDoneResponseBody();

  ConfigurationDoneResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class ContinueResponseBody {
  /// If true, the 'continue' request has ignored the specified thread and
  /// continued all threads instead.
  /// If this attribute is missing a value of 'true' is assumed for backward
  /// compatibility.
  final bool? allThreadsContinued;

  static ContinueResponseBody fromJson(Map<String, Object?> obj) =>
      ContinueResponseBody.fromMap(obj);

  ContinueResponseBody({
    this.allThreadsContinued,
  });

  ContinueResponseBody.fromMap(Map<String, Object?> obj)
      : allThreadsContinued = obj['allThreadsContinued'] as bool?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['allThreadsContinued'] is! bool?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (allThreadsContinued != null)
          'allThreadsContinued': allThreadsContinued,
      };
}

class ContinuedEventBody extends EventBody {
  /// If 'allThreadsContinued' is true, a debug adapter can announce that all
  /// threads have continued.
  final bool? allThreadsContinued;

  /// The thread which was continued.
  final int threadId;

  static ContinuedEventBody fromJson(Map<String, Object?> obj) =>
      ContinuedEventBody.fromMap(obj);

  ContinuedEventBody({
    this.allThreadsContinued,
    required this.threadId,
  });

  ContinuedEventBody.fromMap(Map<String, Object?> obj)
      : allThreadsContinued = obj['allThreadsContinued'] as bool?,
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['allThreadsContinued'] is! bool?) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (allThreadsContinued != null)
          'allThreadsContinued': allThreadsContinued,
        'threadId': threadId,
      };
}

class DataBreakpointInfoResponseBody {
  /// Optional attribute listing the available access types for a potential data
  /// breakpoint. A UI frontend could surface this information.
  final List<DataBreakpointAccessType>? accessTypes;

  /// Optional attribute indicating that a potential data breakpoint could be
  /// persisted across sessions.
  final bool? canPersist;

  /// An identifier for the data on which a data breakpoint can be registered
  /// with the setDataBreakpoints request or null if no data breakpoint is
  /// available.
  final Either2<String, Null> dataId;

  /// UI string that describes on what data the breakpoint is set on or why a
  /// data breakpoint is not available.
  final String description;

  static DataBreakpointInfoResponseBody fromJson(Map<String, Object?> obj) =>
      DataBreakpointInfoResponseBody.fromMap(obj);

  DataBreakpointInfoResponseBody({
    this.accessTypes,
    this.canPersist,
    required this.dataId,
    required this.description,
  });

  DataBreakpointInfoResponseBody.fromMap(Map<String, Object?> obj)
      : accessTypes = (obj['accessTypes'] as List?)
            ?.map((item) =>
                DataBreakpointAccessType.fromJson(item as Map<String, Object?>))
            .toList(),
        canPersist = obj['canPersist'] as bool?,
        dataId = obj['dataId'] is String
            ? Either2<String, Null>.t1(obj['dataId'] as String)
            : Either2<String, Null>.t2(obj['dataId'] as Null),
        description = obj['description'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['accessTypes'] is! List ||
        (obj['accessTypes']
            .any((item) => !DataBreakpointAccessType.canParse(item))))) {
      return false;
    }
    if (obj['canPersist'] is! bool?) {
      return false;
    }
    if ((obj['dataId'] is! String && obj['dataId'] != null)) {
      return false;
    }
    if (obj['description'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (accessTypes != null) 'accessTypes': accessTypes,
        if (canPersist != null) 'canPersist': canPersist,
        'dataId': dataId,
        'description': description,
      };
}

class DisassembleResponseBody {
  /// The list of disassembled instructions.
  final List<DisassembledInstruction> instructions;

  static DisassembleResponseBody fromJson(Map<String, Object?> obj) =>
      DisassembleResponseBody.fromMap(obj);

  DisassembleResponseBody({
    required this.instructions,
  });

  DisassembleResponseBody.fromMap(Map<String, Object?> obj)
      : instructions = (obj['instructions'] as List)
            .map((item) =>
                DisassembledInstruction.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['instructions'] is! List ||
        (obj['instructions']
            .any((item) => !DisassembledInstruction.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'instructions': instructions,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class DisconnectResponseBody {
  static DisconnectResponseBody fromJson(Map<String, Object?> obj) =>
      DisconnectResponseBody.fromMap(obj);

  DisconnectResponseBody();

  DisconnectResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class ErrorResponseBody {
  /// An optional, structured error message.
  final Message? error;

  static ErrorResponseBody fromJson(Map<String, Object?> obj) =>
      ErrorResponseBody.fromMap(obj);

  ErrorResponseBody({
    this.error,
  });

  ErrorResponseBody.fromMap(Map<String, Object?> obj)
      : error = obj['error'] == null
            ? null
            : Message.fromJson(obj['error'] as Map<String, Object?>);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!Message?.canParse(obj['error'])) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (error != null) 'error': error,
      };
}

class EvaluateResponseBody {
  /// The number of indexed child variables.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? indexedVariables;

  /// Optional memory reference to a location appropriate for this result.
  /// For pointer type eval results, this is generally a reference to the memory
  /// address contained in the pointer.
  /// This attribute should be returned by a debug adapter if the client has
  /// passed the value true for the 'supportsMemoryReferences' capability of the
  /// 'initialize' request.
  final String? memoryReference;

  /// The number of named child variables.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? namedVariables;

  /// Properties of a evaluate result that can be used to determine how to
  /// render the result in the UI.
  final VariablePresentationHint? presentationHint;

  /// The result of the evaluate request.
  final String result;

  /// The optional type of the evaluate result.
  /// This attribute should only be returned by a debug adapter if the client
  /// has passed the value true for the 'supportsVariableType' capability of the
  /// 'initialize' request.
  final String? type;

  /// If variablesReference is > 0, the evaluate result is structured and its
  /// children can be retrieved by passing variablesReference to the
  /// VariablesRequest.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int variablesReference;

  static EvaluateResponseBody fromJson(Map<String, Object?> obj) =>
      EvaluateResponseBody.fromMap(obj);

  EvaluateResponseBody({
    this.indexedVariables,
    this.memoryReference,
    this.namedVariables,
    this.presentationHint,
    required this.result,
    this.type,
    required this.variablesReference,
  });

  EvaluateResponseBody.fromMap(Map<String, Object?> obj)
      : indexedVariables = obj['indexedVariables'] as int?,
        memoryReference = obj['memoryReference'] as String?,
        namedVariables = obj['namedVariables'] as int?,
        presentationHint = obj['presentationHint'] == null
            ? null
            : VariablePresentationHint.fromJson(
                obj['presentationHint'] as Map<String, Object?>),
        result = obj['result'] as String,
        type = obj['type'] as String?,
        variablesReference = obj['variablesReference'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['indexedVariables'] is! int?) {
      return false;
    }
    if (obj['memoryReference'] is! String?) {
      return false;
    }
    if (obj['namedVariables'] is! int?) {
      return false;
    }
    if (!VariablePresentationHint?.canParse(obj['presentationHint'])) {
      return false;
    }
    if (obj['result'] is! String) {
      return false;
    }
    if (obj['type'] is! String?) {
      return false;
    }
    if (obj['variablesReference'] is! int) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (indexedVariables != null) 'indexedVariables': indexedVariables,
        if (memoryReference != null) 'memoryReference': memoryReference,
        if (namedVariables != null) 'namedVariables': namedVariables,
        if (presentationHint != null) 'presentationHint': presentationHint,
        'result': result,
        if (type != null) 'type': type,
        'variablesReference': variablesReference,
      };
}

class ExceptionInfoResponseBody {
  /// Mode that caused the exception notification to be raised.
  final ExceptionBreakMode breakMode;

  /// Descriptive text for the exception provided by the debug adapter.
  final String? description;

  /// Detailed information about the exception.
  final ExceptionDetails? details;

  /// ID of the exception that was thrown.
  final String exceptionId;

  static ExceptionInfoResponseBody fromJson(Map<String, Object?> obj) =>
      ExceptionInfoResponseBody.fromMap(obj);

  ExceptionInfoResponseBody({
    required this.breakMode,
    this.description,
    this.details,
    required this.exceptionId,
  });

  ExceptionInfoResponseBody.fromMap(Map<String, Object?> obj)
      : breakMode = ExceptionBreakMode.fromJson(
            obj['breakMode'] as Map<String, Object?>),
        description = obj['description'] as String?,
        details = obj['details'] == null
            ? null
            : ExceptionDetails.fromJson(obj['details'] as Map<String, Object?>),
        exceptionId = obj['exceptionId'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!ExceptionBreakMode.canParse(obj['breakMode'])) {
      return false;
    }
    if (obj['description'] is! String?) {
      return false;
    }
    if (!ExceptionDetails?.canParse(obj['details'])) {
      return false;
    }
    if (obj['exceptionId'] is! String) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'breakMode': breakMode,
        if (description != null) 'description': description,
        if (details != null) 'details': details,
        'exceptionId': exceptionId,
      };
}

class ExitedEventBody extends EventBody {
  /// The exit code returned from the debuggee.
  final int exitCode;

  static ExitedEventBody fromJson(Map<String, Object?> obj) =>
      ExitedEventBody.fromMap(obj);

  ExitedEventBody({
    required this.exitCode,
  });

  ExitedEventBody.fromMap(Map<String, Object?> obj)
      : exitCode = obj['exitCode'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['exitCode'] is! int) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'exitCode': exitCode,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class GotoResponseBody {
  static GotoResponseBody fromJson(Map<String, Object?> obj) =>
      GotoResponseBody.fromMap(obj);

  GotoResponseBody();

  GotoResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class GotoTargetsResponseBody {
  /// The possible goto targets of the specified location.
  final List<GotoTarget> targets;

  static GotoTargetsResponseBody fromJson(Map<String, Object?> obj) =>
      GotoTargetsResponseBody.fromMap(obj);

  GotoTargetsResponseBody({
    required this.targets,
  });

  GotoTargetsResponseBody.fromMap(Map<String, Object?> obj)
      : targets = (obj['targets'] as List)
            .map((item) => GotoTarget.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['targets'] is! List ||
        (obj['targets'].any((item) => !GotoTarget.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'targets': targets,
      };
}

/// The capabilities of this debug adapter.
class InitializeResponseBody {
  static InitializeResponseBody fromJson(Map<String, Object?> obj) =>
      InitializeResponseBody.fromMap(obj);

  InitializeResponseBody();

  InitializeResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Event-specific information.
class InitializedEventBody extends EventBody {
  static InitializedEventBody fromJson(Map<String, Object?> obj) =>
      InitializedEventBody.fromMap(obj);

  InitializedEventBody();

  InitializedEventBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {};
}

class InvalidatedEventBody extends EventBody {
  /// Optional set of logical areas that got invalidated. This property has a
  /// hint characteristic: a client can only be expected to make a 'best effort'
  /// in honouring the areas but there are no guarantees. If this property is
  /// missing, empty, or if values are not understand the client should assume a
  /// single value 'all'.
  final List<InvalidatedAreas>? areas;

  /// If specified, the client only needs to refetch data related to this stack
  /// frame (and the 'threadId' is ignored).
  final int? stackFrameId;

  /// If specified, the client only needs to refetch data related to this
  /// thread.
  final int? threadId;

  static InvalidatedEventBody fromJson(Map<String, Object?> obj) =>
      InvalidatedEventBody.fromMap(obj);

  InvalidatedEventBody({
    this.areas,
    this.stackFrameId,
    this.threadId,
  });

  InvalidatedEventBody.fromMap(Map<String, Object?> obj)
      : areas = (obj['areas'] as List?)
            ?.map((item) =>
                InvalidatedAreas.fromJson(item as Map<String, Object?>))
            .toList(),
        stackFrameId = obj['stackFrameId'] as int?,
        threadId = obj['threadId'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['areas'] is! List ||
        (obj['areas'].any((item) => !InvalidatedAreas.canParse(item))))) {
      return false;
    }
    if (obj['stackFrameId'] is! int?) {
      return false;
    }
    if (obj['threadId'] is! int?) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (areas != null) 'areas': areas,
        if (stackFrameId != null) 'stackFrameId': stackFrameId,
        if (threadId != null) 'threadId': threadId,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class LaunchResponseBody {
  static LaunchResponseBody fromJson(Map<String, Object?> obj) =>
      LaunchResponseBody.fromMap(obj);

  LaunchResponseBody();

  LaunchResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class LoadedSourceEventBody extends EventBody {
  /// The reason for the event.
  final String reason;

  /// The new, changed, or removed source.
  final Source source;

  static LoadedSourceEventBody fromJson(Map<String, Object?> obj) =>
      LoadedSourceEventBody.fromMap(obj);

  LoadedSourceEventBody({
    required this.reason,
    required this.source,
  });

  LoadedSourceEventBody.fromMap(Map<String, Object?> obj)
      : reason = obj['reason'] as String,
        source = Source.fromJson(obj['source'] as Map<String, Object?>);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['reason'] is! String) {
      return false;
    }
    if (!Source.canParse(obj['source'])) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'reason': reason,
        'source': source,
      };
}

class LoadedSourcesResponseBody {
  /// Set of loaded sources.
  final List<Source> sources;

  static LoadedSourcesResponseBody fromJson(Map<String, Object?> obj) =>
      LoadedSourcesResponseBody.fromMap(obj);

  LoadedSourcesResponseBody({
    required this.sources,
  });

  LoadedSourcesResponseBody.fromMap(Map<String, Object?> obj)
      : sources = (obj['sources'] as List)
            .map((item) => Source.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['sources'] is! List ||
        (obj['sources'].any((item) => !Source.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'sources': sources,
      };
}

class ModuleEventBody extends EventBody {
  /// The new, changed, or removed module. In case of 'removed' only the module
  /// id is used.
  final Module module;

  /// The reason for the event.
  final String reason;

  static ModuleEventBody fromJson(Map<String, Object?> obj) =>
      ModuleEventBody.fromMap(obj);

  ModuleEventBody({
    required this.module,
    required this.reason,
  });

  ModuleEventBody.fromMap(Map<String, Object?> obj)
      : module = Module.fromJson(obj['module'] as Map<String, Object?>),
        reason = obj['reason'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (!Module.canParse(obj['module'])) {
      return false;
    }
    if (obj['reason'] is! String) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'module': module,
        'reason': reason,
      };
}

class ModulesResponseBody {
  /// All modules or range of modules.
  final List<Module> modules;

  /// The total number of modules available.
  final int? totalModules;

  static ModulesResponseBody fromJson(Map<String, Object?> obj) =>
      ModulesResponseBody.fromMap(obj);

  ModulesResponseBody({
    required this.modules,
    this.totalModules,
  });

  ModulesResponseBody.fromMap(Map<String, Object?> obj)
      : modules = (obj['modules'] as List)
            .map((item) => Module.fromJson(item as Map<String, Object?>))
            .toList(),
        totalModules = obj['totalModules'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['modules'] is! List ||
        (obj['modules'].any((item) => !Module.canParse(item))))) {
      return false;
    }
    if (obj['totalModules'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'modules': modules,
        if (totalModules != null) 'totalModules': totalModules,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class NextResponseBody {
  static NextResponseBody fromJson(Map<String, Object?> obj) =>
      NextResponseBody.fromMap(obj);

  NextResponseBody();

  NextResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class OutputEventBody extends EventBody {
  /// The output category. If not specified, 'console' is assumed.
  final String? category;

  /// An optional source location column where the output was produced.
  final int? column;

  /// Optional data to report. For the 'telemetry' category the data will be
  /// sent to telemetry, for the other categories the data is shown in JSON
  /// format.
  final Object? data;

  /// Support for keeping an output log organized by grouping related messages.
  final String? group;

  /// An optional source location line where the output was produced.
  final int? line;

  /// The output to report.
  final String output;

  /// An optional source location where the output was produced.
  final Source? source;

  /// If an attribute 'variablesReference' exists and its value is > 0, the
  /// output contains objects which can be retrieved by passing
  /// 'variablesReference' to the 'variables' request. The value should be less
  /// than or equal to 2147483647 (2^31-1).
  final int? variablesReference;

  static OutputEventBody fromJson(Map<String, Object?> obj) =>
      OutputEventBody.fromMap(obj);

  OutputEventBody({
    this.category,
    this.column,
    this.data,
    this.group,
    this.line,
    required this.output,
    this.source,
    this.variablesReference,
  });

  OutputEventBody.fromMap(Map<String, Object?> obj)
      : category = obj['category'] as String?,
        column = obj['column'] as int?,
        data = obj['data'],
        group = obj['group'] as String?,
        line = obj['line'] as int?,
        output = obj['output'] as String,
        source = obj['source'] == null
            ? null
            : Source.fromJson(obj['source'] as Map<String, Object?>),
        variablesReference = obj['variablesReference'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['category'] is! String?) {
      return false;
    }
    if (obj['column'] is! int?) {
      return false;
    }
    if (obj['group'] is! String?) {
      return false;
    }
    if (obj['line'] is! int?) {
      return false;
    }
    if (obj['output'] is! String) {
      return false;
    }
    if (!Source?.canParse(obj['source'])) {
      return false;
    }
    if (obj['variablesReference'] is! int?) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (category != null) 'category': category,
        if (column != null) 'column': column,
        if (data != null) 'data': data,
        if (group != null) 'group': group,
        if (line != null) 'line': line,
        'output': output,
        if (source != null) 'source': source,
        if (variablesReference != null)
          'variablesReference': variablesReference,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class PauseResponseBody {
  static PauseResponseBody fromJson(Map<String, Object?> obj) =>
      PauseResponseBody.fromMap(obj);

  PauseResponseBody();

  PauseResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class ProcessEventBody extends EventBody {
  /// If true, the process is running on the same computer as the debug adapter.
  final bool? isLocalProcess;

  /// The logical name of the process. This is usually the full path to
  /// process's executable file. Example: /home/example/myproj/program.js.
  final String name;

  /// The size of a pointer or address for this process, in bits. This value may
  /// be used by clients when formatting addresses for display.
  final int? pointerSize;

  /// Describes how the debug engine started debugging this process.
  final String? startMethod;

  /// The system process id of the debugged process. This property will be
  /// missing for non-system processes.
  final int? systemProcessId;

  static ProcessEventBody fromJson(Map<String, Object?> obj) =>
      ProcessEventBody.fromMap(obj);

  ProcessEventBody({
    this.isLocalProcess,
    required this.name,
    this.pointerSize,
    this.startMethod,
    this.systemProcessId,
  });

  ProcessEventBody.fromMap(Map<String, Object?> obj)
      : isLocalProcess = obj['isLocalProcess'] as bool?,
        name = obj['name'] as String,
        pointerSize = obj['pointerSize'] as int?,
        startMethod = obj['startMethod'] as String?,
        systemProcessId = obj['systemProcessId'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['isLocalProcess'] is! bool?) {
      return false;
    }
    if (obj['name'] is! String) {
      return false;
    }
    if (obj['pointerSize'] is! int?) {
      return false;
    }
    if (obj['startMethod'] is! String?) {
      return false;
    }
    if (obj['systemProcessId'] is! int?) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (isLocalProcess != null) 'isLocalProcess': isLocalProcess,
        'name': name,
        if (pointerSize != null) 'pointerSize': pointerSize,
        if (startMethod != null) 'startMethod': startMethod,
        if (systemProcessId != null) 'systemProcessId': systemProcessId,
      };
}

class ProgressEndEventBody extends EventBody {
  /// Optional, more detailed progress message. If omitted, the previous message
  /// (if any) is used.
  final String? message;

  /// The ID that was introduced in the initial 'ProgressStartEvent'.
  final String progressId;

  static ProgressEndEventBody fromJson(Map<String, Object?> obj) =>
      ProgressEndEventBody.fromMap(obj);

  ProgressEndEventBody({
    this.message,
    required this.progressId,
  });

  ProgressEndEventBody.fromMap(Map<String, Object?> obj)
      : message = obj['message'] as String?,
        progressId = obj['progressId'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['message'] is! String?) {
      return false;
    }
    if (obj['progressId'] is! String) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (message != null) 'message': message,
        'progressId': progressId,
      };
}

class ProgressStartEventBody extends EventBody {
  /// If true, the request that reports progress may be canceled with a 'cancel'
  /// request.
  /// So this property basically controls whether the client should use UX that
  /// supports cancellation.
  /// Clients that don't support cancellation are allowed to ignore the setting.
  final bool? cancellable;

  /// Optional, more detailed progress message.
  final String? message;

  /// Optional progress percentage to display (value range: 0 to 100). If
  /// omitted no percentage will be shown.
  final num? percentage;

  /// An ID that must be used in subsequent 'progressUpdate' and 'progressEnd'
  /// events to make them refer to the same progress reporting.
  /// IDs must be unique within a debug session.
  final String progressId;

  /// The request ID that this progress report is related to. If specified a
  /// debug adapter is expected to emit
  /// progress events for the long running request until the request has been
  /// either completed or cancelled.
  /// If the request ID is omitted, the progress report is assumed to be related
  /// to some general activity of the debug adapter.
  final int? requestId;

  /// Mandatory (short) title of the progress reporting. Shown in the UI to
  /// describe the long running operation.
  final String title;

  static ProgressStartEventBody fromJson(Map<String, Object?> obj) =>
      ProgressStartEventBody.fromMap(obj);

  ProgressStartEventBody({
    this.cancellable,
    this.message,
    this.percentage,
    required this.progressId,
    this.requestId,
    required this.title,
  });

  ProgressStartEventBody.fromMap(Map<String, Object?> obj)
      : cancellable = obj['cancellable'] as bool?,
        message = obj['message'] as String?,
        percentage = obj['percentage'] as num?,
        progressId = obj['progressId'] as String,
        requestId = obj['requestId'] as int?,
        title = obj['title'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['cancellable'] is! bool?) {
      return false;
    }
    if (obj['message'] is! String?) {
      return false;
    }
    if (obj['percentage'] is! num?) {
      return false;
    }
    if (obj['progressId'] is! String) {
      return false;
    }
    if (obj['requestId'] is! int?) {
      return false;
    }
    if (obj['title'] is! String) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (cancellable != null) 'cancellable': cancellable,
        if (message != null) 'message': message,
        if (percentage != null) 'percentage': percentage,
        'progressId': progressId,
        if (requestId != null) 'requestId': requestId,
        'title': title,
      };
}

class ProgressUpdateEventBody extends EventBody {
  /// Optional, more detailed progress message. If omitted, the previous message
  /// (if any) is used.
  final String? message;

  /// Optional progress percentage to display (value range: 0 to 100). If
  /// omitted no percentage will be shown.
  final num? percentage;

  /// The ID that was introduced in the initial 'progressStart' event.
  final String progressId;

  static ProgressUpdateEventBody fromJson(Map<String, Object?> obj) =>
      ProgressUpdateEventBody.fromMap(obj);

  ProgressUpdateEventBody({
    this.message,
    this.percentage,
    required this.progressId,
  });

  ProgressUpdateEventBody.fromMap(Map<String, Object?> obj)
      : message = obj['message'] as String?,
        percentage = obj['percentage'] as num?,
        progressId = obj['progressId'] as String;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['message'] is! String?) {
      return false;
    }
    if (obj['percentage'] is! num?) {
      return false;
    }
    if (obj['progressId'] is! String) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (message != null) 'message': message,
        if (percentage != null) 'percentage': percentage,
        'progressId': progressId,
      };
}

class ReadMemoryResponseBody {
  /// The address of the first byte of data returned.
  /// Treated as a hex value if prefixed with '0x', or as a decimal value
  /// otherwise.
  final String address;

  /// The bytes read from memory, encoded using base64.
  final String? data;

  /// The number of unreadable bytes encountered after the last successfully
  /// read byte.
  /// This can be used to determine the number of bytes that must be skipped
  /// before a subsequent 'readMemory' request will succeed.
  final int? unreadableBytes;

  static ReadMemoryResponseBody fromJson(Map<String, Object?> obj) =>
      ReadMemoryResponseBody.fromMap(obj);

  ReadMemoryResponseBody({
    required this.address,
    this.data,
    this.unreadableBytes,
  });

  ReadMemoryResponseBody.fromMap(Map<String, Object?> obj)
      : address = obj['address'] as String,
        data = obj['data'] as String?,
        unreadableBytes = obj['unreadableBytes'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['address'] is! String) {
      return false;
    }
    if (obj['data'] is! String?) {
      return false;
    }
    if (obj['unreadableBytes'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'address': address,
        if (data != null) 'data': data,
        if (unreadableBytes != null) 'unreadableBytes': unreadableBytes,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class RestartFrameResponseBody {
  static RestartFrameResponseBody fromJson(Map<String, Object?> obj) =>
      RestartFrameResponseBody.fromMap(obj);

  RestartFrameResponseBody();

  RestartFrameResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Contains request result if success is true and optional error details if
/// success is false.
class RestartResponseBody {
  static RestartResponseBody fromJson(Map<String, Object?> obj) =>
      RestartResponseBody.fromMap(obj);

  RestartResponseBody();

  RestartResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Contains request result if success is true and optional error details if
/// success is false.
class ReverseContinueResponseBody {
  static ReverseContinueResponseBody fromJson(Map<String, Object?> obj) =>
      ReverseContinueResponseBody.fromMap(obj);

  ReverseContinueResponseBody();

  ReverseContinueResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class RunInTerminalResponseBody {
  /// The process ID. The value should be less than or equal to 2147483647
  /// (2^31-1).
  final int? processId;

  /// The process ID of the terminal shell. The value should be less than or
  /// equal to 2147483647 (2^31-1).
  final int? shellProcessId;

  static RunInTerminalResponseBody fromJson(Map<String, Object?> obj) =>
      RunInTerminalResponseBody.fromMap(obj);

  RunInTerminalResponseBody({
    this.processId,
    this.shellProcessId,
  });

  RunInTerminalResponseBody.fromMap(Map<String, Object?> obj)
      : processId = obj['processId'] as int?,
        shellProcessId = obj['shellProcessId'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['processId'] is! int?) {
      return false;
    }
    if (obj['shellProcessId'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (processId != null) 'processId': processId,
        if (shellProcessId != null) 'shellProcessId': shellProcessId,
      };
}

class ScopesResponseBody {
  /// The scopes of the stackframe. If the array has length zero, there are no
  /// scopes available.
  final List<Scope> scopes;

  static ScopesResponseBody fromJson(Map<String, Object?> obj) =>
      ScopesResponseBody.fromMap(obj);

  ScopesResponseBody({
    required this.scopes,
  });

  ScopesResponseBody.fromMap(Map<String, Object?> obj)
      : scopes = (obj['scopes'] as List)
            .map((item) => Scope.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['scopes'] is! List ||
        (obj['scopes'].any((item) => !Scope.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'scopes': scopes,
      };
}

class SetBreakpointsResponseBody {
  /// Information about the breakpoints.
  /// The array elements are in the same order as the elements of the
  /// 'breakpoints' (or the deprecated 'lines') array in the arguments.
  final List<Breakpoint> breakpoints;

  static SetBreakpointsResponseBody fromJson(Map<String, Object?> obj) =>
      SetBreakpointsResponseBody.fromMap(obj);

  SetBreakpointsResponseBody({
    required this.breakpoints,
  });

  SetBreakpointsResponseBody.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map((item) => Breakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints'].any((item) => !Breakpoint.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

class SetDataBreakpointsResponseBody {
  /// Information about the data breakpoints. The array elements correspond to
  /// the elements of the input argument 'breakpoints' array.
  final List<Breakpoint> breakpoints;

  static SetDataBreakpointsResponseBody fromJson(Map<String, Object?> obj) =>
      SetDataBreakpointsResponseBody.fromMap(obj);

  SetDataBreakpointsResponseBody({
    required this.breakpoints,
  });

  SetDataBreakpointsResponseBody.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map((item) => Breakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints'].any((item) => !Breakpoint.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

class SetExceptionBreakpointsResponseBody {
  /// Information about the exception breakpoints or filters.
  /// The breakpoints returned are in the same order as the elements of the
  /// 'filters', 'filterOptions', 'exceptionOptions' arrays in the arguments. If
  /// both 'filters' and 'filterOptions' are given, the returned array must
  /// start with 'filters' information first, followed by 'filterOptions'
  /// information.
  final List<Breakpoint>? breakpoints;

  static SetExceptionBreakpointsResponseBody fromJson(
          Map<String, Object?> obj) =>
      SetExceptionBreakpointsResponseBody.fromMap(obj);

  SetExceptionBreakpointsResponseBody({
    this.breakpoints,
  });

  SetExceptionBreakpointsResponseBody.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List?)
            ?.map((item) => Breakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints'].any((item) => !Breakpoint.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (breakpoints != null) 'breakpoints': breakpoints,
      };
}

class SetExpressionResponseBody {
  /// The number of indexed child variables.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? indexedVariables;

  /// The number of named child variables.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? namedVariables;

  /// Properties of a value that can be used to determine how to render the
  /// result in the UI.
  final VariablePresentationHint? presentationHint;

  /// The optional type of the value.
  /// This attribute should only be returned by a debug adapter if the client
  /// has passed the value true for the 'supportsVariableType' capability of the
  /// 'initialize' request.
  final String? type;

  /// The new value of the expression.
  final String value;

  /// If variablesReference is > 0, the value is structured and its children can
  /// be retrieved by passing variablesReference to the VariablesRequest.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? variablesReference;

  static SetExpressionResponseBody fromJson(Map<String, Object?> obj) =>
      SetExpressionResponseBody.fromMap(obj);

  SetExpressionResponseBody({
    this.indexedVariables,
    this.namedVariables,
    this.presentationHint,
    this.type,
    required this.value,
    this.variablesReference,
  });

  SetExpressionResponseBody.fromMap(Map<String, Object?> obj)
      : indexedVariables = obj['indexedVariables'] as int?,
        namedVariables = obj['namedVariables'] as int?,
        presentationHint = obj['presentationHint'] == null
            ? null
            : VariablePresentationHint.fromJson(
                obj['presentationHint'] as Map<String, Object?>),
        type = obj['type'] as String?,
        value = obj['value'] as String,
        variablesReference = obj['variablesReference'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['indexedVariables'] is! int?) {
      return false;
    }
    if (obj['namedVariables'] is! int?) {
      return false;
    }
    if (!VariablePresentationHint?.canParse(obj['presentationHint'])) {
      return false;
    }
    if (obj['type'] is! String?) {
      return false;
    }
    if (obj['value'] is! String) {
      return false;
    }
    if (obj['variablesReference'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (indexedVariables != null) 'indexedVariables': indexedVariables,
        if (namedVariables != null) 'namedVariables': namedVariables,
        if (presentationHint != null) 'presentationHint': presentationHint,
        if (type != null) 'type': type,
        'value': value,
        if (variablesReference != null)
          'variablesReference': variablesReference,
      };
}

class SetFunctionBreakpointsResponseBody {
  /// Information about the breakpoints. The array elements correspond to the
  /// elements of the 'breakpoints' array.
  final List<Breakpoint> breakpoints;

  static SetFunctionBreakpointsResponseBody fromJson(
          Map<String, Object?> obj) =>
      SetFunctionBreakpointsResponseBody.fromMap(obj);

  SetFunctionBreakpointsResponseBody({
    required this.breakpoints,
  });

  SetFunctionBreakpointsResponseBody.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map((item) => Breakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints'].any((item) => !Breakpoint.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

class SetInstructionBreakpointsResponseBody {
  /// Information about the breakpoints. The array elements correspond to the
  /// elements of the 'breakpoints' array.
  final List<Breakpoint> breakpoints;

  static SetInstructionBreakpointsResponseBody fromJson(
          Map<String, Object?> obj) =>
      SetInstructionBreakpointsResponseBody.fromMap(obj);

  SetInstructionBreakpointsResponseBody({
    required this.breakpoints,
  });

  SetInstructionBreakpointsResponseBody.fromMap(Map<String, Object?> obj)
      : breakpoints = (obj['breakpoints'] as List)
            .map((item) => Breakpoint.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['breakpoints'] is! List ||
        (obj['breakpoints'].any((item) => !Breakpoint.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'breakpoints': breakpoints,
      };
}

class SetVariableResponseBody {
  /// The number of indexed child variables.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? indexedVariables;

  /// The number of named child variables.
  /// The client can use this optional information to present the variables in a
  /// paged UI and fetch them in chunks.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? namedVariables;

  /// The type of the new value. Typically shown in the UI when hovering over
  /// the value.
  final String? type;

  /// The new value of the variable.
  final String value;

  /// If variablesReference is > 0, the new value is structured and its children
  /// can be retrieved by passing variablesReference to the VariablesRequest.
  /// The value should be less than or equal to 2147483647 (2^31-1).
  final int? variablesReference;

  static SetVariableResponseBody fromJson(Map<String, Object?> obj) =>
      SetVariableResponseBody.fromMap(obj);

  SetVariableResponseBody({
    this.indexedVariables,
    this.namedVariables,
    this.type,
    required this.value,
    this.variablesReference,
  });

  SetVariableResponseBody.fromMap(Map<String, Object?> obj)
      : indexedVariables = obj['indexedVariables'] as int?,
        namedVariables = obj['namedVariables'] as int?,
        type = obj['type'] as String?,
        value = obj['value'] as String,
        variablesReference = obj['variablesReference'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['indexedVariables'] is! int?) {
      return false;
    }
    if (obj['namedVariables'] is! int?) {
      return false;
    }
    if (obj['type'] is! String?) {
      return false;
    }
    if (obj['value'] is! String) {
      return false;
    }
    if (obj['variablesReference'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        if (indexedVariables != null) 'indexedVariables': indexedVariables,
        if (namedVariables != null) 'namedVariables': namedVariables,
        if (type != null) 'type': type,
        'value': value,
        if (variablesReference != null)
          'variablesReference': variablesReference,
      };
}

class SourceResponseBody {
  /// Content of the source reference.
  final String content;

  /// Optional content type (mime type) of the source.
  final String? mimeType;

  static SourceResponseBody fromJson(Map<String, Object?> obj) =>
      SourceResponseBody.fromMap(obj);

  SourceResponseBody({
    required this.content,
    this.mimeType,
  });

  SourceResponseBody.fromMap(Map<String, Object?> obj)
      : content = obj['content'] as String,
        mimeType = obj['mimeType'] as String?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['content'] is! String) {
      return false;
    }
    if (obj['mimeType'] is! String?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'content': content,
        if (mimeType != null) 'mimeType': mimeType,
      };
}

class StackTraceResponseBody {
  /// The frames of the stackframe. If the array has length zero, there are no
  /// stackframes available.
  /// This means that there is no location information available.
  final List<StackFrame> stackFrames;

  /// The total number of frames available in the stack. If omitted or if
  /// totalFrames is larger than the available frames, a client is expected to
  /// request frames until a request returns less frames than requested (which
  /// indicates the end of the stack). Returning monotonically increasing
  /// totalFrames values for subsequent requests can be used to enforce paging
  /// in the client.
  final int? totalFrames;

  static StackTraceResponseBody fromJson(Map<String, Object?> obj) =>
      StackTraceResponseBody.fromMap(obj);

  StackTraceResponseBody({
    required this.stackFrames,
    this.totalFrames,
  });

  StackTraceResponseBody.fromMap(Map<String, Object?> obj)
      : stackFrames = (obj['stackFrames'] as List)
            .map((item) => StackFrame.fromJson(item as Map<String, Object?>))
            .toList(),
        totalFrames = obj['totalFrames'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['stackFrames'] is! List ||
        (obj['stackFrames'].any((item) => !StackFrame.canParse(item))))) {
      return false;
    }
    if (obj['totalFrames'] is! int?) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'stackFrames': stackFrames,
        if (totalFrames != null) 'totalFrames': totalFrames,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class StepBackResponseBody {
  static StepBackResponseBody fromJson(Map<String, Object?> obj) =>
      StepBackResponseBody.fromMap(obj);

  StepBackResponseBody();

  StepBackResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Contains request result if success is true and optional error details if
/// success is false.
class StepInResponseBody {
  static StepInResponseBody fromJson(Map<String, Object?> obj) =>
      StepInResponseBody.fromMap(obj);

  StepInResponseBody();

  StepInResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class StepInTargetsResponseBody {
  /// The possible stepIn targets of the specified source location.
  final List<StepInTarget> targets;

  static StepInTargetsResponseBody fromJson(Map<String, Object?> obj) =>
      StepInTargetsResponseBody.fromMap(obj);

  StepInTargetsResponseBody({
    required this.targets,
  });

  StepInTargetsResponseBody.fromMap(Map<String, Object?> obj)
      : targets = (obj['targets'] as List)
            .map((item) => StepInTarget.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['targets'] is! List ||
        (obj['targets'].any((item) => !StepInTarget.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'targets': targets,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class StepOutResponseBody {
  static StepOutResponseBody fromJson(Map<String, Object?> obj) =>
      StepOutResponseBody.fromMap(obj);

  StepOutResponseBody();

  StepOutResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class StoppedEventBody extends EventBody {
  /// If 'allThreadsStopped' is true, a debug adapter can announce that all
  /// threads have stopped.
  /// - The client should use this information to enable that all threads can be expanded to access their stacktraces.
  /// - If the attribute is missing or false, only the thread with the given threadId can be expanded.
  final bool? allThreadsStopped;

  /// The full reason for the event, e.g. 'Paused on exception'. This string is
  /// shown in the UI as is and must be translated.
  final String? description;

  /// Ids of the breakpoints that triggered the event. In most cases there will
  /// be only a single breakpoint but here are some examples for multiple
  /// breakpoints:
  /// - Different types of breakpoints map to the same location.
  /// - Multiple source breakpoints get collapsed to the same instruction by the compiler/runtime.
  /// - Multiple function breakpoints with different function names map to the same location.
  final List<int>? hitBreakpointIds;

  /// A value of true hints to the frontend that this event should not change
  /// the focus.
  final bool? preserveFocusHint;

  /// The reason for the event.
  /// For backward compatibility this string is shown in the UI if the
  /// 'description' attribute is missing (but it must not be translated).
  final String reason;

  /// Additional information. E.g. if reason is 'exception', text contains the
  /// exception name. This string is shown in the UI.
  final String? text;

  /// The thread which was stopped.
  final int? threadId;

  static StoppedEventBody fromJson(Map<String, Object?> obj) =>
      StoppedEventBody.fromMap(obj);

  StoppedEventBody({
    this.allThreadsStopped,
    this.description,
    this.hitBreakpointIds,
    this.preserveFocusHint,
    required this.reason,
    this.text,
    this.threadId,
  });

  StoppedEventBody.fromMap(Map<String, Object?> obj)
      : allThreadsStopped = obj['allThreadsStopped'] as bool?,
        description = obj['description'] as String?,
        hitBreakpointIds = (obj['hitBreakpointIds'] as List?)
            ?.map((item) => item as int)
            .toList(),
        preserveFocusHint = obj['preserveFocusHint'] as bool?,
        reason = obj['reason'] as String,
        text = obj['text'] as String?,
        threadId = obj['threadId'] as int?;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['allThreadsStopped'] is! bool?) {
      return false;
    }
    if (obj['description'] is! String?) {
      return false;
    }
    if ((obj['hitBreakpointIds'] is! List ||
        (obj['hitBreakpointIds'].any((item) => item is! int)))) {
      return false;
    }
    if (obj['preserveFocusHint'] is! bool?) {
      return false;
    }
    if (obj['reason'] is! String) {
      return false;
    }
    if (obj['text'] is! String?) {
      return false;
    }
    if (obj['threadId'] is! int?) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (allThreadsStopped != null) 'allThreadsStopped': allThreadsStopped,
        if (description != null) 'description': description,
        if (hitBreakpointIds != null) 'hitBreakpointIds': hitBreakpointIds,
        if (preserveFocusHint != null) 'preserveFocusHint': preserveFocusHint,
        'reason': reason,
        if (text != null) 'text': text,
        if (threadId != null) 'threadId': threadId,
      };
}

/// Contains request result if success is true and optional error details if
/// success is false.
class TerminateResponseBody {
  static TerminateResponseBody fromJson(Map<String, Object?> obj) =>
      TerminateResponseBody.fromMap(obj);

  TerminateResponseBody();

  TerminateResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

/// Contains request result if success is true and optional error details if
/// success is false.
class TerminateThreadsResponseBody {
  static TerminateThreadsResponseBody fromJson(Map<String, Object?> obj) =>
      TerminateThreadsResponseBody.fromMap(obj);

  TerminateThreadsResponseBody();

  TerminateThreadsResponseBody.fromMap(Map<String, Object?> obj);

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {};
}

class TerminatedEventBody extends EventBody {
  /// A debug adapter may set 'restart' to true (or to an arbitrary object) to
  /// request that the front end restarts the session.
  /// The value is not interpreted by the client and passed unmodified as an
  /// attribute '__restart' to the 'launch' and 'attach' requests.
  final Object? restart;

  static TerminatedEventBody fromJson(Map<String, Object?> obj) =>
      TerminatedEventBody.fromMap(obj);

  TerminatedEventBody({
    this.restart,
  });

  TerminatedEventBody.fromMap(Map<String, Object?> obj)
      : restart = obj['restart'];

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        if (restart != null) 'restart': restart,
      };
}

class ThreadEventBody extends EventBody {
  /// The reason for the event.
  final String reason;

  /// The identifier of the thread.
  final int threadId;

  static ThreadEventBody fromJson(Map<String, Object?> obj) =>
      ThreadEventBody.fromMap(obj);

  ThreadEventBody({
    required this.reason,
    required this.threadId,
  });

  ThreadEventBody.fromMap(Map<String, Object?> obj)
      : reason = obj['reason'] as String,
        threadId = obj['threadId'] as int;

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if (obj['reason'] is! String) {
      return false;
    }
    if (obj['threadId'] is! int) {
      return false;
    }
    return EventBody.canParse(obj);
  }

  Map<String, Object?> toJson() => {
        'reason': reason,
        'threadId': threadId,
      };
}

class ThreadsResponseBody {
  /// All threads.
  final List<Thread> threads;

  static ThreadsResponseBody fromJson(Map<String, Object?> obj) =>
      ThreadsResponseBody.fromMap(obj);

  ThreadsResponseBody({
    required this.threads,
  });

  ThreadsResponseBody.fromMap(Map<String, Object?> obj)
      : threads = (obj['threads'] as List)
            .map((item) => Thread.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['threads'] is! List ||
        (obj['threads'].any((item) => !Thread.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'threads': threads,
      };
}

class VariablesResponseBody {
  /// All (or a range) of variables for the given variable reference.
  final List<Variable> variables;

  static VariablesResponseBody fromJson(Map<String, Object?> obj) =>
      VariablesResponseBody.fromMap(obj);

  VariablesResponseBody({
    required this.variables,
  });

  VariablesResponseBody.fromMap(Map<String, Object?> obj)
      : variables = (obj['variables'] as List)
            .map((item) => Variable.fromJson(item as Map<String, Object?>))
            .toList();

  static bool canParse(Object? obj) {
    if (obj is! Map<String, dynamic>) {
      return false;
    }
    if ((obj['variables'] is! List ||
        (obj['variables'].any((item) => !Variable.canParse(item))))) {
      return false;
    }
    return true;
  }

  Map<String, Object?> toJson() => {
        'variables': variables,
      };
}

const eventTypes = {
  BreakpointEventBody: 'breakpoint',
  CapabilitiesEventBody: 'capabilities',
  ContinuedEventBody: 'continued',
  ExitedEventBody: 'exited',
  InitializedEventBody: 'initialized',
  InvalidatedEventBody: 'invalidated',
  LoadedSourceEventBody: 'loadedSource',
  ModuleEventBody: 'module',
  OutputEventBody: 'output',
  ProcessEventBody: 'process',
  ProgressEndEventBody: 'progressEnd',
  ProgressStartEventBody: 'progressStart',
  ProgressUpdateEventBody: 'progressUpdate',
  StoppedEventBody: 'stopped',
  TerminatedEventBody: 'terminated',
  ThreadEventBody: 'thread',
};

const commandTypes = {
  AttachRequestArguments: 'attach',
  BreakpointLocationsArguments: 'breakpointLocations',
  CancelArguments: 'cancel',
  CompletionsArguments: 'completions',
  ConfigurationDoneArguments: 'configurationDone',
  ContinueArguments: 'continue',
  DataBreakpointInfoArguments: 'dataBreakpointInfo',
  DisassembleArguments: 'disassemble',
  DisconnectArguments: 'disconnect',
  EvaluateArguments: 'evaluate',
  ExceptionInfoArguments: 'exceptionInfo',
  GotoArguments: 'goto',
  GotoTargetsArguments: 'gotoTargets',
  InitializeRequestArguments: 'initialize',
  LaunchRequestArguments: 'launch',
  LoadedSourcesArguments: 'loadedSources',
  ModulesArguments: 'modules',
  NextArguments: 'next',
  PauseArguments: 'pause',
  ReadMemoryArguments: 'readMemory',
  RestartFrameArguments: 'restartFrame',
  RestartArguments: 'restart',
  ReverseContinueArguments: 'reverseContinue',
  RunInTerminalRequestArguments: 'runInTerminal',
  ScopesArguments: 'scopes',
  SetBreakpointsArguments: 'setBreakpoints',
  SetDataBreakpointsArguments: 'setDataBreakpoints',
  SetExceptionBreakpointsArguments: 'setExceptionBreakpoints',
  SetExpressionArguments: 'setExpression',
  SetFunctionBreakpointsArguments: 'setFunctionBreakpoints',
  SetInstructionBreakpointsArguments: 'setInstructionBreakpoints',
  SetVariableArguments: 'setVariable',
  SourceArguments: 'source',
  StackTraceArguments: 'stackTrace',
  StepBackArguments: 'stepBack',
  StepInArguments: 'stepIn',
  StepInTargetsArguments: 'stepInTargets',
  StepOutArguments: 'stepOut',
  TerminateArguments: 'terminate',
  TerminateThreadsArguments: 'terminateThreads',
  VariablesArguments: 'variables',
};
