diff options
author | Tom Tromey <tromey@adacore.com> | 2023-02-13 09:56:58 -0700 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2023-03-14 09:09:23 -0600 |
commit | 8900a92ead1c4f94216b95eb5f76aafdf74a94a0 (patch) | |
tree | 439376c5c7cafcab586273c2c7d0e22edd8427b1 /gdb/python/lib/gdb/dap/scopes.py | |
parent | d0aa28e155baf16ec37afdf0193c3d58816c1927 (diff) | |
download | binutils-gdb-8900a92ead1c4f94216b95eb5f76aafdf74a94a0.tar.gz |
Implement DAP variables, scopes, and evaluate requests
The DAP code already claimed to implement "scopes" and "evaluate", but
this wasn't done completely correctly. This patch implements these
and also implements the "variables" request.
After this patch, variables and scopes correctly report their
sub-structure. This also interfaces with the gdb pretty-printer API,
so the output of pretty-printers is available.
Diffstat (limited to 'gdb/python/lib/gdb/dap/scopes.py')
-rw-r--r-- | gdb/python/lib/gdb/dap/scopes.py | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/gdb/python/lib/gdb/dap/scopes.py b/gdb/python/lib/gdb/dap/scopes.py index 490fa9cf098..9ab454aa57b 100644 --- a/gdb/python/lib/gdb/dap/scopes.py +++ b/gdb/python/lib/gdb/dap/scopes.py @@ -18,6 +18,7 @@ import gdb from .frames import frame_for_id from .startup import send_gdb_with_response, in_gdb_thread from .server import request +from .varref import BaseReference # Helper function to return a frame's block without error. @@ -29,17 +30,53 @@ def _safe_block(frame): return None -# Helper function to return a list of variables of block, up to the -# enclosing function. +# Helper function to return two lists of variables of block, up to the +# enclosing function. The result is of the form (ARGS, LOCALS), where +# each element is itself a list. @in_gdb_thread def _block_vars(block): - result = [] + args = [] + locs = [] while True: - result += list(block) + for var in block: + if var.is_argument: + args.append(var) + else: + locs.append(var) if block.function is not None: break block = block.superblock - return result + return (args, locs) + + +class ScopeReference(BaseReference): + def __init__(self, name, frame, var_list): + super().__init__(name) + self.frame = frame + self.func = frame.function() + self.var_list = var_list + + def to_object(self): + result = super().to_object() + # How would we know? + result["expensive"] = False + result["namedVariables"] = len(self.var_list) + if self.func is not None: + result["line"] = self.func.line + # FIXME construct a Source object + return result + + def child_count(self): + return len(self.var_list) + + @in_gdb_thread + def fetch_one_child(self, idx): + sym = self.var_list[idx] + if sym.needs_frame: + val = sym.value(self.frame) + else: + val = sym.value() + return (sym.print_name, val) # Helper function to create a DAP scopes for a given frame ID. @@ -49,14 +86,12 @@ def _get_scope(id): block = _safe_block(frame) scopes = [] if block is not None: - new_scope = { - # FIXME - "name": "Locals", - "expensive": False, - "namedVariables": len(_block_vars(block)), - } - scopes.append(new_scope) - return scopes + (args, locs) = _block_vars(block) + if args: + scopes.append(ScopeReference("Arguments", frame, args)) + if locs: + scopes.append(ScopeReference("Locals", frame, locs)) + return [x.to_object() for x in scopes] @request("scopes") |