[2/2] Add two new pretty-printer methods

Message ID 20230911-pp-v2-v1-2-c4e0d40c8b63@adacore.com
State New
Headers
Series Add pretty-printer base class and new methods |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 fail Testing failed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Tom Tromey Sept. 11, 2023, 5:28 p.m. UTC
  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.
---
 gdb/doc/python.texi              | 16 ++++++++++++++++
 gdb/python/lib/gdb/dap/varref.py | 22 +++++++++++++++-------
 gdb/python/lib/gdb/printing.py   |  9 ++++++---
 3 files changed, 37 insertions(+), 10 deletions(-)
  

Comments

Eli Zaretskii Sept. 11, 2023, 7 p.m. UTC | #1
> Date: Mon, 11 Sep 2023 11:28:26 -0600
> From: Tom Tromey via Gdb-patches <gdb-patches@sourceware.org>
> 
> 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.
> ---
>  gdb/doc/python.texi              | 16 ++++++++++++++++
>  gdb/python/lib/gdb/dap/varref.py | 22 +++++++++++++++-------
>  gdb/python/lib/gdb/printing.py   |  9 ++++++---
>  3 files changed, 37 insertions(+), 10 deletions(-)
> 
> diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
> index d09f5e03997..79438baf477 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}:

The python.texi part is OK, thanks.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
  

Patch

diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index d09f5e03997..79438baf477 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..768d768c7b3 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 80851590134..4982abc3f77 100644
--- a/gdb/python/lib/gdb/printing.py
+++ b/gdb/python/lib/gdb/printing.py
@@ -299,9 +299,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
 
@@ -311,6 +308,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])