Subject: bug#59853: 30.0.50; tree-sitter modes have unexpected beginning-of-defun behavior

From: Yuan Fu <[email-masked]>
Date: Wed, 7 Dec 2022 11:34:05 -0800

Theodor Thornhill <[email-masked]> writes:

> Brian Leung <[email-masked]> writes:
>
>> Theodor Thornhill <[email-masked]> writes:
>>
>>> Not sure I can reproduce this.
>>
>> Sorry, I made a mistake in my description. I additionally noticed 
>> additional odd results in java-ts-mode. Let me try again:
>>
>>> p[u]blic abstract class Class {
>>>     public static interface Interface {
>>>         void someMethod();
>>> [*]
>>>         void otherMethod();
>>>     [}]
>>> }
>
> Right - thanks!  Now I understand what you describe.  I'll try to answer
> them case by case.
>
>>
>> 1. When point is at the "u" in "public", narrow-to-defun cuts off 
>> "pu" and moves point to "b".
>
> Yes, this definitely looks like a bug.  This is probably because the
> whole 'public' keyword maps to the declaration, and we don't move to the
> actual beginning.  I can look into this.
>
>> 2. When point is anywhere in the first line of the class 
>> declaration, mark-defun highlights "void otherMethod()", instead 
>> of the entire class declaration.
>
> Yeah, I think I've fixed this in a patch I just submitted.
>
>> 3a. When point is at the [*] in between someMethod and 
>> otherMethod, narrow-to-defun captures "void otherMethod()". I feel 
>> that since the methods inside the interface declaration have no 
>> bodies, it makes more sense to capture the entire interface 
>> definition if point is at [*].
>
> Maybe, but I don't believe this is wrong either.
>
>> 3b. Arguably, even if point were on the method declarations, we 
>> might still want to (as plain java-mode does) capture the entire 
>> interface definition, since body-less method declarations don't 
>> feel especially defun-like.
>
> Maybe.  Can you try applying the below patch and see if this changes
> anything for you?
>
>> 4. When point is on the closing bracket of the interface 
>> definition, narrow-to-defun captures
>>
>>>         void otherMethod();
>>>     }
>>> }
>>
>> which looks quite unusual to me.
>
> Yes, I agree with this one.  My guess is that this is the same as number
> one.
>
> What do you think?
>
> Theo

There’s a discussion semi-related to this on emacs-devel, where Alan
mentioned this:

In CC Mode, it has been configurable via the user option c-defun-tactic
for somewhere between ten and fifteen years.  When c-defun-tactic is t,
C-M-a/e go to the start/end of the top level defuns.  When it is the
symbol go-outward, C-M-a/e move to the next start/end of defun, if any,
at the current level of class/namespace nesting, and move outwards to
the next level of class/namespace nesting when a class/namespace boundary
is reached.

If we add this option to tree-sitter, user could decide what bahavior
they want. I’m planning to work on that. Though there is already
something that can more-or-less do this: treesit-defun-prefer-top-level.

Yuan