Subject: bug#79363: 31.0.50; Font locking issue in go-ts-mode when tree-sitter grammar is automatically installed

From: Roi Martin <[email-masked]>
Date: Mon, 01 Sep 2025 23:31:52 +0200

Steps to reproduce:

1. Run
     emacs -Q --init-directory=/tmp/go-ts-mode-bug
2. Eval
     (setopt treesit-enabled-modes '(go-ts-mode))
3. Open .go file
4. Answer y to the question
     Tree-sitter grammar for `go' is missing; install it?  (y or n)
5. go-ts-mode emits the following warning and definitions are not
   highlighted correctly.

     ⛔ Warning (treesit-font-lock-rules-mismatch): Emacs cannot compile
     every font-lock rules because a mismatch between the grammar and the
     rules.  This is most likely due to a mismatch between the font-lock
     rules defined by the major mode and the tree-sitter grammar.
     
     This error can be fixed by either downgrading the grammar
     (tree-sitter-go) on your system, or upgrading the major mode package.
     The following are the temporarily disabled features:
     
     - `definition' for go.

In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.24.49, cairo version 1.18.2)
Repository revision: 3c94ae5a37eac0191fe5d8bd85164b190ac10244
Repository branch: master

I took a quick look and I think this is caused by the following issue:

1. `go-ts-mode--font-lock-settings' depends on the following functions:

     (defun go-ts-mode--iota-query-supported-p ()
       "Return t if the iota query is supported by the tree-sitter-go grammar."
       (ignore-errors
         (or (treesit-query-string "" '((iota) @font-lock-constant-face) 'go) t)))
     
     (defun go-ts-mode--method-elem-supported-p ()
       "Return t if Go grammar uses `method_elem' instead of `method_spec'."
       (ignore-errors
         (or (treesit-query-string "" '((method_elem) @cap) 'go) t)))

2. In this sceneario we don't have the Go grammar installed yet.  So,
   `treesit-query-string' returns a `not-found' error.
3. Because of the previous error, `go-ts-mode--method-elem-supported-p'
   returns `nil'.  Thus, the "definition" rule uses "method_spec" which
   is not supported by the default grammar (commit
   "12fe553fdaaa7449f764bc876fd777704d4fb752").

     (defvar go-ts-mode--font-lock-settings
       (treesit-font-lock-rules
        ...
        :language 'go
        :feature 'definition
        `(...
          (,(if (go-ts-mode--method-elem-supported-p)
                'method_elem
              'method_spec)
           name: (field_identifier) @font-lock-function-name-face)

Please, take this analysis with a pinch of salt.  I'm not familiar with
the code base.  But I hope it makes sense.

        Roi