Show placeholder while run command gets runnables from server
This PR fixes a UI annoyance in the VS Code extension when working in large codebases where rust-analyzer can take a few moments to interact with the server. Scenario:
1. Invoke "rust-analyzer: Run" from the command palette or hotkey
2. Quickly start typing to filter the list (or press Enter to accept the last runnable)
We often do this quickly from muscle memory without waiting to see the picker. The picker often takes several seconds to come up, causing us to type garbage into the currently open editor.
Fix:
Show a placeholder item before we call out to the server.
![image](https://github.com/rust-lang/rust-analyzer/assets/16928427/09de6a1c-6f3c-4d29-8031-ba4baeb43282)
Selecting this item does nothing so if the user accidentally hits Enter nothing happens.
The list is populated and the placeholder dismissed when the actual runnables are retrieved. From here the behavior is the same as before.
![image](https://github.com/rust-lang/rust-analyzer/assets/16928427/837c7dfc-c060-4d68-bbf6-df8aa3101b78)
editor/code: add option to suppress error notifications
Fixes https://github.com/rust-lang/rust-analyzer/issues/14193
- Added the `rust-analyzer.showRequestFailedErrorNotification` configuration option, which defaults to `true`
- If `rust-analyzer.showRequestFailedErrorNotification` is set to `true`, the current behavior is preserved.
- If `rust-analyzer.showRequestFailedErrorNotification` is set to `false`, no error toasts will be displayed for any of the failed requests caused by panics in r-a. This _only_ applies to events that are triggered "implicitly", such as `textDocument/hover`.
To test this, you can manually introduce a panic in one of the language server LSP handlers for non-command events. I added an explicit `panic!()` in the `textDocument/hover` event handler:
#### `rust-analyzer.showRequestFailedErrorNotification` set to `true` (default)
[2023-11-07 17-17-48.webm](https://github.com/rust-lang/rust-analyzer/assets/1665677/d0408ab8-79d1-42cf-a4e7-94e99d9783ec)
#### `rust-analyzer.showRequestFailedErrorNotification` set to `false`
[2023-11-07 17-16-49.webm](https://github.com/rust-lang/rust-analyzer/assets/1665677/0496d8d0-fb53-4bc6-a279-1a47f412dbdb)
Displaying local instead of web docs can have many benefits:
- the web version may have different features enabled than locally selected
- the standard library may be a different version than is available online
- the user may not be online and therefore cannot access the web documentation
- the documentation may not be available online at all, for example because it
is for a new feature in a library the user is currently developing
If the documentation is not available locally, the extension still falls back to
the web version.
According to the VS Code documentation, the vscode.open command opens the URL
_in the editor_ (https://code.visualstudio.com/api/references/commands).
However, in reality, it seems to do so only for file:// URLs, falling back to
other applications for other URL schemes (at least for HTTP/HTTPS).
Until now, the URL to the documentation was always HTTP based, so using the
vscode.open command was perfectly fine. However, displaying local documentation
will be supported from now on (see next commit). Local documentation is not
HTTP-based, but instead addressed via a file:// URL. The file URL would
therefore be opened in VS Code instead of in the browser — this is definitely
not what the user wants.
Therefore, the vscode.env.openExternal function is used instead, this function
never opens the URL in VS Code.
Increase the buffer size for discover project command
The default value for maxBuffer is 1 MiB[1]. If the discover project command returns stdout or stderr that is greater than 1 MiB, the extension would error with "RangeError: stderr maxBuffer length exceeded".
Set the default value for maxBuffer to 10 MiB for project discovery.
[1] https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback
The default value for maxBuffer is 1 MiB[1]. If the discover project
command returns stdout or stderr that is greater than 1 MiB, the
extension would error with "RangeError: stderr maxBuffer length
exceeded".
Set the default value for maxBuffer to 10 MiB for project discovery.
[1] https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback
Use the warning color when rust-analyzer is stopped
If the rust-analyzer server isn't running, we can't do much. Treat this state as a warning color, so it's more obvious.
Previously, clicking 'rust-analyzer' would stop the server
entirely. This was easy to do accidentally, and then the user has to
wait for the server to start up again.
Add Cargo-style project discovery for Buck and Bazel Users
This feature requires the user to add a command that generates a `rust-project.json` from a set of files. Project discovery can be invoked in two ways:
1. At extension activation time, which includes the generated `rust-project.json` as part of the linkedProjects argument in `InitializeParams`.
2. Through a new command titled "rust-analyzer: Add current file to workspace", which makes use of a new, rust-analyzer-specific LSP request that adds the workspace without erasing any existing workspaces. Note that there is no mechanism to _remove_ workspaces other than "quit the rust-analyzer server".
Few notes:
- I think that the command-running functionality _could_ merit being placed into its own extension (and expose it via extension contribution points) to provide build-system idiomatic progress reporting and status handling, but I haven't (yet) made an extension that does this nor does Buck expose this sort of functionality.
- This approach would _just work_ for Bazel. I'll try and get the tool that's responsible for Buck integration open-sourced soon.
- On the testing side of things, I've used this in around my employer's Buck-powered monorepo and it's a nice experience. That being said, I can't think of an open-source repository where this can be tested in public, so you might need to trust me on this one.
I'd love to get feedback on:
- Naming of LSP extensions/new commands. I'm not too pleased with how "rust-analyzer: Add current file to workspace" is named, in that it's creating a _new_ workspace. I think that this command being added should be gated on `rust-analyzer.discoverProjectCommand` on being set, so I can add this in sequent commits.
- My Typescript. It's not particularly good.
- Suggestions on handling folders with _both_ Cargo and non-Cargo build systems and if I make activation a bit better.
(I previously tried to add this functionality entirely within rust-analyzer-the-LSP server itself, but matklad was right—an extension side approach is much, much easier.)
This feature requires the user to add a command that generates a
`rust-project.json` from a set of files. Project discovery can be invoked
in two ways:
1. At extension activation time, which includes the generated
`rust-project.json` as part of the linkedProjects argument in
InitializeParams
2. Through a new command titled "Add current file to workspace", which
makes use of a new, rust-analyzer specific LSP request that adds
the workspace without erasing any existing workspaces.
I think that the command-running functionality _could_ merit being
placed into its own extension (and expose it via extension contribution
points), if only provide build-system idiomatic progress reporting and
status handling, but I haven't (yet) made an extension that does this.
fix: Suppress extra indent after the end of field and function chains
(spurred on by <https://github.com/rust-lang/rust-analyzer/issues/4182#issuecomment-671275652>)
Caveat that this doesn't work for after tail expressions, although there shouldn't be anything after those anyways.
This also complicates when to reload the language configuration by nature of now always having a language configuration applicable.
Examples of indentation fixes:
```rs
fn main() {
println!("Hello!"); // < enter here!
// ... indents down here
fs::read_to_string("soup") // < enter here!
// ... still indents down here :(
.map(|_| ())
.map(|_| ()) // < enter here!
// ... still indents down here :D
.map_err(|_| ())
.unwrap(); // < enter here!
// ... indents down here :D
// ... and subsequent enters stay at the same indent
0.0f64
.to_radians()
.to_radians()
.to_radians() // force semi on a new line
; // < enter here!
// ... indents down here :D
}
fn tail_end() -> i32 {
0i32.wrapping_abs()
.wrapping_abs()
.wrapping_abs()
.wrapping_abs() // < enter here!
// ... still indents here 🤷
}
```
Use ANSI control characters to display text decorations matching the
VScode terminal theme, and strip them out when providing text content
for rustc diagnostics.
This adds the small `anser` library to parse the control codes, and it
also supports HTML output so it should be fairly easy to switch to a
rendered HTML/webview implementation if desired.