diff options
| author | Yuan Fu | 2026-04-04 22:33:19 -0700 |
|---|---|---|
| committer | Yuan Fu | 2026-04-04 22:35:35 -0700 |
| commit | 45d7678ca3717ebcb422145e5705de49df881010 (patch) | |
| tree | 6300b6aaa68787ef443b57d383c2f035d2b9e1b9 /src | |
| parent | ae1ac739b799608cca0ec9f0e78f2b852078bd57 (diff) | |
| download | emacs-45d7678ca3717ebcb422145e5705de49df881010.tar.gz emacs-45d7678ca3717ebcb422145e5705de49df881010.zip | |
Fix treesit-query-capture's NODE-ONLY param
Before the fix, if user uses the NODE-ONLY option, we don't keep
the capture names in the results, then predicates won't work
because they can't reference capture names.
* src/treesit.c (query_capture_remove_capture_name): New
function.
(Ftreesit_query_capture): Use the new function to remove capture
names AFTER running the predicate.
* test/src/treesit-tests.el:
(treesit-query-node-only-and-grouped): New test.
Diffstat (limited to 'src')
| -rw-r--r-- | src/treesit.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/src/treesit.c b/src/treesit.c index bec37067b50..c08691af3d8 100644 --- a/src/treesit.c +++ b/src/treesit.c | |||
| @@ -3977,6 +3977,22 @@ treesit_initialize_query (Lisp_Object query, const TSLanguage *lang, | |||
| 3977 | } | 3977 | } |
| 3978 | } | 3978 | } |
| 3979 | 3979 | ||
| 3980 | /* Go over a list from START to END (until the element eq to END), | ||
| 3981 | replace (capture-name . node) with just node. */ | ||
| 3982 | static void query_capture_remove_capture_name (Lisp_Object start, | ||
| 3983 | Lisp_Object end) | ||
| 3984 | { | ||
| 3985 | Lisp_Object tail = start; | ||
| 3986 | FOR_EACH_TAIL (tail) | ||
| 3987 | { | ||
| 3988 | Lisp_Object cell = CAR (tail); | ||
| 3989 | CHECK_CONS (cell); | ||
| 3990 | XSETCAR (tail, CDR (cell)); | ||
| 3991 | |||
| 3992 | if (EQ (CDR (tail), end)) return; | ||
| 3993 | } | ||
| 3994 | } | ||
| 3995 | |||
| 3980 | DEFUN ("treesit-query-capture", | 3996 | DEFUN ("treesit-query-capture", |
| 3981 | Ftreesit_query_capture, | 3997 | Ftreesit_query_capture, |
| 3982 | Streesit_query_capture, 2, 6, 0, | 3998 | Streesit_query_capture, 2, 6, 0, |
| @@ -4122,18 +4138,12 @@ the query. */) | |||
| 4122 | TSQueryCapture capture = captures[idx]; | 4138 | TSQueryCapture capture = captures[idx]; |
| 4123 | Lisp_Object captured_node = make_treesit_node (lisp_parser, | 4139 | Lisp_Object captured_node = make_treesit_node (lisp_parser, |
| 4124 | capture.node); | 4140 | capture.node); |
| 4125 | 4141 | const char *capture_name | |
| 4126 | Lisp_Object cap; | 4142 | = ts_query_capture_name_for_id (treesit_query, capture.index, |
| 4127 | if (NILP (node_only)) | 4143 | &capture_name_len); |
| 4128 | { | 4144 | Lisp_Object cap |
| 4129 | const char *capture_name | 4145 | = Fcons (intern_c_string_1 (capture_name, capture_name_len), |
| 4130 | = ts_query_capture_name_for_id (treesit_query, capture.index, | 4146 | captured_node); |
| 4131 | &capture_name_len); | ||
| 4132 | cap = Fcons (intern_c_string_1 (capture_name, capture_name_len), | ||
| 4133 | captured_node); | ||
| 4134 | } | ||
| 4135 | else | ||
| 4136 | cap = captured_node; | ||
| 4137 | 4147 | ||
| 4138 | if (NILP (grouped)) | 4148 | if (NILP (grouped)) |
| 4139 | result = Fcons (cap, result); /* Mode 1. */ | 4149 | result = Fcons (cap, result); /* Mode 1. */ |
| @@ -4166,12 +4176,24 @@ the query. */) | |||
| 4166 | if (!NILP (predicate_signal_data)) | 4176 | if (!NILP (predicate_signal_data)) |
| 4167 | break; | 4177 | break; |
| 4168 | 4178 | ||
| 4169 | /* Mode 1: Predicates didn't pass, roll back. */ | 4179 | /* Mode 1: Roll back if predicate didn't pass, don't roll back if |
| 4170 | if (!match && NILP (grouped)) | 4180 | predicate passed. */ |
| 4171 | result = prev_result; | 4181 | if (NILP (grouped)) |
| 4172 | /* Mode 2: Predicates pass, add this match group. */ | 4182 | { |
| 4183 | if (!match) | ||
| 4184 | result = prev_result; | ||
| 4185 | else if (!NILP (node_only)) | ||
| 4186 | query_capture_remove_capture_name (result, prev_result); | ||
| 4187 | } | ||
| 4188 | /* Mode 2: Add this match group if predicate pass, don't add this | ||
| 4189 | group if predicate didn't pass. */ | ||
| 4173 | if (match && !NILP (grouped)) | 4190 | if (match && !NILP (grouped)) |
| 4174 | result = Fcons (Fnreverse (match_group), result); | 4191 | { |
| 4192 | match_group = Fnreverse (match_group); | ||
| 4193 | if (!NILP (node_only)) | ||
| 4194 | query_capture_remove_capture_name (match_group, Qnil); | ||
| 4195 | result = Fcons (match_group, result); | ||
| 4196 | } | ||
| 4175 | } | 4197 | } |
| 4176 | 4198 | ||
| 4177 | /* Final clean up. */ | 4199 | /* Final clean up. */ |