Implement DAP 'terminated' event
[binutils-gdb.git] / gdb / python / lib / gdb / dap / server.py
index 7013cc3bff1410915aa96e5156f86569d1aeb6e8..db7893a387b95c39db6f7fa90c2dd2ed8008ff0b 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2022 Free Software Foundation, Inc.
+# Copyright 2022-2023 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@ from .startup import (
     log_stack,
     send_gdb_with_response,
 )
+from .typecheck import type_check
 
 
 # Map capability names to values.
@@ -100,9 +101,7 @@ class Server:
         log("WROTE: <<<" + json.dumps(obj) + ">>>")
         self.write_queue.put(obj)
 
-    # This must be run in the DAP thread, but we can't use
-    # @in_dap_thread here because the global isn't set until after
-    # this starts running.  FIXME.
+    @in_dap_thread
     def main_loop(self):
         """The main loop of the DAP server."""
         # Before looping, start the thread that writes JSON to the
@@ -152,7 +151,7 @@ class Server:
         self.done = True
 
 
-def send_event(event, body):
+def send_event(event, body=None):
     """Send an event to the DAP client.
     EVENT is the name of the event, a string.
     BODY is the body of the event, an arbitrary object."""
@@ -166,25 +165,38 @@ def request(name):
 
     def wrap(func):
         global _commands
-        _commands[name] = func
         # All requests must run in the DAP thread.
-        return in_dap_thread(func)
+        # Also type-check the calls.
+        func = in_dap_thread(type_check(func))
+        _commands[name] = func
+        return func
 
     return wrap
 
 
-def capability(name):
+def capability(name, value=True):
     """A decorator that indicates that the wrapper function implements
     the DAP capability NAME."""
 
     def wrap(func):
         global _capabilities
-        _capabilities[name] = True
+        _capabilities[name] = value
         return func
 
     return wrap
 
 
+def client_bool_capability(name):
+    """Return the value of a boolean client capability.
+
+    If the capability was not specified, or did not have boolean type,
+    False is returned."""
+    global _server
+    if name in _server.config and isinstance(_server.config[name], bool):
+        return _server.config[name]
+    return False
+
+
 @request("initialize")
 def initialize(**args):
     global _server, _capabilities
@@ -203,7 +215,7 @@ def terminate(**args):
 
 @request("disconnect")
 @capability("supportTerminateDebuggee")
-def disconnect(*, terminateDebuggee=False, **args):
+def disconnect(*, terminateDebuggee: bool = False, **args):
     if terminateDebuggee:
         terminate()
     _server.shutdown()