oxalica / nil

NIx Language server, an incremental analysis assistant for writing in Nix.
Apache License 2.0
1.32k stars 39 forks source link

"In textDocument/completion, panicked: Bad offset" when using nil with kakoune #53

Closed 2xsaiko closed 1 year ago

2xsaiko commented 1 year ago

This error occurs when typing near the end of the document when using this with the kakoune editor and kak-lsp. A similar issue does not occur with rnix-lsp. This is a snippet of the output in kakoune's debug console:

kak-lsp: nix language server error: 'In textDocument/completion, panicked at /build/nil-2023-01-01-vendor.tar.gz/rowan/src/cursor.rs:751:9: Bad offset: range 0..624 offset 625'
kak-lsp: nix language server error: 'In textDocument/completion, panicked at /build/nil-2023-01-01-vendor.tar.gz/rowan/src/cursor.rs:751:9: Bad offset: range 0..624 offset 627'
kak-lsp: nix language server error: 'In textDocument/completion, panicked at /build/nil-2023-01-01-vendor.tar.gz/rowan/src/cursor.rs:751:9: Bad offset: range 0..624 offset 628'
kak-lsp: nix language server error: 'In textDocument/completion, panicked at /build/nil-2023-01-01-vendor.tar.gz/rowan/src/cursor.rs:751:9: Bad offset: range 0..624 offset 630

Here's an asciinema recording that displays the issue: https://asciinema.org/a/wJ3lKw7oyOQzRe1rrJYeV1xfd

Using nil 2023-01-01.

oxalica commented 1 year ago

I cannot reproduce the error by mimicking your recorded video. If you could deterministically reproduce it, please provided the nix file you are editing (maybe after simplification), the editing actions and/or keystrokes. I'm not familiar with kak. It would be better to check if vscode/vscodium or vim/neovim can reproduce it.

Also could you try running nil or your whole editor with environment variable NIL_LOG_PATH=nil.log, and provide the log file after the panic?

2xsaiko commented 1 year ago

You can build kakoune with the config I'm testing with (has kak-lsp with the necessary config to run nil already set up) with this command: nix build --expr 'let f = builtins.getFlake "git+https://git.dblsaiko.net/systems?ref=kakoune&rev=bbd6c6a7057271744e15f5faff537c1b8831a360"; s = f.nixosConfigurations.invader; in s.pkgs.kakoune.override { inherit (s.config.programs.kakoune) plugins; }'. Then open an empty/nonexisting .nix file (result/bin/kak a.nix) while nil is on the PATH, that's the simplest case that reproduces it, and write any text, which can be valid Nix or not. Key bindings are similar to vim (insert with i, esc, :q! to exit without writing). The error should immediately appear when you start typing.

Interestingly, the amount of characters the error starts at (or the range shown in the error) depends on how fast you type. It will be (in an empty file) "range 0..2" if you type slowly, but the right bound can increase if you type faster. Seems to me like nil's text state only gets updated until highlighting/error data is computed and sent to kakoune for the first time, or something like that.

I tested it with Kate (the other LSP editor I have already set up) and it seems to work correctly there, and other LSP servers like the ones for Rust, Python and TypeScript work correctly with kak-lsp, so I assume it's an interaction specifically between kak-lsp and nil, but I'm not sure on which side.

Running it with NIL_LOG_PATH=nil.log gives a file with only this text which seems unrelated:

2023-01-14T14:02:39.103124Z ERROR nil::server: Failed to calculate diagnostics: cancelled
oxalica commented 1 year ago

I suspect it's caused by the state change between diagnostics calculation and line-number conversion. https://github.com/oxalica/nil/blob/b3d65b8bd755372caacd63590a29e588eb8e7610/crates/nil/src/handler.rs#L24-L26

This is hard to fix with the current modal. The line-number map should be instead maintained in the database and snapshot-ed during the calculation, so that they'll be consistent.

oxalica commented 1 year ago

NVM, this particular issue is caused by mishandling of TextDocumentContentChangeEvent without range field, which is also valid. Well, both errors are fixed.

Your flake works fine for me now,

nix build --expr 'let f = builtins.getFlake "git+https://git.dblsaiko.net/systems?ref=kakoune&rev=bbd6c6a7057271744e15f5faff537c1b8831a360"; s = f.nixosConfigurations.invader; in s.pkgs.kakoune.override { inherit (s.config.programs.kakoune) plugins; }'

2xsaiko commented 1 year ago

Just got to test it, it works now. Thanks!