universal-ctags / citre

A superior code reading & auto-completion tool with pluggable backends.
GNU General Public License v3.0
337 stars 26 forks source link

no applicable method reported from xref-find-definitions #148

Open wanghaiqiangk opened 1 year ago

wanghaiqiangk commented 1 year ago

When invoking xref-find-definitions which is bound to M-. at a symbol, the echo area says no applicable method: xref-backend-definitions, citre, <symbol-name-here>.

This happens after I updated citre from a relative old release to the latest version.

The backtrace after enabling debug-on-entry is shown below:

Debugger entered--entering a function:
* cl-no-applicable-method(#s(cl--generic :name xref-backend-definitions :dispatches ((1 #s(cl--generic-generalizer :name cl--generic-t-generalizer :priority 0 :tagcode-function #f(compiled-function (name &rest _) #<bytecode 0x1fcdee8ad43f>) :specializers-function #f(compiled-function (tag &rest _) #<bytecode 0x1fcdee8ad42f>))) (0 #s(cl--generic-generalizer :name cl--generic-eql-generalizer :priority 100 :tagcode-function #f(compiled-function (name &rest _) #<bytecode 0x1fcdee8ac19d>) :specializers-function #f(compiled-function (tag &rest _) #<bytecode 0x1fcdee8ac17d>)) #s(cl--generic-generalizer :name cl--generic-t-generalizer :priority 0 :tagcode-function #f(compiled-function (name &rest _) #<bytecode 0x1fcdee8ad43f>) :specializers-function #f(compiled-function (tag &rest _) #<bytecode 0x1fcdee8ad42f>)))) :method-table (#s(cl--generic-method :specializers ((eql 'citre) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend symbol) "Method for xref to find definitions of SYMBOL." #<bytecode 0xed7061>)) #s(cl--generic-method :specializers ((eql etags) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend symbol) #<bytecode 0xe9c25d>)) #s(cl--generic-method :specializers ((eql eglot) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend id) #<bytecode 0xed59e1>)) #s(cl--generic-method :specializers ((eql dumb-jump) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend prompt) #<bytecode 0xe32c29>)) #s(cl--generic-method :specializers ((eql elisp) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend identifier) #<bytecode 0x1fcdeea1cd6d>))) :options nil) citre "comm_init")
* apply(cl-no-applicable-method #s(cl--generic :name xref-backend-definitions :dispatches ((1 #s(cl--generic-generalizer :name cl--generic-t-generalizer :priority 0 :tagcode-function #f(compiled-function (name &rest _) #<bytecode 0x1fcdee8ad43f>) :specializers-function #f(compiled-function (tag &rest _) #<bytecode 0x1fcdee8ad42f>))) (0 #s(cl--generic-generalizer :name cl--generic-eql-generalizer :priority 100 :tagcode-function #f(compiled-function (name &rest _) #<bytecode 0x1fcdee8ac19d>) :specializers-function #f(compiled-function (tag &rest _) #<bytecode 0x1fcdee8ac17d>)) #s(cl--generic-generalizer :name cl--generic-t-generalizer :priority 0 :tagcode-function #f(compiled-function (name &rest _) #<bytecode 0x1fcdee8ad43f>) :specializers-function #f(compiled-function (tag &rest _) #<bytecode 0x1fcdee8ad42f>)))) :method-table (#s(cl--generic-method :specializers ((eql 'citre) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend symbol) "Method for xref to find definitions of SYMBOL." #<bytecode 0xed7061>)) #s(cl--generic-method :specializers ((eql etags) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend symbol) #<bytecode 0xe9c25d>)) #s(cl--generic-method :specializers ((eql eglot) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend id) #<bytecode 0xed59e1>)) #s(cl--generic-method :specializers ((eql dumb-jump) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend prompt) #<bytecode 0xe32c29>)) #s(cl--generic-method :specializers ((eql elisp) t) :qualifiers nil :uses-cnm nil :function #f(compiled-function (backend identifier) #<bytecode 0x1fcdeea1cd6d>))) :options nil) (citre "comm_init"))
* #f(compiled-function (&rest args) #<bytecode 0x10ab7f1>)(citre "comm_init")
* apply(#f(compiled-function (&rest args) #<bytecode 0x10ab7f1>) citre "comm_init")
* xref-backend-definitions(citre "comm_init")
* #f(compiled-function () #<bytecode 0x221f90d>)()
* xref-show-definitions-buffer(#f(compiled-function () #<bytecode 0x221f90d>) ((window . #<window 3 on core.c>) (display-action) (auto-jump)))
* xref--show-defs(#f(compiled-function () #<bytecode 0x221f90d>) nil)
* xref--find-definitions("comm_init" nil)
* #f(compiled-function (identifier) "Find the definition of the identifier at point.\nWith prefix argument or when there's no identifier at point,\nprompt for it.\n\nIf sufficient information is available to determine a unique\ndefinition for IDENTIFIER, display it in the selected window.\nOtherwise, display the list of the possible definitions in a\nbuffer where the user can select from the list.\n\nUse \\[xref-go-back] to return back to where you invoked this command." (interactive #f(compiled-function () #<bytecode 0x1693925>)) #<bytecode 0xe19335>)("comm_init")
* apply(#f(compiled-function (identifier) "Find the definition of the identifier at point.\nWith prefix argument or when there's no identifier at point,\nprompt for it.\n\nIf sufficient information is available to determine a unique\ndefinition for IDENTIFIER, display it in the selected window.\nOtherwise, display the list of the possible definitions in a\nbuffer where the user can select from the list.\n\nUse \\[xref-go-back] to return back to where you invoked this command." (interactive #f(compiled-function () #<bytecode 0x1fdd6bd>)) #<bytecode 0xe19335>) "comm_init")
* xref-find-definitions("comm_init")
  funcall-interactively(xref-find-definitions "comm_init")
  call-interactively(xref-find-definitions nil nil)
  command-execute(xref-find-definitions)

Besides, the xref-backend-functions variable has the value of (citre-xref-backend t). Manual calls to citre-jump work fine.

Any idea what's the problem here?


Citre config

(use-package citre
  :defer t
  :init
  (require 'citre-config)
  :config
  (setq
   citre-peek-fill-fringe nil
   citre-completion-case-sensitive nil
   ;; citre-project-root-function #'projectile-project-root
   citre-use-project-root-when-creating-tags t
   citre-prompt-language-for-ctags-command t))

Update Found that it's the 84bf573 refactor: pluggable backend design caused the problem.

AmaiKinono commented 1 year ago

Using your config in $ emacs -Q, I can't reproduce the problem. I'm on Arch Linux and Emacs 28.2.

zhongweiy commented 1 year ago

I also have this issue. And find it can be solved by:

modified   citre.el
@@ -422,7 +422,7 @@ The returned value is a valid return value for
   "The Citre backend for xref."
   'citre)

-(cl-defmethod xref-backend-identifier-at-point ((_backend (eql 'citre)))
+(cl-defmethod xref-backend-identifier-at-point ((_backend (eql citre)))
   "Define method for xref to get symbol at point."
   (when-let ((symbol (symbol-at-point)))
     ;; The symbol name doesn't matter for us.  We record the buffer in the text
@@ -432,7 +432,7 @@ The returned value is a valid return value for
                         'xref-symbol-buffer (current-buffer))))

 (cl-defmethod xref-backend-identifier-completion-table
-  ((_backend (eql 'citre)))
+  ((_backend (eql citre)))
   "Return a function for xref to find all completions of a prefix."
   (lambda (str pred action)
     ;; We need this since Xref calls this function in minibuffer.
@@ -441,7 +441,7 @@ The returned value is a valid return value for
                      (citre-get-backend-and-id-list))))
       (complete-with-action action (cdr result) str pred))))

-(cl-defmethod xref-backend-definitions ((_backend (eql 'citre)) symbol)
+(cl-defmethod xref-backend-definitions ((_backend (eql citre)) symbol)
   "Method for xref to find definitions of SYMBOL."
   (if-let ((buf (citre-get-property 'xref-symbol-buffer symbol)))
       ;; If true, the symbol is grabbed from a buffer, not identifier
@@ -451,7 +451,7 @@ The returned value is a valid return value for
     (let ((defs (citre-get-definitions-of-id symbol)))
       (citre-xref--make-collection defs))))

-(cl-defmethod xref-backend-references ((_backend (eql 'citre)) symbol)
+(cl-defmethod xref-backend-references ((_backend (eql citre)) symbol)
   "Method for xref to find references of SYMBOL."
   (if-let ((buf (citre-get-property 'xref-symbol-buffer symbol)))
       (with-current-buffer buf

I don't know why sometime (eql 'citre) also works.

AmaiKinono commented 1 year ago

I don't know why sometime (eql 'citre) also works.

This may be a wrong behavior in Emacs 27, see https://emacs-china.org/t/topic/6620/7. Are you using Emacs 27?

I was following the elisp xref backend when implementing citre xref backend. See xref-backend-definitions in elisp-mode.el:

(cl-defmethod xref-backend-definitions ((_backend (eql 'elisp)) identifier) ...

Does it look different in Emacs 27?