Previously `recv` for new messages from the language server or debug
adapter allocated a fresh Vec for each message. Instead we can reuse
the buffer. This resolves TODO comments.
Co-authored-by: Rolo <roloedits@gmail.com>
The old check would allow sending textDocument/documentColor requests
when the server declared `{"colorProvider": false}` in its capabilities
as this was `Some`:
Some(ColorProviderCapability::Simple(false))
The Julia language server sets this explicitly to `false` in the wild.
Previously the `call` helper (and its related functions) returned a
`serde_json::Value` which was then decoded either later in the client
(see signature help and hover) or by the client's caller. This led to
some unnecessary boilerplate in the client:
let resp = self.call::<MyRequest>(params);
Some(async move { Ok(serde_json::from_value(resp.await?)?) })
and in the caller. It also allowed for mistakes with the types. The
workspace symbol request's calling code for example mistakenly decoded a
`lsp::WorkspaceSymbolResponse` as `Vec<lsp::SymbolInformation>` - one of
the untagged enum members (so it parsed successfully) but not the
correct type.
With this change, the `call` helper eagerly decodes the response to a
request as the `lsp::request::Request::Result` trait item. This is
similar to the old helper `request` (which has become redundant and has
been eliminated) but all work is done within the same async block which
avoids some awkward lifetimes. The return types of functions like
`Client::text_document_range_inlay_hints` are now more verbose but it is
no longer possible to accidentally decode as an incorrect type.
Additionally `Client::resolve_code_action` now uses the `call_with_ref`
helper to avoid an unnecessary clone.
This follows a pattern used in the signature help request for example.
Moving the json deserialization into the return future of
`text_document_hover` makes the types easier for callers to work with.
The info log within `process_request_response` duplicated the body of
the JSON message printed earlier by the transport which was confusing.
The error log in the completion handler was easy to hit during normal
use and is not actually an error - dropping is the graceful way to
handle changes occurring while completion requests are in flight.
The clone of the hashmap can be avoided by passing a ref instead. This
commit also changes the `server_environment` type to match the bounds
expected by `Command::envs` - this will avoid future refactoring if the
underlying type changes (for example switching to `hashbrown::HashMap`).
This is a similar change to the parent commit but for `request`. The
requests should be sent eagerly so that the ordering stays consistent.
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
Previously LSP notifications were sent within a future and most callers
used a `tokio::spawn` to send the notification, silently discarding any
failures like problems serializing parameters or sending on the channel.
It's possible that tokio could schedule futures out of intended order
though which could cause notifications where order is important, like
document synchronization, to become partially shuffled. This change
removes the future wrapper and logs all internal failures.
Also included in this commit is the same change for `Client::reply`
which was also unnecessarily wrapped in a future.
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
When a new language server is started, find_lsp_workspace is called
with LanguageConfiguration::workspace_lsp_roots as the root_dirs.
This behavior is different when a new document is opened.
find_lsp_workspace is called with editor::Config::workspace_lsp_roots
which is never set.
This leads to a bug where workspace-lsp-roots is not respected when
opening a new document. This commit fixes this bug.
Servers stopped with `:lsp-stop` will show this message when the server
exits. If the client isn't in the registry there isn't any work to do
to remove it so this branch is benign.
* refactor `starting_request_args` to only `ref` non-`Copy`
* refactor `needs_recompile` to only `ref` non-`Copy`
* refactor `add_workspace_folder` to only `ref` `Some`
---------
Co-authored-by: Rudxain <rudxain@localhost.localdomain>
Without providing the formatting capability, the language server might not advertise its ability to format in return, causing the :format command to be broken.
While moving completion resolve to the event system in #9668 we introduced what
is essentially a "DOS attack" on slow LSPs. Completion resolve requests were
made in the render loop and debounced with a timeout. Once the timeout expired
the resolve request was made. The problem is the next frame would immediately
request a new completion resolve request (and mark the old one as obsolete but
because LSP has no notion of cancelation the server would still process it). So
we were in essence sending one completion request to the server every 150ms and
only stopped if the server managed to respond before we rendered a new frame.
This caused overload on slower machines/with slower LS.
In this PR I revamped the resolve handler so that a request is only ever
resolved once. Both by checking if a request is already in-flight and by marking
failed resolve requests as resolved.
Previously we used the IdleTimeout event to trigger LSP
`completion/resolveItem` requests. We can now refactor this to use an
event system hook instead and lower the timeout.
`syn_loader` was replaced rather than interior value being replace,
old value was still being referenced and not updated after `:config-refresh`.
By using `ArcSwap` like for `config`, each `.load()` call will return the most
updated value.
Co-authored-by: kyfan <kyfan@email>
* Added required-root-patterns for situational lsp activation using globbing
* Replaced filter_map with flatten
* updated book to include required-root-patterns option
* fixed wrong function name for path
* Added globset to helix-core. Moved globset building to config parsing.
* Normalize implements AsRef
* cargo fmt
* Revert "cargo fmt"
This reverts commit ca8ce123e8.
Currently, helix implements operations which change the paths of files
incorrectly and inconsistently. This PR ensures that we do the following
whenever a buffer is renamed (`:move` and workspace edits)
* always send did_open/did_close notifications
* send will_rename/did_rename requests correctly
* send them to all LSP servers not just those that are active for a
buffer
* also send these requests for paths that are not yet open in a buffer (if
triggered from workspace edit).
* only send these if the server registered interests in the path
* autodetect language, indent, line ending, ..
This PR also centralizes the infrastructure for path setting and
therefore `:w <path>` benefits from similar fixed (but without didRename)
We use `which::which` in many crates, so `which` was a separate
dependency across all of them. We can centralize `which` into the
stdx crate so it's easy for all crates to depend on it.
I also moved the rest of `helix-view/src/env.rs` into helix-stdx's
`env` module since it only contained a thin wrapper around `which`
and `std::env`.
helix-stdx is meant to carry extensions to the stdlib or low-level
dependencies that are useful in all other crates. This commit starts
with all of the path functions from helix-core and the CWD tracking that
lived in helix-loader.
The CWD tracking in helix-loader was previously unable to call the
canonicalization functions in helix-core. Switching to our custom
canonicalization code should make no noticeable difference though
since `std::env::current_dir` returns a canonicalized path with
symlinks resolved (at least on unix).
* feat(lsp): implement show document request
Implement [window.showDocument](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument)
LSP server-sent request.
This PR builds on top of helix-editor#5820,
moves the external-URL opening functionality into shared crate-level
function that returns a callback that is now used by both the
`open_file` command as well as the window.showDocument handler if
the URL is marked as external.
* add return
* use vertical split
* refactor
---------
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* Keep lsp event listener thread alive when malformed json is encountered from the lsp server
* Update unexpected error flow in recv() to close outstanding requests and close the language server
* Log malformed notifications as info instead of error
* Make close_language_server a nested function inside recv, similar to what's done in send
* Update malformed notification log text
* Clean up new log text a bit
* Initialize recv_buffer closer to where it's used
* Use "exit" instead of "close"
* Remove whitespace
* Remove the need for a helper method to exit the language server
* Match on Unhandled error explicitly and keep catch-all error case around