Subject: bug#60407: closed (Re: bug#60407: [PATCH] Update go-ts-mode to use Imenu facility)

From: [email-masked] (GNU bug Tracking System)
Date: Mon, 09 Jan 2023 00:36:08 +0000

Your bug report

#60407: [PATCH] Update go-ts-mode to use Imenu facility

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
60407: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=60407
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#60407: [PATCH] Update go-ts-mode to use Imenu facility
From: Yuan Fu <[email-masked]>
To: [email-masked]
Cc: [email-masked]
Date: Sun, 8 Jan 2023 16:35:36 -0800
List-Id: <debbugs-submit.debbugs.gnu.org>

Evgeni Kolev <[email-masked]> writes:

> Hi Yuan, sure, the .patch is attached.

Thanks. I applied the patch.

Yuan

Subject: [PATCH] Update go-ts-mode to use Imenu facility
From: Evgeni Kolev <[email-masked]>
To: [email-masked]
Date: Thu, 29 Dec 2022 18:05:49 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

This patch updates go-ts-mode to use Imenu facility added in
https://git.savannah.gnu.org/cgit/emacs.git/commit/?h=emacs-29&id=b39dc7ab27a696a8607ab859aeff3c71509231f5

The Imenu items are extended to support "Method", in addition to
"Function" and "Type".

The current Imenu approach uses "type_spec" to identify "Type" which
acts as a catch-all for many Go constructs, for example struct and
interface definitions. This catch-all approach is not optimal because
structs and interfaces are put in the same "Type" bucket. In a
follow-up patch I'll try to change the approach and have separate
"Interface" and "Struct" types.

The patch is below.

commit 71ff7b21fe92167313bd1761b68b6e6fd879b09f
Author: Evgeni Kolev <[email-masked]>
Date:   Thu Dec 29 17:49:40 2022 +0200

    Update go-ts-mode to use Imenu facility

    go-ts-mode is updated to use the Imenu facility added in commit
    b39dc7ab27a696a8607ab859aeff3c71509231f5.

    The Imenu items are extended to support "Method", in addition to
    "Function" and "Type".

    * lisp/progmodes/go-ts-mode.el (go-ts-mode--imenu-1) (go-ts-mode--imenu):
    Remove functions.
    (go-ts-mode--defun-name): New function.

diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index 124d9b044a2..c6c1c61d9f4 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -173,44 +173,6 @@ go-ts-mode--font-lock-settings
    '((ERROR) @font-lock-warning-face))
   "Tree-sitter font-lock settings for `go-ts-mode'.")

-(defun go-ts-mode--imenu ()
-  "Return Imenu alist for the current buffer."
-  (let* ((node (treesit-buffer-root-node))
-         (func-tree (treesit-induce-sparse-tree
-                     node "function_declaration" nil 1000))
-         (type-tree (treesit-induce-sparse-tree
-                     node "type_spec" nil 1000))
-         (func-index (go-ts-mode--imenu-1 func-tree))
-         (type-index (go-ts-mode--imenu-1 type-tree)))
-    (append
-     (when func-index `(("Function" . ,func-index)))
-     (when type-index `(("Type" . ,type-index))))))
-
-(defun go-ts-mode--imenu-1 (node)
-  "Helper for `go-ts-mode--imenu'.
-Find string representation for NODE and set marker, then recurse
-the subtrees."
-  (let* ((ts-node (car node))
-         (children (cdr node))
-         (subtrees (mapcan #'go-ts-mode--imenu-1
-                           children))
-         (name (when ts-node
-                 (treesit-node-text
-                  (pcase (treesit-node-type ts-node)
-                    ("function_declaration"
-                     (treesit-node-child-by-field-name ts-node "name"))
-                    ("type_spec"
-                     (treesit-node-child-by-field-name ts-node "name"))))))
-         (marker (when ts-node
-                   (set-marker (make-marker)
-                               (treesit-node-start ts-node)))))
-    (cond
-     ((or (null ts-node) (null name)) subtrees)
-     (subtrees
-      `((,name ,(cons name marker) ,@subtrees)))
-     (t
-      `((,name . ,marker))))))
-
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))

@@ -228,9 +190,18 @@ go-ts-mode
     (setq-local comment-end "")
     (setq-local comment-start-skip (rx "//" (* (syntax whitespace))))

+    ;; Navigation.
+    (setq-local treesit-defun-type-regexp
+                (regexp-opt '("method_declaration"
+                              "function_declaration"
+                              "type_spec")))
+    (setq-local treesit-defun-name-function #'go-ts-mode--defun-name)
+
     ;; Imenu.
-    (setq-local imenu-create-index-function #'go-ts-mode--imenu)
-    (setq-local which-func-functions nil)
+    (setq-local treesit-simple-imenu-settings
+                `(("Function" "\\`function_declaration\\'" nil nil)
+                  ("Type" "\\`type_spec\\'" nil nil)
+                  ("Method" "\\`method_declaration\\'" nil nil)))

     ;; Indent.
     (setq-local indent-tabs-mode t
@@ -247,6 +218,18 @@ go-ts-mode

     (treesit-major-mode-setup)))

+(defun go-ts-mode--defun-name (node)
+  "Return the defun name of NODE.
+Return nil if there is no name or if NODE is not a defun node."
+  (pcase (treesit-node-type node)
+    ((or "function_declaration"
+         "method_declaration"
+         "type_spec")
+     (treesit-node-text
+      (treesit-node-child-by-field-name
+       node "name")
+      t))))
+
 ;; go.mod support.

 (defvar go-mod-ts-mode--syntax-table