From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Randy Taylor Newsgroups: gmane.emacs.bugs Subject: bug#60407: [PATCH] Update go-ts-mode to use Imenu facility Date: Tue, 03 Jan 2023 14:30:59 +0000 Message-ID: References: <83y1qm39o3.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="30885"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Eli Zaretskii , Yuan Fu , 60407@debbugs.gnu.org To: Evgeni Kolev Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Jan 03 15:32:49 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pCiLQ-0007lW-HL for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 03 Jan 2023 15:32:48 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pCiLG-0001Sq-73; Tue, 03 Jan 2023 09:32:39 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pCiKr-0001KK-At for bug-gnu-emacs@gnu.org; Tue, 03 Jan 2023 09:32:16 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pCiKg-0000Oq-O6 for bug-gnu-emacs@gnu.org; Tue, 03 Jan 2023 09:32:06 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pCiKg-0007FY-Ho for bug-gnu-emacs@gnu.org; Tue, 03 Jan 2023 09:32:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Randy Taylor Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 03 Jan 2023 14:32:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 60407 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 60407-submit@debbugs.gnu.org id=B60407.167275628427817 (code B ref 60407); Tue, 03 Jan 2023 14:32:02 +0000 Original-Received: (at 60407) by debbugs.gnu.org; 3 Jan 2023 14:31:24 +0000 Original-Received: from localhost ([127.0.0.1]:45028 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pCiK3-0007Ea-3N for submit@debbugs.gnu.org; Tue, 03 Jan 2023 09:31:23 -0500 Original-Received: from mail-4018.proton.ch ([185.70.40.18]:37167) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pCiJy-0007EK-GR for 60407@debbugs.gnu.org; Tue, 03 Jan 2023 09:31:21 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rjt.dev; s=protonmail2; t=1672756271; x=1673015471; bh=Ff17HKrc29sDxifvwgRE0e4b7wCFOKazs4xEwINJiug=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=MahC2tQDA+zkVqvUdTbKD4FXt5YkotWsk5xVrMNI6OjmxBQOJRRyQBzGi2eim89nO AtQToH98tfw+FAtdjCoTaWP5+qUYtfsGCUd+CNgkHGUgI41ditbBKh3tZSgbA2MCqs z/cmGYAJlCJOdD5PTEw1T91oI+jMeUaVBqQtK9w0d7qcc0DjJ1O86uYAfjPG/TCnm0 RC1XFdY/d5HWJPd8ORLZyUBmnYzzepXKcNo368WNMwL8mEJEwRt3pZ/lXIYd8E8eCN wYz954vTY6PZ5IPjkP8L9nl7RWhgnEnvIr5OAHiB6WYoZaBn1lOOhuOiPrtmfaZtv7 k4MRaC73wShFQ== In-Reply-To: Feedback-ID: 44397038:user:proton X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:252407 Archived-At: On Tuesday, January 3rd, 2023 at 04:01, Evgeni Kolev w= rote: > > Hi Randy, thank you for your feedback! >=20 > I'm providing an updated patch below. I tested with "type Quack int" > and other cases such as: > type MyInt =3D int > type Option func(s string) > type List[T any] struct { > head, tail *element[T] > } > type Number interface { > int64 | float64 > } >=20 > After experimenting, I decided to add additional Imenu categories: > "Alias" and "Type". > So the final list of newly added categories is "Method", "Struct", > "Interface", "Alias" and "Type". Sounds good to me. It looks like the alias type MyInt =3D int shows up in both categories: Ali= as and Type. It should probably belong just in the Alias category. >=20 > Structs and interfaces are technically a private case for "Type", but > are put in their own Imenu category. > Hence the "Type" category now holds all types except structs, > interfaces and aliases (aliases have their own tree sitter type > defined in Go's grammar.js). >=20 > For reference, eglot's Imenu uses category "Class" instead of "Type". > But I decided to not replicate this behavior - "Class" is not a widely > used Go concept. > However, I decided to replicate another eglot behaviour - prefixing > the method names with the type of the receiver (for example, > "(rect).area" for "func (r rect) area() float64..."). Great! I was going to suggest that but forgot. >=20 > I've also addressed the other comments. I'm a bit unsure how the git > commit should be formatted - the part of the message which describes > changed functions/files. >=20 > Please let me know if the patch can be improved. The patch is below. Comments below. >=20 > commit a96e70052a79881ac666ab699ffd63ed916eaf83 > Author: Evgeni Kolev evgenysw@gmail.com >=20 > Date: Thu Dec 29 17:49:40 2022 +0200 >=20 > Improve go-ts-mode Imenu Maybe this should also say "and add navigation support" (or something simil= ar)? >=20 > The Imenu items are extended to support "Method", "Struct", > "Interface", "Alias" and "Type". >=20 > go-ts-mode is updated to use the Imenu facility added in commit > b39dc7ab27a696a8607ab859aeff3c71509231f5. >=20 > * lisp/progmodes/go-ts-mode.el (go-ts-mode--imenu-1) (go-ts-mode--imenu): > Remove functions. > (go-ts-mode--defun-name) (go-ts-mode--interface-node-p) I'm no commit format expert, but I think this can be (go-ts-mode--defun-nam= e, go-ts-mode--interface-node-p) Whenever it fits on a single line, you can combine them like that. Same for= the line below. > (go-ts-mode--struct-node-p) (go-ts-mode--other-type-node-p) > (go-ts-mode--alias-node-p): New functions. > (go-ts-mode): Improve Imenu settings. I think the (go-ts-mode) part should mention that navigation support was ad= ded. >=20 > diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el > index 1d6a8a30db5..d91b555e03e 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--i= menu () - "Return Imenu alist for the current buffer." - (let* ((node (tree= sit-buffer-root-node)) - (func-tree (treesit-induce-sparse-tree - node "fun= ction_declaration" nil 1000)) - (type-tree (treesit-induce-sparse-tree - no= de "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--im= enu-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)) >=20 > @@ -228,9 +190,21 @@ go-ts-mode > (setq-local comment-end "") > (setq-local comment-start-skip (rx "//" (* (syntax whitespace)))) >=20 > + ;; Navigation. > + (setq-local treesit-defun-type-regexp > + (regexp-opt '("method_declaration" > + "function_declaration" > + "type_declaration"))) > + (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) > + ("Method" "\\`method_declaration\\\\'" nil nil) + ("Struct" "\\\\`type_= declaration\\'" > go-ts-mode--struct-node-p nil) > + ("Interface" "\\`type_declaration\\\\'" go-ts-mode--interface-node-p ni= l) + ("Type" "\\\\`type_declaration\\'" > go-ts-mode--other-type-node-p nil) > + ("Alias" "\\`type_declaration\\'" > go-ts-mode--alias-node-p nil))) >=20 > ;; Indent. > (setq-local indent-tabs-mode t > @@ -247,6 +221,53 @@ go-ts-mode >=20 > (treesit-major-mode-setup))) >=20 > +(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) > + ("function_declaration" > + (treesit-node-text > + (treesit-node-child-by-field-name > + node "name") > + t)) > + ("method_declaration" > + (let* ((receiver-node (treesit-node-child-by-field-name node "receiver"= )) > + (type-node (treesit-search-subtree receiver-node > "type_identifier")) > + (name-node (treesit-node-child-by-field-name node "name"))) > + (concat > + "(" (treesit-node-text type-node) ")." > + (treesit-node-text name-node)))) > + ("type_declaration" > + (treesit-node-text > + (treesit-node-child-by-field-name > + (treesit-node-child node 0 t) "name") > + t)))) > + > +(defun go-ts-mode--interface-node-p (node) > + "Return t if NODE is an interface." > + (and > + (string-equal "type_declaration" (treesit-node-type node)) > + (treesit-search-subtree node "interface_type" nil nil 2))) I think you need to add (declare-function treesit-search-subtree "treesit.c= ") after the last one at the top of the file. > + > +(defun go-ts-mode--struct-node-p (node) > + "Return t if NODE is a struct." > + (and > + (string-equal "type_declaration" (treesit-node-type node)) > + (treesit-search-subtree node "struct_type" nil nil 2))) > + > +(defun go-ts-mode--alias-node-p (node) > + "Return t if NODE is a type alias." > + (and > + (string-equal "type_declaration" (treesit-node-type node)) > + (treesit-search-subtree node "type_alias" nil nil 1))) > + > +(defun go-ts-mode--other-type-node-p (node) > + "Return t if NODE is a type, other than interface or struct." > + (and > + (string-equal "type_declaration" (treesit-node-type node)) > + (not (go-ts-mode--interface-node-p node)) > + (not (go-ts-mode--struct-node-p node)))) Here I guess we just need a (not alias) (and the docstring updated) to fix = the issue mentioned above. > + > ;; go.mod support. >=20 > (defvar go-mod-ts-mode--syntax-table >