From f35baff348a2260616dc04721c31726d88e24851 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 8 Sep 2023 13:18:17 -0600 Subject: [PATCH] Add two new pretty-printer methods This adds two new pretty-printer methods, to support random access to children. The methods are implemented for the no-op array printer, and DAP is updated to use this. Reviewed-By: Eli Zaretskii --- gdb/doc/python.texi | 16 ++++++++++++++++ gdb/python/lib/gdb/dap/varref.py | 22 +++++++++++++++------- gdb/python/lib/gdb/printing.py | 16 ++++++++++++---- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 2aaf10191e1..5e88fd09e48 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -1828,6 +1828,22 @@ are peformed in this method and nothing is printed. If the result is not one of these types, an exception is raised. @end defun +@defun pretty_printer.num_children () +This is not a basic method, so @value{GDBN} will only ever call it for +objects derived from @code{gdb.ValuePrinter}. + +If available, this method should return the number of children. +@code{None} may be returned if the number can't readily be computed. +@end defun + +@defun pretty_printer.child (n) +This is not a basic method, so @value{GDBN} will only ever call it for +objects derived from @code{gdb.ValuePrinter}. + +If available, this method should return the child value indicated by +@var{n}. Indices start at zero. +@end defun + @value{GDBN} provides a function which can be used to look up the default pretty-printer for a @code{gdb.Value}: diff --git a/gdb/python/lib/gdb/dap/varref.py b/gdb/python/lib/gdb/dap/varref.py index c1e5ba8686d..764a8291027 100644 --- a/gdb/python/lib/gdb/dap/varref.py +++ b/gdb/python/lib/gdb/dap/varref.py @@ -151,9 +151,9 @@ class VariableReference(BaseReference): # This discards all laziness. This could be improved # slightly by lazily evaluating children, but because this # code also generally needs to know the number of - # children, it probably wouldn't help much. A real fix - # would require an update to gdb's pretty-printer protocol - # (though of course that is probably also inadvisable). + # children, it probably wouldn't help much. Note that + # this is only needed with legacy (non-ValuePrinter) + # printers. self.child_cache = list(self.printer.children()) return self.child_cache @@ -161,9 +161,12 @@ class VariableReference(BaseReference): if self.count is None: return None if self.count == -1: - if hasattr(self.printer, "num_children"): - num_children = self.printer.num_children - else: + num_children = None + if isinstance(self.printer, gdb.ValuePrinter) and hasattr( + self.printer, "num_children" + ): + num_children = self.printer.num_children() + if num_children is None: num_children = len(self.cache_children()) self.count = num_children return self.count @@ -193,7 +196,12 @@ class VariableReference(BaseReference): @in_gdb_thread def fetch_one_child(self, idx): - return self.cache_children()[idx] + if isinstance(self.printer, gdb.ValuePrinter) and hasattr( + self.printer, "child" + ): + return self.printer.child(idx) + else: + return self.cache_children()[idx] @in_gdb_thread diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py index 21afa4d93b1..0bbe2cb8ae7 100644 --- a/gdb/python/lib/gdb/printing.py +++ b/gdb/python/lib/gdb/printing.py @@ -285,11 +285,16 @@ class NoOpPointerReferencePrinter(gdb.ValuePrinter): def __init__(self, value): self.__value = value - self.num_children = 1 def to_string(self): return self.__value.format_string(deref_refs=False) + def num_children(self): + return 1 + + def child(self, i): + return "value", self.__value.referenced_value() + def children(self): yield "value", self.__value.referenced_value() @@ -313,9 +318,6 @@ class NoOpArrayPrinter(gdb.ValuePrinter): e_values = itertools.takewhile(lambda x: x.enumval <= high, e_values) low = 0 high = len(list(e_values)) - 1 - # This is a convenience to the DAP code and perhaps other - # users. - self.num_children = high - low + 1 self.__low = low self.__high = high @@ -325,6 +327,12 @@ class NoOpArrayPrinter(gdb.ValuePrinter): def display_hint(self): return "array" + def num_children(self): + return self.__high - self.__low + 1 + + def child(self, i): + return (self.__low + i, self.__value[self.__low + i]) + def children(self): for i in range(self.__low, self.__high + 1): yield (i, self.__value[i]) -- 2.30.2