unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: "João Távora" <joaotavora@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: dalal.chinmay.0101@gmail.com, emacs-devel@gnu.org,
	dimitri@belopopsky.com,  luangruo@yahoo.com
Subject: Re: Eglot "inlay hints" landed
Date: Thu, 23 Feb 2023 16:09:24 +0000	[thread overview]
Message-ID: <CALDnm52WVVLkUPxgWoHSH2xPQSmSNTEWhJOMkMvZaiAak3dJHQ@mail.gmail.com> (raw)
In-Reply-To: <83y1oophd0.fsf@gnu.org>

On Thu, Feb 23, 2023 at 2:49 PM Eli Zaretskii <eliz@gnu.org> wrote:
>
> > From: João Távora <joaotavora@gmail.com>
> > Cc: dalal.chinmay.0101@gmail.com,  emacs-devel@gnu.org,
> >   dimitri@belopopsky.com,  luangruo@yahoo.com
> > Date: Thu, 23 Feb 2023 12:57:26 +0000
> >
> > Eli Zaretskii <eliz@gnu.org> writes:
> >
> > > We don't need to make the overlays until the buffer is shown in some
> > > window, right?
> >
> > Yes, but two buffers A and B might already be showing in some window.
> > If you do the change in buffer A and it affects B, then in the current
> > version, the parts of A being show in windows will be updated, but B the
> > parts of B being shown in some other windows will not.
>
> If there's a change in A that affects B, jit-lock will call
> fontification-functions in both A and B, each one when it's about to
> display the corresponding window.

Sure, but you're in charge of coding up the "affection" by asking
the LSP server.  In other words, only the LSP server knows that the
change in A affects B. You must assume that it does and ask it "Hey LSP
server, given that I've just changed document A, in your document B from
42 to 420 is are there any new or different inlay hints you'd like to
give me?" jit-lock cannot foresee that upfront, it will only act on B's
display if B's buffer is changed.

Regardless of that separate issue, I started experimenting with
jit-lock-register.  It's promising, but has problems. Here's a
small experiment.  Use this foo.cpp file somewhere and have say,
the clangd server handy.

void foo(int bar){}

int main() {
  foo(42);
  .... repeats about ~250 times ....
  foo(42);
}

If you start eglot and eglot-inlay-hints-mode in this buffer,
you should see

void foo(int bar){}

int main() {
  foo(bar: 42);  // 'bar: ' is the untangible hint overlay
  foo(bar: 42);
  foo(bar: 42);
  ...
  < end of window >

I also traced the current eglot--update-hints-1 file which is a
binary function of two buffer positions, just like the jit
function.

This is the function that contacts the LSP server via JSONRPC
and some time in the future, after it returns, the 0-length
overlays will be created.

Here's how it is called after enabling eglot and scrolling 4
screenfuls forward (C-v) and 4 back (M-v).

======================================================================
1 -> (eglot--update-hints-1 1 476)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 443 927)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 894 1378)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 1345 1829)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 1796 2280)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 1345 1829)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 894 1378)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 443 927)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 1 476)
1 <- eglot--update-hints-1: nil

As you can see, it only requests inlay hints for the regions actually
displayed in the window.  It re-requests some stuff when going
back, since it has no memory of what it already requested or if
things were invalidated.

Now if I put eglot--update-hints-1 in jit-lock-function and
disable my window-scroll-functions, then do the same:

======================================================================
1 -> (eglot--update-hints-1 1 1501)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 1501 2678)
1 <- eglot--update-hints-1: nil

As you can see, it did much larger, heavier requests upfront, even before
it knew I was going to scroll forward.  But in general it worked and you
can argue that doing only two requests for larger chunks of inlay hints
is better than more requests for smaller chunks.

Now, if I change the line void foo(int bar){} to void foo(int baz){}
the point is to get updated hints in the window:

int main() {
  foo(baz: 42);  // 'bar: ' is the untangible hint overlay
  foo(baz: 42);
  foo(baz: 42);
  ...
  < end of window >

The jit-lock implementation will do this:

======================================================================
1 -> (eglot--update-hints-1 1 19)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 1 20)
1 <- eglot--update-hints-1: nil
======================================================================
1 -> (eglot--update-hints-1 20 1520)
1 <- eglot--update-hints-1: nil

The first two calls are useless and so is most of the third one.
For the third one you can argue, as above, that it's a good
thing to predict that the user is going to scroll down.  But
the first two, which also caused two LSP requests, are definitely
useless.

OT1H, I think I can make this work, by finding some means to
coalesce those three calls into one.  Suggestions welcome.
Even after that complexity, it seems it will be a much neater
implementation.

OTOH it sort of negates my original intention of requesting
only as many inlay hints as strictly necessary.  THough that
might have been premature optimization anyway.

> > PS: On an unrelated note, I pushed this to emacs-29.  If you wish me to
> > revert the inlay hints implementation and do all this work in master,
> > it's fine by me.
>
> emacs-29 is fine, thanks.

OK!

João



  reply	other threads:[~2023-02-23 16:09 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <ypi9cz6ahi5n.fsf@gmail.com>
     [not found] ` <83edqqaf8c.fsf@gnu.org>
     [not found]   ` <2B284D77-97DF-4B3E-89FB-13F0CA93D240@gmail.com>
     [not found]     ` <CALDnm53otfeDQGr0dWWUhxGLTSuiWTstLXJz1HXQgWLiAgsk=A@mail.gmail.com>
     [not found]       ` <CA+46MXbbW60t=JccgKGX39jTkOu+i=GZhzSQsfnqBUPb-mnJWg@mail.gmail.com>
2023-02-22 19:42         ` Eglot "inlay hints" landed João Távora
2023-02-23  1:45           ` [SPAM UNSURE] " Stephen Leake
2023-02-23  5:29           ` Chinmay Dalal
2023-02-23  6:31             ` Eli Zaretskii
2023-02-23  9:55               ` Chinmay Dalal
2023-02-23 10:03                 ` João Távora
2023-02-23 10:55                   ` Dimitri Belopopsky
2023-02-23 11:07                     ` João Távora
2023-02-23 12:03                     ` João Távora
2023-02-23 13:25                       ` Dimitri Belopopsky
2023-02-23 11:05                 ` Eli Zaretskii
2023-02-23 11:23                   ` João Távora
2023-02-23 12:36                     ` Eli Zaretskii
2023-02-23 12:57                       ` João Távora
2023-02-23 14:48                         ` Eli Zaretskii
2023-02-23 16:09                           ` João Távora [this message]
2023-02-23 17:17                             ` Eli Zaretskii
2023-02-23 17:46                               ` João Távora
2023-02-23 18:01                                 ` Eli Zaretskii
2023-02-23 19:26                                   ` João Távora
2023-02-23 19:54                                     ` Eli Zaretskii
2023-02-23 20:03                                       ` João Távora
2023-02-23 19:27                                 ` Stefan Monnier
2023-02-23 19:39                                   ` João Távora
2023-02-23 19:53                                     ` Stefan Monnier
2023-02-23 20:09                                       ` João Távora
2023-02-23 22:19                                         ` Stefan Monnier
2023-02-23 23:59                                           ` João Távora
2023-02-24  1:08                                             ` Stefan Monnier
2023-02-24  2:28                                               ` João Távora
2023-02-24  7:35                                               ` Eli Zaretskii
2023-02-24 10:42                                                 ` João Távora
2023-02-24 11:33                                                   ` Eli Zaretskii
2023-02-24 12:26                                                     ` João Távora
2023-02-23 10:17           ` Tassilo Horn
2023-02-23 12:55           ` Chinmay Dalal
2023-02-23 19:50           ` Nikola Pajkovsky
2023-02-23 21:35             ` João Távora
2023-02-23 21:45               ` Nikola Pajkovsky
2023-02-24  4:20               ` Chinmay Dalal
2023-02-24  5:04                 ` Chinmay Dalal
2023-02-24  9:59                 ` João Távora
2023-02-24 11:03                   ` Nikola Pajkovsky
2023-02-27 22:50           ` Johann Klähn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CALDnm52WVVLkUPxgWoHSH2xPQSmSNTEWhJOMkMvZaiAak3dJHQ@mail.gmail.com \
    --to=joaotavora@gmail.com \
    --cc=dalal.chinmay.0101@gmail.com \
    --cc=dimitri@belopopsky.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=luangruo@yahoo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).