all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: "João Távora" <joaotavora@gmail.com>
To: Dmitry Gutov <dmitry@gutov.dev>
Cc: 72705@debbugs.gnu.org
Subject: bug#72705: 31.0.50; eglot--dumb-tryc Filters out too much
Date: Wed, 21 Aug 2024 17:52:19 +0100	[thread overview]
Message-ID: <87ed6hyg1o.fsf@gmail.com> (raw)
In-Reply-To: <0632f40f-98fd-4388-aba0-629a32d415eb@gutov.dev> (Dmitry Gutov's message of "Wed, 21 Aug 2024 03:30:18 +0300")

Dmitry Gutov <dmitry@gutov.dev> writes:

> On 20/08/2024 12:40, João Távora wrote:
>> On Tue, Aug 20, 2024 at 3:08 AM Dmitry Gutov <dmitry@gutov.dev> wrote:
>> 
>>> So far I've tested with gopls and clangd (when writing the new tests),
>>> typescript-language-server and rust-analyzer.
>> That's pretty good.  If you could add pylsp or pyright
>> (basedpyright),
>> I'd feel even more confident.
>
> Installed pylsp with apt - the basic things I tested seem to work too.

Great.

>> I don't have time to spend examining these details, just the final
>> outcome is relevant: partial completions cannot be inserted, but
>> fragments of a completion can be completed to a fully formed
>> completion (eventually running exit-function then).
>
> And only fragments that prefix-match all completions as
> prefix. exit-function seems to function.

Also good.

> In relation to the current state, but I think I've figured it out -
> see the new revision attached.

Great.

> See the new test 'eglot-test-try-completion-inside-symbol' inside the
> patch. Wasn't sure whether to make it use 'completion-try-completion'
> or 'completion-at-point', but the former seems more explicit.

This all looks very good, especially the abundant tests.  You may push
right now if you want.

I'll just comment on those:

+(ert-deftest eglot-test-common-prefix-completion ()
+  "Test completion appending the common prefix."
+  (skip-unless (executable-find "clangd"))
+  (eglot--with-fixture
+      `(("project" . (("coiso.c" .

Eh.  You may replace "coiso.c" for the Russian equivalent of "thingy.c"
if you want :-).  Or something more imaginative.

+                       ,(concat "int foo_bar; int foo_bar_baz;"
+                                "int main() {foo")))))
+    (with-current-buffer
+        (eglot--find-file-noselect "project/coiso.c")
+      (eglot--wait-for-clangd)
+      (goto-char (point-max))
+      (completion-at-point)
+      (should (looking-back "{foo_bar")))))

Here, we completed to foo_bar and it's a fully formed completion.  I
understand you've checked that exit-function does run.  This is good.

Unfortunately, if the the two ints were named "foo_bar_1" and
"foo_bar_2" it would also complete to foo_bar_, which is wrong in the
general case, since that text is not a fully formed completion.
exit-function cannot run here.

It happens to "work" here because clangd supplies the "insertText" as
well as the "textEdit" property and that "insertText" isn't meaningless.
The LSP spec recommendation is for servers to prefer supplying textEdit.

    * The `insertText` is subject to interpretation by the client side.
    * Some tools might not take the string literally. For example
    * VS Code when code complete is requested in this example
    * `con<cursor position>` and a completion item with an `insertText` of
    * `console` is provided it will only insert `sole`. Therefore it is
    * recommended to use `textEdit` instead since it avoids additional client
    * side interpretation.

Anyway this is _not_ a regression in your patch: the current state also
does this mistake.  Though, I wonder if you could fix it as well (in a
follow-up commit, maybe).

+(ert-deftest eglot-test-stop-completion-on-nonprefix ()
+  "Test completion also resulting in 'Complete, but not unique'."
+  (skip-unless (executable-find "clangd"))
+  (eglot--with-fixture
+      `(("project" . (("coiso.c" .
+                       ,(concat "int foot; int footer; int fo_obar;"
+                                "int main() {foo")))))
+    (with-current-buffer
+        (eglot--find-file-noselect "project/coiso.c")
+      (eglot--wait-for-clangd)
+      (goto-char (point-max))
+      (completion-at-point)
+      (should (looking-back "foo")))))

Here, we're looking-back to "foo" here because _no_ completion took
place.  This means a *Completions* buffer has appeared and is now
offering foot and footer.

The current state does not do this, and chooses one of the two
completions indiscrimately.  This is, I think, the original bug you
reported here.  So this is clearly a win.  To underline it and defend
against regresison, I suggest to also assert that the *Completions*
buffer popped up.  Though, maybe not going so far as asserting the there
are exactly those two completions in that order -- doing it
"graphically" might prove too brittle.

+(ert-deftest eglot-test-try-completion-inside-symbol ()
+  "Test completion table inside symbol, with only prefix matching."
+  (skip-unless (executable-find "clangd"))
+  (eglot--with-fixture
+      `(("project" . (("coiso.c" .
+                       ,(concat
+                         "int foobar;"
+                         "int main() {foo123")))))
+    (with-current-buffer
+        (eglot--find-file-noselect "project/coiso.c")
+      (eglot--wait-for-clangd)
+      (goto-char (- (point-max) 3))
+      (should
+       (equal
+        '("foo123" . 3)
+        (completion-try-completion
+         "foo123"
+         (nth 2 (eglot-completion-at-point)) nil 3))))))

I don't understand the point of this last test.  Are you checking that
nothing changes?  What are you guarding against?

Finally, an interesting test could be the rust-analyzer one from the
issue 1339 issue, which starts with.

fn main() {
    let v: usize = 1;
    1234.1234567890
}

I've manually checked that neither the v.c1234.12345676890 nor the
v.count_on1234.1234567890 case has regressed.

The tests for rust-analyzer require a bit more boilerplate (they require
a "cargo" call to setup a temporary project), but other than that it's
mostly the same.  They won't run on Hydra (no rust-analyzer there)), but
I do run them on occasion.

João





  reply	other threads:[~2024-08-21 16:52 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-19  1:51 bug#72705: 31.0.50; eglot--dumb-tryc Filters out too much Dmitry Gutov
2024-08-19  9:22 ` João Távora
2024-08-19 11:39   ` Dmitry Gutov
2024-08-19 12:59     ` João Távora
2024-08-20  2:08       ` Dmitry Gutov
2024-08-20  9:40         ` João Távora
2024-08-21  0:30           ` Dmitry Gutov
2024-08-21 16:52             ` João Távora [this message]
2024-08-22  0:41               ` Dmitry Gutov
2024-08-22 16:59                 ` João Távora
2024-08-22 23:16                   ` Dmitry Gutov
2024-08-23 10:23                     ` João Távora
2024-08-25  2:49                       ` Dmitry Gutov
2024-08-25  9:53                         ` João Távora
2024-08-25 15:56                           ` Dmitry Gutov
2024-08-25 23:40                           ` Dmitry Gutov

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

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

  git send-email \
    --in-reply-to=87ed6hyg1o.fsf@gmail.com \
    --to=joaotavora@gmail.com \
    --cc=72705@debbugs.gnu.org \
    --cc=dmitry@gutov.dev \
    /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 external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.