emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Adding support for xref jumping to headers/interfaces


From: Dmitry Gutov
Subject: Re: Adding support for xref jumping to headers/interfaces
Date: Tue, 28 Nov 2023 02:18:19 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0

On 27/11/2023 17:19, João Távora wrote:

Alright, so since this is contentious (who else but you is pushing
this idea?)

Indeed, I wonder if nobody else is interested in having the additional
commands have pre-defined bindings, or having the same bindings across
languages.

Of course if you put it like that then EVERYBODY is interested in that.
Everybody likes consistency, but this consistency you're proposing
is a mirage.  An naive Xref user would be very proud to use
"xref-find-declaration" in 3 different languages but then would
start to doubt xref that the things he and the backend author meant
by declaration are entirely different.

It's not like things are very different now: a backend might fail to implement "references", or the new "kinds" thingy, leaving the most recent addition not working anyway.

Or, again, different languages might have different notions for what a "definition" is. E.g. C vs. TeX.

Again, leave this to major modes, which is what we always do (or to backend
which in 95% of cases would live in the major mode when they are
language-specific).

I wonder where you're getting this statistic from: advanced language analysis features don't usually live in major modes, not in the current state of the Emacs ecosystem.

what about we start with 0 in xref.el.  We can always
add to 0, no problem, but taking away  from some other number
isn't so easy.

We could indeed start with 0, but then I already see the same set of
extra commands supported in Eglot, Elisp, lsp-mode

They only exist in Eglot and LSP-mode because these are LSP things,
it makes full sense they would exist in any Emacs/LSP interface.

Before LSP, they would similarly make sense for eclim, or omnisharp, or rtags/irony-mode, and etc. And that would be the case after LSP, unless the current crop of popular languages is simply washed away. We might have taken the names from LSP where they're nicely categorized, but they correspond to existing navigation features in IDEs that's been there for years.

Elisp?  What commands are you talking about, only if you force them.
I see no elisp-find-{declaration,type-definition,implementation}
or anything of the sort.

The 7 Elisp cross-reference kinds you defined in your original
patch are

   "defalias"
   "face"
   "function"
   "constructor"
   "generic"
   "variable"
   "feature'"

That's a good critique. But the list above is a different ontology than the declaration/implementation/type-definition "drawers" we were talking about. I wonder how much of it really language-specific.

E.g., a C++/Java/Ruby program also has symbols like modules/namespaces/classes/methods/functions... Variables, too. Some have global ones, some allow one local variables.

What makes the drawers called declaration/definition/implementation/type-definition different? I think that these ones, in many cases, apply several at once to the same symbol, and not just the same name, but the same entity in the code, such as for example a method -- one method can have a declaration and an implementation (which is these are the "definition" -- perhaps both -- is up to interpretation). Or a variable can have a definition (or declaration -- for variables they're usually the same) -- and a type definition. Point is, there is no way for the Xref backend to decide which of these you want to see when invoking "M-.", that's why there are separate actions for them in the protocol.

Whereas for Elisp's defalias/face/function/constructor/generic/variable/feature, 95% of the time the choice is easy to detect from the usage context. Same for modules/classes/methods for Ruby or C++. That's actually the reason why I felt my implementation for Elisp's "kinds" was useless -- it's simply slower and more awkward to work with than the existing 'M-.' (which has the automatic "infer namespace" functionality since 2021 courtesy of Mattias).

So we could also say that declaration/definition/implementation/type-definition are the names of "search actions" whereas namespace/class/face/function are "symbol namespaces". And to make interaction with "symbol namespaces" more useful, I'm guessing we would need something more - e.g. namespace-specific symbol completion. For xref-find-all-definitions (or whatever new name it has) to prompt for the namespace first and then fetch its specific identifier completion table (all functions or all faces, etc). And that, by the way, could also work in different languages, with very similar nomenclature (I think only "face" in the above list is really Elisp-specific).

I concede that the "search actions" such as find-declaration/implementation (and especially type-definition) are less useful in Elisp than in OO languages where inheritance (or at least traits/mixins) are used more widely. Maybe just for the cl-generic code, which is a minority. OTOH, perhaps they would be more relevant in CL?

   and to allow frictionless extensions for special capabilities.

As to frictionless extension, the macro I proposed already
xref-define-finder seems the easiest way by far.

Sorry, I can't find it.

But the definition of xref-find-declarations takes about 3 lines. There
is not much potential for making it even shorter.

It's very similar and analogous to:

(defmacro eglot--code-action (name kind)
   "Define NAME to execute KIND code action."
   `(defun ,name (beg &optional end)
      ,(format "Execute `%s' code actions between BEG and END." kind)
      (interactive (eglot--code-action-bounds))
      (eglot-code-actions beg end ,kind t)))

And allows us to control exactly the 'interactive' spec of such
commands to give us consistency among them.

I'm wary of using macros as framework/library interface in Elisp because unless they are very stable, they can cause versioning problems when upgrading or reverting to an earlier version. You change a macro, but a dependent package is already installed and byte-compiled, and there won't be a recompilation until its next update. We might not even intend to change them much, but then you don't always anticipate a bugfix.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]