================
@@ -0,0 +1,2022 @@
+# NOTE: this module must not include `from __future__ import annotations`
+# as the `annotations` import changes some of the types hints to strings.
+# especially when you have a forward declared type reference.
+# see https://peps.python.org/pep-0649/#motivation-for-this-pep
+# https://peps.python.org/pep-0749/#rejected-alternatives
+#
+# This module may not depend on any other module.
+
+from contextlib import suppress
+import copy
+import dataclasses
+import enum
+import json
+import os
+import sys
+import typing
+from dataclasses import asdict, dataclass, field, is_dataclass
+from enum import Enum
+from functools import lru_cache
+from typing import (
+    Any,
+    ClassVar,
+    Dict,
+    List,
+    Literal,
+    Optional,
+    Protocol,
+    Set,
+    Tuple,
+    Type,
+    TypeVar,
+    Union,
+    runtime_checkable,
+)
+
+if sys.version_info >= (3, 11):
+    from enum import StrEnum
+else:
+
+    class StrEnum(str, Enum):
+        """Backport of StrEnum for Python < 3.11."""
+
+        def __str__(self) -> str:
+            return self.value
+
+        def __repr__(self) -> str:
+            return self.value
+
+        @staticmethod
+        def _generate_next_value_(name: str, start, count, last_values) -> str:
+            return name.lower()
+
+
+T = TypeVar("T")
+
+
+class DAPError(AssertionError):
+    """The base error for all DAP related errors
+
+    Inherits from assertion error because of unittests treats assertions 
outside of a test as a failure
+    instead of a test error. see 
https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUp
+    """
+
+    @classmethod
+    def history_closed(cls, reason=None, last_event: Optional["Event"] = None):
+        suffix = f" (Reason: {reason})" if reason else ""
+        return cls(
+            f"EventHistory is closed{suffix}. Last recorded event: 
{last_event}."
+        )
+
+
+RawMessage = Dict[str, Any]
+"""Representation of a json protocol message """
+
+
+class MessageType(StrEnum):
+    REQUEST = "request"
+    RESPONSE = "response"
+    EVENT = "event"
+
+
+class EventName(StrEnum):
+    BREAKPOINT = "breakpoint"
+    CAPABILITIES = "capabilities"
+    CONTINUED = "continued"
+    EXITED = "exited"
+    INITIALIZED = "initialized"
+    INVALIDATED = "invalidated"
+    MEMORY = "memory"
+    MODULE = "module"
+    OUTPUT = "output"
+    PROCESS = "process"
+    PROGRESS_END = "progressEnd"
+    PROGRESS_START = "progressStart"
+    PROGRESS_UPDATE = "progressUpdate"
+    STOPPED = "stopped"
+    TERMINATED = "terminated"
+    THREAD = "thread"
+
+
+@dataclass(frozen=True)
+class ProtocolMessage:
+    type: MessageType
+    seq: int
+
+    def to_dict(self):
+        return message_to_dict(self)
+
+    @classmethod
+    def from_json(cls: Type[T], json: RawMessage) -> T:
+        if not dataclasses.is_dataclass(cls):
+            raise ValueError(f"{cls.__name__} must be a dataclass")
+
+        return dict_to_message(cls, json)
+
+
+@dataclass(frozen=True)
+class Request(ProtocolMessage):
+    command: str
+    arguments: Any
+
+    def __post_init__(self):
+        assert (
+            self.type == MessageType.REQUEST
+        ), f"expected request type to be 'request' got '{self.type}' in : 
{self}"
+
+
+@dataclass(frozen=True)
+class Response(ProtocolMessage):
+    command: str
+    request_seq: int
+    success: bool
+
+    def __post_init__(self):
+        assert (
+            self.type == MessageType.RESPONSE
+        ), f"expected '{type(self).__name__}' to be of type response: {self}"
+
+    def __init_subclass__(cls, **kwargs):
+        super().__init_subclass__(**kwargs)
+        if not dataclasses.is_dataclass(cls):
+            raise TypeError(f"{cls.__name__} must be a dataclass")
+
+
+AnyResponse = TypeVar("AnyResponse", bound=Response)
+
+
+class RequestError(DAPError):
+    """Raised if a DAP request fails."""
+
+    def __init__(
+        self,
+        request: Union[Request, dict],
+        response: Optional[Union[Response, dict]] = None,
+    ):
+        super().__init__()
+        self.request = request
+        self.response = response
+
+    def __str__(self) -> str:
+        desc = f"request failed request={self.request!r}"
+        if self.response:
+            desc += f" response={self.response!r}"
+        return desc
+
+
+@dataclass(frozen=True)
+class Event(ProtocolMessage):
+    event: Union[EventName, str]
+    type: MessageType
+    __registry: ClassVar[Dict[str, Type]] = {}
+
+    def __init_subclass__(cls, *, event: str, **kwargs):
+        super().__init_subclass__(**kwargs)
+
+        assert event is not None
+        # Attach metadata (not a field of an event).
+        cls.__message_type__ = event
+
+        # Prevent duplicate types.
+        existing_event_class = Event.__registry.get(event)
+        if existing_event_class is not None:
+            raise Exception(
+                f"cannot register '{event}' event to class '{cls}' because it 
is already registered to '{existing_event_class}'"
+            )
+
+        Event.__registry[event] = cls
+
+    def __post_init__(self):
+        if self.type != MessageType.EVENT:
+            raise ValueError(f"event must have type of 'event': {self}")
+
+    @classmethod
+    def from_json(cls: Type[T], json: dict, check_class: bool = True) -> T:
+        event_type = json["event"]
+
+        if event_type not in Event.__registry:
+            raise ValueError(f"event type '{event_type}' is not registered")
+
+        event_class = Event.__registry[event_type]
+
+        if check_class and type(cls) != type(event_class):
+            raise ValueError(
+                f"class: {type(cls)} is not of the expected type 
{type(event_class)}"
+            )
+
+        if not dataclasses.is_dataclass(cls):
+            raise ValueError(f"{cls.__name__} must be a dataclass")
+
+        return dict_to_message(event_class, json)
+
+
+AnyEvent = TypeVar("AnyEvent", bound=Event)
+
+
+class EmptyBodyResponse(Response):
+    body: None = field(init=False, default=None)
+
+
+def args_protocol(cls):
+    """Decorator to check a class conforms to the ArgsProtocol"""
+
+    required_fields = filter(lambda x: not x.startswith("_"), 
dir(ArgsProtocol))
+    for r_field in required_fields:
+        if not hasattr(cls, r_field):
+            raise AttributeError(
+                f"{cls.__name__} must define '{r_field}' to implement 
ArgProtocol"
+            )
+
+    command_name = getattr(cls, "command_")
+    if not issubclass(type(command_name), str):
+        raise TypeError(
+            f"the command_ type '{type(command_name)}' for class 
'{cls.__name__}' must be string like"
+        )
+
+    return cls
+
+
+def _message_to_dict_impl(obj: typing.Any, skip_none: bool = True) -> 
typing.Any:
+    if dataclasses.is_dataclass(obj):
+        fields = _get_dataclass_fields(type(obj))
+        visited: Dict[str, Any] = {}
+        for f in fields:
+            dict_name = f.metadata.get("alias", f.name)
+            if dict_name in visited or not hasattr(obj, f.name):
+                continue
+            name_attr = getattr(obj, f.name)
+            if skip_none and name_attr is None:
+                continue
+            visited[dict_name] = _message_to_dict_impl(name_attr, skip_none)
+        return visited
+
+    if isinstance(obj, (list, tuple)):
+        return type(obj)(_message_to_dict_impl(item, skip_none) for item in 
obj)
+
+    if isinstance(obj, dict):
+        result: Dict[str, Any] = {}
+        for key, value in obj.items():
+            result[str(key)] = _message_to_dict_impl(value, skip_none)
+        return result
+
+    # Test enum first as it can also be a subclass of other primitives.
+    if isinstance(obj, Enum):
+        return obj.value
+
+    if isinstance(obj, (bool, int, float, str, bytes, type, type(None))):
+        return obj
+
+    return copy.deepcopy(obj)
+
+
+def message_to_dict(args: Any) -> RawMessage:
+    """
+    Converts DAP types to dictionaries.
+    We always skip optional types in dataclasses during conversion.
+    """
+    if not is_dataclass(args):
+        raise TypeError(
+            f"expected a dataclass instance, got {type(args).__name__}: 
{args!r}"
+        )
+    result = _message_to_dict_impl(args)
+    assert isinstance(result, dict)
+    return result
+
+
+@lru_cache
+def _get_dataclass_fields(cls: Type) -> Tuple[dataclasses.Field, ...]:
+    data_class_hints = typing.get_type_hints(cls)
+    result: List[dataclasses.Field] = []
+    for f in dataclasses.fields(cls):  # noqa
+        # Ignores 'command_' and 'response_class_'.
+        if f.name.endswith("_"):
+            continue
+        f_copy = copy.copy(f)
+        f_copy.type = data_class_hints[f_copy.name]
+        result.append(f_copy)
+    return tuple(result)
+
+
+@lru_cache
+def _prepare_dataclass_fields(cls: Type) -> Dict[str, dataclasses.Field]:
+    # Excludes init=False fields since they cannot be passed to __init__.
+    return {f.name: f for f in _get_dataclass_fields(cls) if f.init}
+
+
+def _get_compatible_union_types(data: Any, possible_types: List[Type]) -> 
List[Type]:
+    """Filters a list of candidate types to find those compatible with the 
given raw data.
+
+    This helps fail early on type mismatches during parsing. For example, it
+    ensures that a raw payload like `[10, 20]` is correctly matched to 
`List[int]`
+    rather than a primitive `int`.
+    """
+
+    def _is_type_compatible(candidate_type: Type, data: Any) -> bool:
+        """Helper function to check if a single type is compatible with the 
data."""
+        origin = typing.get_origin(candidate_type)
+
+        if dataclasses.is_dataclass(candidate_type) or origin is dict:
+            return isinstance(data, dict)
+
+        if origin in (list, tuple):
+            return isinstance(data, (list, tuple))
+
+        if candidate_type is bool:
+            return isinstance(data, bool)
+
+        if candidate_type in (int, float):
+            # Prevent implicit bool conversion as bool is a subclass of int.
+            return isinstance(data, (int, float)) and not isinstance(data, 
bool)
+
+        if candidate_type is str:
+            return isinstance(data, str)
+
+        if isinstance(candidate_type, type) and issubclass(candidate_type, 
enum.Enum):
+            if issubclass(candidate_type, enum.IntEnum):
+                return isinstance(data, int) and not isinstance(data, bool)
+            return isinstance(data, str)
+
+        # Fallback for unknown or other generic types
+        return True
+
+    result = [a_type for a_type in possible_types if 
_is_type_compatible(a_type, data)]
+    return result
+
+
+def _generic_to_message(cls: Optional[Type], data: Any, scope: List[str]) -> 
Any:
+    origin = typing.get_origin(cls)
+    args = typing.get_args(cls)
+    full_path = ".".join(scope)
+
+    if origin is Literal:
+        unique_literals: Set = set()
+
+        def flatten_literal(args: Any):
+            """'Literal' types can be nested e.g.
+            Literal[Literal["book"], Literal["pen"]] is the same as  
Literal["book", "pen"]
+            """
+            for val in args:
+                if typing.get_origin(val) is None:
+                    unique_literals.add(val)
+                else:
+                    flatten_literal(typing.get_args(val))
+
+        flatten_literal(args)
+
+        if data not in unique_literals:
+            raise ValueError(
+                f"expected one of {unique_literals!r} at {full_path}, got 
{data!r}"
+            )
+        return data
+
+    elif origin is Union:
+        none_type = type(None)
+        is_optional = none_type in args
+        candidate_args = [a for a in args if a is not none_type]
+
+        # Handle Optional.
+        # Optional is represented as Union[T, None].
+        if is_optional and len(candidate_args) == 1:
+            return _dict_to_message_impl(candidate_args[0], data, scope)
+
+        matches = _get_compatible_union_types(data, candidate_args)
+        if not matches:
+            raise TypeError(
+                f"no variant of {cls} is compatible with "
+                f"{type(data).__name__} at {full_path}: {data!r}"
+            )
+
+        # Only one match, try conversion.
+        if len(matches) == 1:
+            return _dict_to_message_impl(matches[0], data, scope)
+
+        for arg in matches:
+            with suppress(TypeError, ValueError, AttributeError, 
AssertionError):
+                return _dict_to_message_impl(arg, data, scope)
+
+        raise TypeError(
+            f"no variant of {cls} matched {type(data).__name__} at 
{full_path}: {data!r}"
+        )
+
+    elif origin is list:
+        if not isinstance(data, list):
+            raise TypeError(
+                f"expected list at {full_path}, got {type(data).__name__}: 
{data!r}"
+            )
+        list_type = args[0]
+        return [
+            _dict_to_message_impl(list_type, val, scope + [str(idx)])
+            for idx, val in enumerate(data)
+        ]
+
+    elif origin is tuple:
+        if not isinstance(data, list):
+            raise TypeError(
+                f"expected list for tuple at {full_path}, got 
{type(data).__name__}: {data!r}"
+            )
+        item_type = args[0]
+        return tuple(
+            _dict_to_message_impl(item_type, val, scope + [str(idx)])
+            for idx, val in enumerate(data)
+        )
+
+    elif origin is dict:
+        if not isinstance(data, dict):
+            raise TypeError(
+                f"expected dict at {full_path}, got {type(data).__name__}: 
{data!r}"
+            )
+        if len(args) == 0:
+            args = (str, Any)
+        key_type = args[0]
+        value_type = args[1]
+        return {
+            _dict_to_message_impl(key_type, key, scope): _dict_to_message_impl(
+                value_type, value, scope + [str(key)]
+            )
+            for key, value in data.items()
+        }
+
+    raise TypeError(f"unhandled generic type {cls} at {full_path}: {data!r}")
+
+
+def _dict_to_message_impl(
+    cls: Optional[Type], data: typing.Any, scope: List[str]
+) -> typing.Any:
+    """
+    Recursively deserializes a dictionary into a specified Python type or 
dataclass.
+
+    Args:
+        cls: The target Python type or dataclass to deserialize the data into.
+        data: The raw data (usually from a dictionary or JSON payload) to be 
converted.
+        scope: A list of keys representing the current depth in the nested 
data structure.
+               Used to provide error messages when validation fails.
+
+    Returns:
+        The deserialized data cast to the requested type or instantiated 
dataclass.
+
+    Raises:
+        TypeError: If the data type does not match the expected type and 
cannot be coerced.
+        ValueError: If a dataclass field has a required value that does not 
match the data.
+    """
+    if not cls:
+        return data
+
+    full_path = ".".join(scope)
+    if data is None:
+        # Only pass None through if the declared type permits it.
+        if cls is type(None):
+            return None
+        is_union = typing.get_origin(cls) is Union
+        if is_union and type(None) in typing.get_args(cls):  # Is Optional
+            return None
+
+        raise TypeError(f"got None for non-optional type '{cls}' at 
{full_path}")
+
+    if cls in (bytes, bytearray, Any):
+        return data
+
+    if dataclasses.is_dataclass(cls):
+        if not isinstance(data, dict):
+            raise TypeError(
+                f"expected dict for '{cls.__name__}' at {full_path}, "
+                f"got {type(data).__name__}: {data!r}"
+            )
+        fields = _prepare_dataclass_fields(cls)
+        deserialized = {}
+        for key, f in fields.items():
+            data_key = f.metadata.get("alias", key)
+            if data_key not in data:
+                continue
+
+            required_value = f.metadata.get("required", dataclasses.MISSING)
+            value = _dict_to_message_impl(f.type, data[data_key], scope + 
[key])
+
+            if required_value is not dataclasses.MISSING and value != 
required_value:
+                raise ValueError(
+                    f"field '{key}' at {full_path} must be {required_value!r}, 
"
+                    f"got {value!r}"
+                )
+            deserialized[key] = value
+        try:
+            return cls(**deserialized)
+        except TypeError as err:
+            msg = f"\n\tfailed to initialize '{cls.__name__}' at '{full_path}' 
"
+            msg += f'\n\twith dict: "{data}"'
+            err.args = (err.args[0] + msg, *err.args[1:])
+            raise
+
+    if cls in (str, int, float):
+        if isinstance(data, cls):
+            return data
+        # Allow int to float coercion but not bool as bool is a subclass of 
int:
+        if cls is float and isinstance(data, int) and not isinstance(data, 
bool):
+            return float(data)
+        raise TypeError(
+            f"expected {cls.__name__} at {full_path}, "
+            f"got {type(data).__name__}: {data!r}"
+        )
+
+    if cls is bool:
+        if not isinstance(data, bool):
+            raise TypeError(
+                f"expected bool at {full_path}, " f"got {type(data).__name__}: 
{data!r}"
+            )
+        return data
+
+    if isinstance(cls, type) and issubclass(cls, enum.Enum):
+        if issubclass(cls, enum.IntEnum):
+            return cls(int(data))
+        return cls(data)
+
+    # Handle generic types i.e List[T], Tuple[T] e.t.c.
+    if typing.get_origin(cls) is not None:
+        return _generic_to_message(cls, data, scope)
+
+    raise TypeError(
+        f"unexpected type {cls} at {full_path}: " f"got {type(data).__name__}: 
{data!r}"
+    )
+
+
+def dict_to_message(cls: Type[T], raw_dict: RawMessage) -> T:
+    return _dict_to_message_impl(cls, raw_dict, [cls.__name__])
+
+
+@runtime_checkable
+class ArgsProtocol(Protocol[T]):  # type: ignore[misc]
+    __dataclass_fields__: ClassVar[Dict]
+
+    @property
+    def response_class_(self) -> Type[T]:
+        ...
+
+    @property
+    def command_(self) -> str:
+        ...
+
+
+class Console(StrEnum):
+    INTERNAL = "internalConsole"
+    INTEGRATED_TERMINAL = "integratedTerminal"
+    EXTERNAL_TERMINAL = "externalTerminal"
+
+
+class OutputCategory(StrEnum):
+    CONSOLE = "console"
+    IMPORTANT = "important"
+    STDOUT = "stdout"
+    STDERR = "stderr"
+    TELEMETRY = "telemetry"
+
+
+class StoppedReason(StrEnum):
+    STEP = "step"
+    BREAKPOINT = "breakpoint"
+    EXCEPTION = "exception"
+    PAUSE = "pause"
+    ENTRY = "entry"
+    GOTO = "goto"
+    FUNCTION_BREAKPOINT = "function breakpoint"
+    DATA_BREAKPOINT = "data breakpoint"
+    INSTRUCTION_BREAKPOINT = "instruction breakpoint"
+
+
+class ModuleReason(StrEnum):
+    NEW = "new"
+    CHANGED = "changed"
+    REMOVED = "removed"
+
+
+class BreakpointReason(StrEnum):
+    NEW = "new"
+    CHANGED = "changed"
+    REMOVED = "removed"
+
+
+class InvalidatedAreas(StrEnum):
+    ALL = "all"
+    STACKS = "stacks"
+    THREADS = "threads"
+    VARIABLES = "variables"
+
+
+class StartDebuggingRequestType(StrEnum):
+    LAUNCH = "launch"
+    ATTACH = "attach"
+
+
+ExceptionBreakMode = Literal["never", "always", "unhandled", "userUnhandled"]
+ChecksumAlgorithm = Literal["MD5", "SHA1", "SHA256", "timestamp"]
+
+ScopePresentationHint = Literal["arguments", "locals", "registers"]
+SourcePresentationHint = Literal["normal", "emphasize", "deemphasize"]
+StepInTargetPresentationHint = Literal["normal", "label", "subtle"]
+GotoTargetPresentationHint = StepInTargetPresentationHint
+StackFramePresentationHint = StepInTargetPresentationHint
+
+VariablePresentationHintKind = Literal[
+    "property",
+    "method",
+    "class",
+    "data",
+    "event",
+    "baseClass",
+    "innerClass",
+    "interface",
+    "mostDerivedClass",
+    "virtual",
+    "dataBreakpoint",
+]
+
+VariablePresentationHintVisibility = Literal[
+    "public", "private", "protected", "internal", "final"
+]
+
+
+@dataclass(frozen=True)
+class Checksum:
+    algorithm: ChecksumAlgorithm
+    checksum: str
+
+
+@dataclass(frozen=True)
+class Source:
+    name: Optional[str] = None
+    path: Optional[str] = None
+    sourceReference: Optional[int] = None
+    presentationHint: Optional[SourcePresentationHint] = None
+    origin: Optional[str] = None
+    sources: Optional[List["Source"]] = None
+    adapterData: Optional[Any] = None
+    checksums: Optional[List[Checksum]] = None
+
+    def __post_init__(self):
+        if not self.name and not self.path and not self.sourceReference:
+            raise ValueError(
+                f"Source requires either name, path, or source_reference. 
{self}"
+            )
+
+    @classmethod
+    def create(cls, name: Optional[str] = None, path: Optional[str] = None, 
**kwargs):
+        if path and not name:
+            name = os.path.basename(path)
+
+        return cls(name=name, path=path, **kwargs)
+
+
+@dataclass(frozen=True)
+class Breakpoint:
+    verified: bool
+    id: Optional[int] = None
+    message: Optional[str] = None
+    source: Optional[Source] = None
+    line: Optional[int] = None
+    column: Optional[int] = None
+    endLine: Optional[int] = None
+    endColumn: Optional[int] = None
+    instructionReference: Optional[str] = None
+    offset: Optional[int] = None
+    reason: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class SourceBreakpoint:
+    line: int
+    column: Optional[int] = None
+    condition: Optional[str] = None
+    hitCondition: Optional[str] = None
+    logMessage: Optional[str] = None
+    mode: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class FunctionBreakpoint:
+    name: str
+    condition: Optional[str] = None
+    hitCondition: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class DataBreakpoint:
+    dataId: str
+    accessType: Optional[str] = None
+    condition: Optional[str] = None
+    hitCondition: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class InstructionBreakpoint:
+    instructionReference: str
+    offset: Optional[int] = None
+    condition: Optional[str] = None
+    hitCondition: Optional[str] = None
+    mode: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class BreakpointLocation:
+    line: int
+    column: Optional[int] = None
+    endLine: Optional[int] = None
+    endColumn: Optional[int] = None
+
+
+ColumnDescriptorType = Literal["string", "number", "boolean", 
"unixTimestampUTC"]
+
+
+@dataclass(frozen=True)
+class ColumnDescriptor:
+    attributeName: str
+    label: str
+    format: Optional[str] = None
+    type: Optional[ColumnDescriptorType] = None
+    width: Optional[int] = None
+
+
+@dataclass(frozen=True)
+class ExceptionFilterOptions:
+    filterId: str
+    condition: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class ExceptionPathSegment:
+    names: List[str]
+    negate: Optional[bool] = None
+
+
+@dataclass(frozen=True)
+class ExceptionOptions:
+    breakMode: ExceptionBreakMode
+    path: Optional[List[ExceptionPathSegment]] = None
+
+
+@dataclass(frozen=True)
+class ExceptionDetails:
+    message: Optional[str] = None
+    typeName: Optional[str] = None
+    fullTypeName: Optional[str] = None
+    evaluateName: Optional[str] = None
+    stackTrace: Optional[str] = None
+    innerException: Optional[List["ExceptionDetails"]] = None
+
+
+@dataclass(frozen=True)
+class ExceptionBreakpointsFilter:
+    filter: str
+    label: str
+    description: Optional[str] = None
+    default: Optional[bool] = None
+    supportsCondition: Optional[bool] = None
+    conditionDescription: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class Thread:
+    id: int
+    name: str
+
+
+@dataclass(frozen=True)
+class StackFrame:
+    id: int
+    name: str
+    line: int
+    column: int
+    source: Optional[Source] = None
+    endLine: Optional[int] = None
+    endColumn: Optional[int] = None
+    canRestart: Optional[bool] = None
+    instructionPointerReference: Optional[str] = None
+    moduleId: Optional[Union[int, str]] = None
+    presentationHint: Optional[StackFramePresentationHint] = None
+
+
+@dataclass(frozen=True)
+class Scope:
+    name: str
+    variablesReference: int
+    presentationHint: Optional[ScopePresentationHint] = None
+    namedVariables: Optional[int] = None
+    indexedVariables: Optional[int] = None
+    expensive: bool = False
+    source: Optional[Source] = None
+    line: Optional[int] = None
+    column: Optional[int] = None
+    endLine: Optional[int] = None
+    endColumn: Optional[int] = None
+
+
+@dataclass(frozen=True)
+class VariablePresentationHint:
+    kind: Optional[VariablePresentationHintKind] = None
+    attributes: Optional[List[str]] = None
+    visibility: Optional[VariablePresentationHintVisibility] = None
+    lazy: Optional[bool] = None
+
+
+@dataclass(frozen=True)
+class Variable:
+    name: str
+    value: str
+    variablesReference: int
+    type: Optional[str] = None
+    presentationHint: Optional[VariablePresentationHint] = None
+    evaluateName: Optional[str] = None
+    namedVariables: Optional[int] = None
+    indexedVariables: Optional[int] = None
+    memoryReference: Optional[str] = None
+    declarationLocationReference: Optional[int] = None
+    valueLocationReference: Optional[int] = None
+
+    @property
+    def value_as_int(self):
+        value = self.value
+        # 'value' may have the variable value and summary.
+        # Extract the variable value since summary can have nonnumeric 
characters.
+        value = value.split(" ")[0]
+        if value.startswith("0x"):
+            return int(value, 16)
+        elif value.startswith("0"):
+            return int(value, 8)
+        else:
+            return int(value)
+
+
+@dataclass(frozen=True)
+class Message:
+    id: int
+    format: str
+    variables: Optional[Dict[str, str]] = None
+    sendTelemetry: Optional[bool] = None
+    showUser: Optional[bool] = None
+    url: Optional[str] = None
+    urlLabel: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class Module:
+    id: str
+    name: str
+    path: Optional[str] = None
+    isOptimized: Optional[bool] = None
+    isUserCode: Optional[bool] = None
+    version: Optional[str] = None
+    symbolStatus: Optional[str] = None
+    symbolFilePath: Optional[str] = None
+    dateTimeStamp: Optional[str] = None
+    addressRange: Optional[str] = None
+    # custom
+    debugInfoSize: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class CompletionItem:
+    label: str
+    text: Optional[str] = None
+    detail: Optional[str] = None
+    start: Optional[int] = None
+    length: int = 0
+
+    def __repr__(self):
+        # Use json as it is easier to see the diff on failure.
+        return json.dumps(asdict(self), indent=4)
+
+    def clone(self, **kwargs) -> "CompletionItem":
+        """Creates a copy of this CompletionItem with specified fields 
modified."""
+        return dataclasses.replace(self, **kwargs)
+
+
+@dataclass(frozen=True)
+class ValueFormat:
+    hex: Optional[bool] = None
+
+
+@dataclass(frozen=True)
+class StackFrameFormat:
+    hex: Optional[bool] = None
+    parameters: Optional[bool] = None
+    parameterTypes: Optional[bool] = None
+    parameterNames: Optional[bool] = None
+    parameterValues: Optional[bool] = None
+    line: Optional[bool] = None
+    module: Optional[bool] = None
+    includeAll: Optional[bool] = None
+
+
+@dataclass(frozen=True)
+class GotoTarget:
+    id: int
+    label: str
+    line: int
+    column: Optional[int] = None
+    endLine: Optional[int] = None
+    endColumn: Optional[int] = None
+    instructionPointerReference: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class StepInTarget:
+    id: int
+    label: str
+    line: Optional[int] = None
+    column: Optional[int] = None
+    endLine: Optional[int] = None
+    endColumn: Optional[int] = None
+
+
+@dataclass(frozen=True)
+class DisassembledInstruction:
+    address: str
+    instruction: str
+    instructionBytes: Optional[str] = None
+    symbol: Optional[str] = None
+    location: Optional[Source] = None
+    line: Optional[int] = None
+    column: Optional[int] = None
+    endLine: Optional[int] = None
+    endColumn: Optional[int] = None
+    presentationHint: Optional[str] = None
+
+
+@dataclass(frozen=True)
+class Capabilities:
+    supportsConfigurationDoneRequest: Optional[bool] = None
+    supportsFunctionBreakpoints: Optional[bool] = None
+    supportsConditionalBreakpoints: Optional[bool] = None
+    supportsHitConditionalBreakpoints: Optional[bool] = None
+    supportsEvaluateForHovers: Optional[bool] = None
+    exceptionBreakpointFilters: Optional[List[ExceptionBreakpointsFilter]] = 
None
+    supportsStepBack: Optional[bool] = None
+    supportsSetVariable: Optional[bool] = None
+    supportsRestartFrame: Optional[bool] = None
+    supportsGotoTargetsRequest: Optional[bool] = None
+    supportsStepInTargetsRequest: Optional[bool] = None
+    supportsCompletionsRequest: Optional[bool] = None
+    completionTriggerCharacters: Optional[List[str]] = None
+    supportsModulesRequest: Optional[bool] = None
+    additionalModuleColumns: Optional[List[ColumnDescriptor]] = None
+    supportedChecksumAlgorithms: Optional[List[ChecksumAlgorithm]] = None
+    supportsRestartRequest: Optional[bool] = None
+    supportsExceptionOptions: Optional[bool] = None
+    supportsValueFormattingOptions: Optional[bool] = None
+    supportsExceptionInfoRequest: Optional[bool] = None
+    supportTerminateDebuggee: Optional[bool] = None
+    supportSuspendDebuggee: Optional[bool] = None
+    supportsDelayedStackTraceLoading: Optional[bool] = None
+    supportsLoadedSourcesRequest: Optional[bool] = None
+    supportsLogPoints: Optional[bool] = None
+    supportsTerminateThreadsRequest: Optional[bool] = None
+    supportsSetExpression: Optional[bool] = None
+    supportsTerminateRequest: Optional[bool] = None
+    supportsDataBreakpoints: Optional[bool] = None
+    supportsReadMemoryRequest: Optional[bool] = None
+    supportsWriteMemoryRequest: Optional[bool] = None
+    supportsDisassembleRequest: Optional[bool] = None
+    supportsCancelRequest: Optional[bool] = None
+    supportsBreakpointLocationsRequest: Optional[bool] = None
+    supportsClipboardContext: Optional[bool] = None
+    supportsSteppingGranularity: Optional[bool] = None
+    supportsInstructionBreakpoints: Optional[bool] = None
+    supportsExceptionFilterOptions: Optional[bool] = None
+    supportsSingleThreadExecutionRequests: Optional[bool] = None
+    supportsDataBreakpointBytes: Optional[bool] = None
+    breakpointModes: Optional[List[Any]] = None
+    lldb_version: Optional[str] = field(
+        metadata={"alias": "$__lldb_version"}, default=None
+    )
+
+    # lldb-dap custom capability.
+    supportsModuleSymbolsRequest: Optional[bool] = None
+
+
+@dataclass(frozen=True)
+class ErrorResponse(Response):
+    @dataclass(frozen=True)
+    class Body:
+        error: Optional[Message] = None
+
+    message: Optional[str] = None
+    body: Optional[Body] = None
+
+    def __post_init__(self):
+        assert not self.success, f"success field must be 'False' {self}"
+
+
+@dataclass(frozen=True)
+@args_protocol
+class CancelArgs:
+    requestId: Optional[int] = None
+    progressId: Optional[str] = None
+
+    command_ = "cancel"
+    response_class_ = EmptyBodyResponse
+
+
+@dataclass(frozen=True)
+class RunInTerminalResponse(Response):
+    @dataclass(frozen=True)
+    class Body:
+        processId: Optional[int] = None
+        shellProcessId: Optional[int] = None
+
+    body: Body
+
+
+@dataclass(frozen=True)
+class RunInTerminalArgs:
----------------
DrSergei wrote:

Do we need `@args_protocol`, `command_` and `response_class_`?

https://github.com/llvm/llvm-project/pull/203978
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to