From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Spencer Baugh Newsgroups: gmane.emacs.devel Subject: Re: Adding support for xref jumping to headers/interfaces Date: Wed, 08 Nov 2023 12:25:44 -0500 Message-ID: References: <861qm4tkih.fsf@stephe-leake.org> <71ea5e83-183f-2ae3-8146-6a31045a0309@yandex.ru> <834jqzafse.fsf@gnu.org> <83h6uv47e8.fsf@gnu.org> <4639d7ca-2109-864c-33c0-38e65f26f262@yandex.ru> <835ybb3txt.fsf@gnu.org> <83wn3q311i.fsf@gnu.org> <412afa2d-5dbc-52da-39c4-99be3873929c@yandex.ru> <83o7p20wdi.fsf@gnu.org> <72b09256-5a1b-8962-9e3c-7d2ffd0dc0d7@yandex.ru> <83ilf925n8.fsf@gnu.org> <95afa441-18ae-e62a-be16-be73a545bbba@yandex.ru> <54cb435f-4d51-4c0d-43d8-2991dd7ee6bd@gutov.dev> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="31656"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) To: emacs-devel@gnu.org Cancel-Lock: sha1:0TTVZpZO8A0phh29JPWLHxKpQkY= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed Nov 08 18:45:20 2023 Return-path: Envelope-to: ged-emacs-devel@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 1r0mcB-0007xv-Fk for ged-emacs-devel@m.gmane-mx.org; Wed, 08 Nov 2023 18:45:19 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r0mbi-0004yA-Ng; Wed, 08 Nov 2023 12:44:50 -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 1r0mJY-0001jq-Gl for emacs-devel@gnu.org; Wed, 08 Nov 2023 12:26:04 -0500 Original-Received: from ciao.gmane.io ([116.202.254.214]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1r0mJT-0006i5-R8 for emacs-devel@gnu.org; Wed, 08 Nov 2023 12:26:03 -0500 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1r0mJL-0002te-6O for emacs-devel@gnu.org; Wed, 08 Nov 2023 18:25:51 +0100 X-Injected-Via-Gmane: http://gmane.org/ Received-SPF: pass client-ip=116.202.254.214; envelope-from=ged-emacs-devel@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.25, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 08 Nov 2023 12:44:49 -0500 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:312355 Archived-At: Dmitry Gutov writes: > On 07/11/2023 18:51, Spencer Baugh wrote: >>> Perhaps it /should/ (xref-find-definitions to include both >>> implementation and interface). And include the typeDefinition entries >>> for langs that have those. Etc. >>> >>> Would the UI be worse? Let's try to find out. >>> >>> Attached is the patch along the lines that we discussed: a new command >>> xref-find-extra currently bound to M-' just for the sake of this >>> experiment (eliminating the need to set up define-key to try out the >>> "fast" workflow). It uses the symbol at point or asks for it, then >>> polls the backend for available kinds, does completing-read and asks >>> the backend for definitions of that kind. And shows the list or jumps >>> to the unique one. >>> >>> To have something to test, I implemented this for Elisp. However, all >>> known kinds are already printed by the regular xref-find-definitions >>> output in that backend. So the result turned out interesting, but a >>> little impractical: with Elisp, we already make the choice between the >>> kinds in the Xref output buffer, when that buffer is shown at all (as >>> Eli pointed out, actually). So... we could proceed in that direction >>> and recommend that all kinds of definitions would be added there. >> This (and Joao's patch adding support for eglot) is very >> interesting, >> thank you for implementing it! >> We also discussed a UI which shows all kinds of definitions in a >> single >> buffer. Maybe the prompt for KIND should default to "all" which shows >> all kinds of definitions? > > The natural question is whether 'xref-find-definitions' would be that > UI, and if not, why not. As in, xref-find-definitions (M-.) *by default* shows all kinds of definitions? That seems bad for one big reason: 90% of the time, in 90% of languages, there's a clear meaning of "definition" and I want M-. to take me there directly rather than prompting in any way. But there are other kinds of "definitions" which plausibly I could want, just sometimes, not by default. If you mean something a non-default version of xref-find-definitions, or another binding for another basically-identical command, sure, I think that would be good. We can have both that command *and* have a command which prompts for KIND and defaults to "all". > Also, if "references" are included in the list of kinds (as the > current patch for Eglot does, I think), then "show all kinds" is not > likely to be very useful -- all will drown in "references". True, interesting point. I wonder if we could reasonably distinguish "definition" kinds (a small number per identifier) from "reference" kinds (no limit on how many per identifier). Although I suppose there's also no limit on how many implementations of a generic function there can be, and that's definitely something that fits in "definitions". Maybe the backend could decide what kinds get included in "all". Then it could deliberately avoid including anything "reference-like". >> I notice the API doesn't support "fetch all kinds of definitions"; >> extra-defs requires specifying a specific kind. Perhaps just specifying >> a nil KIND should request all kinds, and extra-defs should tag each >> returned object with the kind? We could also just make a separate call >> to extra-defs for each kind returned by extra-kinds, but that would be >> allow less space for the backend to batch its operations. > > That's a question for later. > >>> Or perhaps the main value would be in actually having separate >>> commands which could be bound to a submap with faster key sequences >>> and/or to the context menu (with context-menu-mode on). Then our >>> solution should be more in line with either defining a number of >>> additional named commands (for mode universal kinds) and/or making it >>> easier to define new such commands for users/3rd-party packages/etc. >> That's an interesting idea. So maybe M-' (or whatever) could be a >> new >> prefix for a prefix-map which contains both universal and mode-specific >> kinds of lookups. >> So maybe something which looks kinda like (not suggesting final >> bindings, just trying to feel out what it would be like): >> generic eglot-find-implementation: M-' i >> generic eglot-find-declaration: M-' d >> generic eglot-find-typeDefinition: M-' t > > Then we will more-or-less nail down the whole set of "available Xref > kinds" in the core by having these commands defined. > > That's not very flexible, but if the set doesn't actually change too > much, and doesn't vary between languages a lot, it could work. Would > lead to a more straightforward design, too. Hm, why do you say this? This approach seems very extensible to me - modes could add their own bindings/commands/kinds for things specific to that mode. But they build on top of a set of common kinds which are provided by the core, which don't vary between language too much. I do think that if we go with an API which has any notion of "kinds", we should have some standard "kinds" in the core like implementation, declaration, type-definition. I don't see any reason not to do that. >> xref-extra-kind, prompting for kind: M-' M-' > > Would we need this command, if we had separate commands for each kind > already? This would support kinds which: - are language-specific, - or are more rarely used and don't need a dedicated command, - or are both. >> xref-extra-kind, showing all: M-' a >> And if there was something mode-specific, like the Java overriding >> method thing, it could be e.g. M-' o > > Most of them are mode-specific already. Some languages don't have > separate "declarations", some don't know what "type definitions" are, > and some, indeed, don't have method overrides. Most languages have something that can fit into "declaration" or "type definitions", though. For Elisp generics, find-implementation could show the cl-defmethod, and find-declaration could jump to the cl-defgeneric. I would love that, actually - I already find it rather annoying to have to navigate in the xref buffer to the cl-defgeneric when I M-. on a generic method, if I know up front that I want to jump to the cl-defgeneric. Actually, this example has just convinced me that I definitely want "kind-specific commands", even for Elisp. That would be great. For functions without separate declarations, find-implementation and find-declaration could jump to the same place. In some languages, maybe that's just always what happens. As for type definitions - even Elisp has things that could reasonably be called type definitions, we just don't support jump-to-definition for them right now. I have no idea how we'd implement it, but we could support jumping to cl-defstruct definitions, for example. Maybe we could use information from native compilation to guess the type of the identifier at point? But anyway, for now we'd just error if the user ran such a command in emacs-lisp-mode or other modes that don't support jumping to the type definition. >> I like this sort of design a lot actually: > >> - it's faster to type than having to complete the kind name (IMO, having >> to complete the kind name makes the current patch quite clumsy) >> - it allows a common set of keys between all modes >> - it's extensible by individual modes without too much trouble >> - it works naturally with context-menu-mode and other menus > > Indeed. > >> (although I suppose we could automatically populate the context-menu >> with the output from xref-backend-extra-kinds) > > Probably. > >> - users could still use completing-read to type the kind >> Plus, if we do use M-' or any other short binding for this, we >> should >> almost certainly make it the start of a new prefix-map rather than bind >> M-' directly to the new command; doing otherwise would be wasteful of >> valuable keybinding space. > > If we're going to have separate commands for kinds, that is indeed a > good idea. I almost want to say that we should have it be a prefix regardless of whether we have separate commands for kinds. I guess it depends: - if we use C-M-?, that's already such a hard key to hit that maybe it's okay if we bind it directly to a command - if we use M-' or something similarly convenient, it would be really tragic to not reclaim all that premium keybinding space. (And probably if we use M-' we will need to put the old command on something under M-' anyway)