Subject: Re: bug#61502: 29.0.60; c-ts-mode auto-indent not working

From: Eli Zaretskii <[email-masked]>
Date: Tue, 14 Feb 2023 22:02:02 +0200

> From: Theodor Thornhill <[email-masked]>
> Cc: [email-masked]
> Date: Tue, 14 Feb 2023 20:41:04 +0100
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> > Keep typing whatever code you wan "int main" to include, and it will
> > auto-indent soon enough.
> 
> Yeah, but.

My point is that what we are used to from CC mode does not necessarily
have to work the same way with tree-sitter based modes.  As long as
the indentation fixes itself soon enough, we are still fine, I think.

> int
> main
> {
>   for (;;)
>     {|
> }
> ```
> 
> If you press RET if point at | you'll see we indent immediately, even
> though there is no closing bracket.  This is because of how
> treesit-indent defaults to treesit-node-on when there is no node at
> point.  So in the example without the for loop the parent is then set to
> whatever treesit-node-on returns, which in this case is the root
> node. That means that the rule for translation_unit is selected, which
> is:
> 
>          `(((parent-is "translation_unit") point-min 0)
> 
> However, what's interesting here is that treesit-indent selects an
> "unexisting" node as the "smallest-node".  Specifically that is:
> 
>          #<treesit-node "}" in 13-13>
> 
> This node in turn will return "compound_statement" if you look for its
> parent.  It seems some parsers detects these nodes, so maybe we should
> add some handling for that?  Some "block-closers" code in
> treesit-node-on, so that treesit-node-on doesn't default to the root
> node, but rather the compound_statement?

AFAIU, you are talking about hitting RET in the following situation
(where "|" stands for point):

int main ()
{|
}

However, the OP presented a slightly different situation:

int main ()
{|

That is, without the closing brace.  In that case, there's no "}" in
the source.  Are you saying that the tree-sitter's parser "invents"
such a node?

And why does treesit-indent select that "unexisting" node in the first
place?

> I'm not sure this explanation was easy to follow at all, but I'll add a
> hack in a diff to make the point hopefully a little clearer.
> 
> What do you think?

How well did you test that?  Does it fix similar problems with struct
definition at top-level?  Are there any regressions elsewhere in the
indentation?

There are also other similar cases, but with code on deeper levels.
Try this, for example (where "|" again stands for point):

int
main
{
  for (;;)|
}

Now press RET and observe the result:

int
main
{
  for (;;)
  |
}

instead of the expected

int
main
{
  for (;;)
    |
}

Why?

(Of course, as soon as you type ";", the code is automatically
reindented to yield the correct indentation.  Which was my point.)