]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/testsuite] Add tclint-plugin.py
authorTom de Vries <tdevries@suse.de>
Thu, 11 Dec 2025 21:31:49 +0000 (22:31 +0100)
committerTom de Vries <tdevries@suse.de>
Thu, 11 Dec 2025 21:31:49 +0000 (22:31 +0100)
Tclint v0.6.2 adds the possibility to specify a dynamic plugin using:
...
$ tclint --commands tclint-plugin.py
...

Update the pre-commit tclint version to v0.6.2, and add a plugin
gdb/testsuite/tclint-plugin.py.

The new plugin informs tclint about procs like proc_with_prefix which have a
script-type parameter, making tclint check the body of proc foo:
...
proc_with_prefix foo {} {
    ...
}
...

Declaring proc_with_prefix a builtin command makes tclint issue a
redefined-builtin for the definition of proc_with_prefix.  Fix this by adding
"tclint-disable redefined-builtin" at the start of each file containing such
procs.

The plugin is not complete.  Most entries were found by grepping for something
like "proc.*body".

The hope is that eventually we get to a situation where we can drop the
plugin and instead annotate like this [1]:
...
 # tclint-args: name: any, arguments: any, body: script
 proc proc_with_prefix { name arguments body } {
     ...
 }
...

One fix in the testsuite, in test-case gdb.python/py-missing-objfile.exp.

[1] https://github.com/nmoroze/tclint/issues/121#issuecomment-3319368338

13 files changed:
.pre-commit-config.yaml
gdb/testsuite/gdb.python/py-missing-objfile.exp
gdb/testsuite/lib/ada.exp
gdb/testsuite/lib/cache.exp
gdb/testsuite/lib/completion-support.exp
gdb/testsuite/lib/debuginfod-support.exp
gdb/testsuite/lib/dwarf.exp
gdb/testsuite/lib/gdb-utils.exp
gdb/testsuite/lib/gdb.exp
gdb/testsuite/lib/mi-support.exp
gdb/testsuite/lib/rocm.exp
gdb/testsuite/lib/tuiterm.exp
gdb/testsuite/tclint-plugin.py [new file with mode: 0644]

index a78659cd17389caac2cf314db65c1594b2398345..62af6f5d2f9fc22a469be1f0979414da611468fd 100644 (file)
@@ -105,9 +105,9 @@ repos:
       pass_filenames: true
       stages: [pre-commit]
   - repo: https://github.com/nmoroze/tclint
-    rev: v0.6.1
+    rev: v0.6.2
     hooks:
     - id: tclint
-      args: [--config, gdb/tclint.toml]
+      args: [--config, gdb/tclint.toml, --commands, gdb/testsuite/tclint-plugin.py]
       types_or: [file]
       files: '^gdb/testsuite/.*\.(exp|tcl)$'
index 2f54f618cf0b5580e18f8cd5881e12d77a93cfd5..f36c59713c3342b2dd81fc2194ac4d99fc51a5c6 100644 (file)
@@ -190,8 +190,8 @@ with_test_prefix "no objfiles available" {
 
 # The following tests assume that the build-ids of binfile and libfile can be
 # found in the core file.
-require {expr $expect_build_id_in_core_file_binfile}
-require {expr $expect_build_id_in_core_file_libfile}
+require {expr {$expect_build_id_in_core_file_binfile}}
+require {expr {$expect_build_id_in_core_file_libfile}}
 
 with_test_prefix "all objfiles available" {
     # Another sanity check that GDB can find the files via the
index c6d1c463b2bccd2d443466f31e1639f87c14a3be..57b547b9af1dd76e872291758f59b84f7b8b6d15 100644 (file)
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+# tclint-disable redefined-builtin
+
 # A wrapper for foreach_with_prefix that applies suitable
 # -fgnat-encodings arguments to a command line.  SCENARIO_ARG is the
 # name of a loop variable that will hold the scenario currently being
index f5780721e0f98788e2811a2423096137382f581e..68d860732504eedf5c22972e52d35383085df849 100644 (file)
@@ -13,6 +13,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+# tclint-disable redefined-builtin
 
 # The in-memory cache.
 array set gdb_data_cache {}
index 8ddf53d6243b9ada484736f5a8385da274ff30db..d13e6cffc51ce52c43bbcf4872694db456bb3bab 100644 (file)
@@ -18,6 +18,8 @@
 # Any variable or procedure in the namespace whose name starts with
 # "_" is private to the module.  Do not use these.
 
+# tclint-disable redefined-builtin
+
 namespace eval completion {
     variable bell_re "\\\x07"
 
index ad6963e7af4779d20a7604cb82a18f1963dc1226..04033a0e47f4094f64483906673877a75e2390c0 100644 (file)
@@ -15,6 +15,8 @@
 
 # Helper functions to make it easier to write debuginfod tests.
 
+# tclint-disable redefined-builtin
+
 # Return true if the debuginfod tests should be run, otherwise, return
 # false.
 proc allow_debuginfod_tests {} {
index 708bbd448de22982f66b5afa94ee3706318dad8e..a6a31916204e0ce6468dd8a1a36d15eeef6ba9ce 100644 (file)
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+# tclint-disable redefined-builtin
+
 # Return true if the target supports DWARF-2 and uses gas.
 # For now pick a sampling of likely targets.
 proc dwarf2_support {} {
index e81f35ace79ea0876e2ce7039f15cf4ba1312918..175451dc2623ff9c643b5c81dc26bf2b767fa576 100644 (file)
@@ -15,6 +15,8 @@
 
 # Utility procedures, shared between test suite domains.
 
+# tclint-disable redefined-builtin
+
 # A helper procedure to retrieve commands to send to GDB before a program
 # is started.
 
index 8dc03231a104bef105f1a786fd6a465189d7195e..f7d9b61fec0df5eb8f6441650c6da63684501f74 100644 (file)
@@ -15,6 +15,8 @@
 
 # This file was written by Fred Fish. (fnf@cygnus.com)
 
+# tclint-disable redefined-builtin
+
 package require Tcl 8.6.2
 
 # Generic gdb subroutines that should work for any target.  If these
index b64c5862f2618732bb3205eb459dedcda21038e3..607512b7ee273e2f4e8821f1898d30862493e607 100644 (file)
@@ -19,6 +19,8 @@
 
 load_lib gdb-utils.exp
 
+# tclint-disable redefined-builtin
+
 # The variable mi_gdb_prompt is a regexp which matches the gdb mi prompt.
 # Set it if it is not already set.
 global mi_gdb_prompt
index d3f201ccf2dd2f0432b52dffd1139f8d91e28de3..67f05709cc2882adea2107db22bb7320faa43999 100644 (file)
@@ -15,6 +15,8 @@
 #
 # Support library for testing ROCm (AMD GPU) GDB features.
 
+# tclint-disable redefined-builtin
+
 # ROCM_PATH is used by hipcc as well.
 if {[info exists ::env(ROCM_PATH)]} {
     set rocm_path $::env(ROCM_PATH)
index 68fd6777b7c86474843bfb26f1d611385592821d..86e52b9a788637cf5e0e7aac26feba7027ceb194 100644 (file)
@@ -15,6 +15,8 @@
 
 # An ANSI terminal emulator for expect.
 
+# tclint-disable redefined-builtin
+
 namespace eval Term {
     # Size of the terminal.
     variable _rows
diff --git a/gdb/testsuite/tclint-plugin.py b/gdb/testsuite/tclint-plugin.py
new file mode 100644 (file)
index 0000000..24a813a
--- /dev/null
@@ -0,0 +1,199 @@
+from tclint.commands.checks import (
+    CommandArgError,
+)
+from tclint.commands.schema import commands_schema
+
+
+def _script_args(name, n, script_args, args, parser):
+    if len(args) != n:
+        raise CommandArgError(
+            f"wrong # of args to {name}: got {len(args)}, expected {n}"
+        )
+
+    res = []
+    arg_n = 0
+    for arg in args:
+        if arg_n in script_args:
+            res.append(parser.parse_script(arg))
+        else:
+            res.append(arg)
+        arg_n += 1
+    return res
+
+
+def _script_last_arg(name, n, args, parser):
+    return _script_args(name, n, [n - 1], args, parser)
+
+
+def _cond_wrap(args, parser):
+    return _script_last_arg("cond_wrap", 3, args, parser)
+
+
+def _foreach_gnat_encoding(args, parser):
+    return _script_last_arg("foreach_gnat_encoding", 4, args, parser)
+
+
+def _foreach_location_functions(args, parser):
+    return _script_args("foreach_location_functions", 4, [2, 3], args, parser)
+
+
+def _foreach_location_labels(args, parser):
+    return _script_args("foreach_location_labels", 5, [3, 4], args, parser)
+
+
+def _foreach_mi_ui_mode(args, parser):
+    return _script_last_arg("foreach_mi_ui_mode", 2, args, parser)
+
+
+def _foreach_with_prefix(args, parser):
+    return _script_last_arg("foreach_with_prefix", 3, args, parser)
+
+
+def _gdb_caching_proc(args, parser):
+    return _script_last_arg("gdb_caching_proc", 3, args, parser)
+
+
+def _proc_with_prefix(args, parser):
+    return _script_last_arg("proc_with_prefix", 3, args, parser)
+
+
+def _require(args, parser):
+    res = []
+    for arg in args:
+        res.append(parser.parse_script(arg))
+    return res
+
+
+def _save_vars(args, parser):
+    return _script_last_arg("save_vars", 2, args, parser)
+
+
+def _save_target_board_info(args, parser):
+    return _script_last_arg("save_target_board_info", 2, args, parser)
+
+
+def _with_debuginfod_env(args, parser):
+    return _script_last_arg("with_debuginfod_env", 2, args, parser)
+
+
+def _with_shared_gdb(args, parser):
+    return _script_last_arg("with_shared_gdb", 1, args, parser)
+
+
+def _with_test_prefix(args, parser):
+    return _script_last_arg("with_test_prefix", 2, args, parser)
+
+
+def _with_cwd(args, parser):
+    return _script_last_arg("with_cwd", 2, args, parser)
+
+
+def _with_gdb_cwd(args, parser):
+    return _script_last_arg("with_gdb_cwd", 2, args, parser)
+
+
+def _with_gdb_prompt(args, parser):
+    return _script_last_arg("with_gdb_prompt", 2, args, parser)
+
+
+def _with_target_charset(args, parser):
+    return _script_last_arg("with_target_charset", 2, args, parser)
+
+
+def _with_max_value_size(args, parser):
+    return _script_last_arg("with_max_value_size", 2, args, parser)
+
+
+def _with_spawn_id(args, parser):
+    return _script_last_arg("with_spawn_id", 2, args, parser)
+
+
+def _with_timeout_factor(args, parser):
+    return _script_last_arg("with_timeout_factor", 2, args, parser)
+
+
+def _with_read1_timeout_factor(args, parser):
+    return _script_last_arg("with_read1_timeout_factor", 2, args, parser)
+
+
+def _with_multilib_flags_filtered(args, parser):
+    return _script_last_arg("with_multilib_flags_filtered", 2, args, parser)
+
+
+def _with_PIE_multilib_flags_filtered(args, parser):
+    return _script_last_arg("with_PIE_multilib_flags_filtered", 1, args, parser)
+
+
+def _with_set(args, parser):
+    return _script_last_arg("with_set", 3, args, parser)
+
+
+def _with_complaints(args, parser):
+    return _script_last_arg("with_complaints", 2, args, parser)
+
+
+def _with_override(args, parser):
+    return _script_last_arg("with_override", 3, args, parser)
+
+
+def _with_ansi_styling_terminal(args, parser):
+    return _script_last_arg("with_ansi_styling_terminal", 1, args, parser)
+
+
+def _with_lock(args, parser):
+    return _script_last_arg("with_lock", 2, args, parser)
+
+
+def _with_rocm_gpu_lock(args, parser):
+    return _script_last_arg("with_rocm_gpu_lock", 1, args, parser)
+
+
+def _ns_term_log_cur(args, parser):
+    return _script_last_arg("Term::log_cur", 2, args, parser)
+
+
+def _ns_term_with_term(args, parser):
+    return _script_last_arg("Term::with_term", 2, args, parser)
+
+
+def _ns_term_with_tuiterm(args, parser):
+    return _script_last_arg("Term::with_tuiterm", 3, args, parser)
+
+
+commands = commands_schema(
+    {
+        "cond_wrap": _cond_wrap,
+        "foreach_gnat_encoding": _foreach_gnat_encoding,
+        "foreach_location_functions": _foreach_location_functions,
+        "foreach_location_labels": _foreach_location_labels,
+        "foreach_mi_ui_mode": _foreach_mi_ui_mode,
+        "foreach_with_prefix": _foreach_with_prefix,
+        "gdb_caching_proc": _gdb_caching_proc,
+        "proc_with_prefix": _proc_with_prefix,
+        "require": _require,
+        "save_vars": _save_vars,
+        "save_target_board_info": _save_target_board_info,
+        "with_debuginfod_env": _with_debuginfod_env,
+        "with_shared_gdb": _with_shared_gdb,
+        "with_test_prefix": _with_test_prefix,
+        "with_cwd": _with_cwd,
+        "with_gdb_cwd": _with_gdb_cwd,
+        "with_gdb_prompt": _with_gdb_prompt,
+        "with_target_charset": _with_target_charset,
+        "with_max_value_size": _with_max_value_size,
+        "with_spawn_id": _with_spawn_id,
+        "with_timeout_factor": _with_timeout_factor,
+        "with_read1_timeout_factor": _with_read1_timeout_factor,
+        "with_multilib_flags_filtered": _with_multilib_flags_filtered,
+        "with_PIE_multilib_flags_filtered": _with_PIE_multilib_flags_filtered,
+        "with_set": _with_set,
+        "with_complaints": _with_complaints,
+        "with_override": _with_override,
+        "with_ansi_styling_terminal": _with_ansi_styling_terminal,
+        "with_lock": _with_lock,
+        "with_rocm_gpu_lock": _with_rocm_gpu_lock,
+        "Term::_log_cur": _ns_term_log_cur,
+        "Term::with_term": _ns_term_with_term,
+        "Term::with_tuiterm": _ns_term_with_tuiterm,
+    }
+)