// 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 'package:dds/src/dap/protocol_common.dart';
import 'package:dds/src/dap/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',
};
