Subject: bug#66845: 29.1; cmake-ts-mode indentation broken

From: Yuan Fu <[email-masked]>
Date: Tue, 7 Nov 2023 00:25:18 -0800

> On Oct 31, 2023, at 7:45 PM, Randy Taylor <[email-masked]> wrote:
> 
> On Tuesday, October 31st, 2023 at 07:35, Juan Palacios <[email-masked]> wrote:
>> Using cmake grammar from https://github.com/uyha/tree-sitter-cmake
>> 
>> Reproduction:
>> 1. emacs -q
>> 2. C-x C-f test.cmake
>> 3. M-x cmake-ts-mode
>> 4. Insert the following text:
>> if(TRUE)
>> message("indent")
>> endif()
>> 5. Move the point to the beginning of the second line.
>> 6. TAB
>> 7. Notice that no indentation is performed.
>> 
>> treesit-simple-indent-rules local value:
>> ((cmake
>> ((node-is ")")
>> parent-bol 0)
>> ((node-is "else_command")
>> parent-bol 0)
>> ((node-is "elseif_command")
>> parent-bol 0)
>> ((node-is "endforeach_command")
>> parent-bol 0)
>> ((node-is "endfunction_command")
>> parent-bol 0)
>> ((node-is "endif_command")
>> parent-bol 0)
>> ((parent-is "foreach_loop")
>> parent-bol cmake-ts-mode-indent-offset)
>> ((parent-is "function_def")
>> parent-bol cmake-ts-mode-indent-offset)
>> ((parent-is "if_condition")
>> parent-bol cmake-ts-mode-indent-offset)
>> ((parent-is "normal_command")
>> parent-bol cmake-ts-mode-indent-offset)))
>> 
>> treesit-explore-mode shows:
>> (if_condition
>> (if_command (if) (
>> (argument_list
>> (argument (unquoted_argument)))
>> ))
>> (body
>> (normal_command (identifier) (
>> (argument_list
>> (argument
>> (quoted_argument " (quoted_element) ")))
>> )))
>> (endif_command (endif) ( )))
>> 
> 
> I've attached a patch fixing this while retaining compatibility with
> older grammars. 2 new versions of the grammar, v0.3.0 and v0.4.0
> (and anything beyond for now) wrap things in new nodes.
> 
> Yuan,
> It's been awhile since I've touched any tree-sitter stuff so I'm
> probably missing something obvious, but it seems to me like the
> function I've added in the patch
> (cmake-ts-mode--argument-list-body-offset) is working around a bug
> somewhere? I'm not sure why the start of line_comment is considered
> parent-bol for indentation.
> 
> For example, with this test cmake file: (test.cmake)
> if(TRUE)
>  # Comment.
>  message("indent")
> endif()
> 
> We get:
> (source_file
> (if_condition
>  (if_command (if) (
>   (argument_list
>    (argument (unquoted_argument)))
>   ))
>  (body (line_comment)
>   (normal_command (identifier) (
>    (argument_list
>     (argument
>      (quoted_argument " (quoted_element) ")))
>    )))
>  (endif_command (endif) ( ))))
> 
> With cmake-ts-mode--argument-list-body-offset always returning
> cmake-ts-mode-indent-offset (which is what I would expect), the
> `parent-is "body"` rule will cause this indentation:
> if(TRUE)
>  # Comment.
>    message("indent")
> endif()
> 
> Am I being silly or is there indeed something odd going on?<0001-Fix-cmake-ts-mode-indentation-Bug-66845.patch>

IMO it makes more sense to use prev-sibling:

,@(ignore-errors
         (treesit-query-capture 'cmake '((body) @capture))
         `(((parent-is "body") prev-sibling 0)))

This would allow users to manually adjust the indentation of a line and have the rest of the body follow that.

As for why parent-bol returns the BOL of the comment line, that’s expected: The parent is body, and body starts at the comment, so of course the beginning of the parent line is the beginning of the comment line. In the image below, the highlighted portion marks the body node.

Some tree-sitter grammar would mark the beginning of body at the end of if(TRUE), but what tree-sitter-cmake does here is equally valid.

Yuan