fix: when running the "discoverProjectCommand", use the Rust file's parent directory instead of the workspace folder
This is a quick fix to allow the `discoverProjectCommand` to run successfully when the user has a workspace that does not, e.g., have a `.buckconfig` defined.
(It's also probably _more correct_ to set the `pwd` of the command to the parent of the Rust file _anyways_ rather than relying on the workspace folders, which may be entirely unrelated.)
internal: Add config to specifiy lru capacities for all queries
Might help figuring out what queries should be limited by LRU by default, as currently we only limit `parse`, `parse_macro_expansion` and `macro_expand`.
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.
Beginning of MIR
This pull request introduces the initial implementation of MIR lowering and interpreting in Rust Analyzer.
The implementation of MIR has potential to bring several benefits:
- Executing a unit test without compiling it: This is my main goal. It can be useful for quickly testing code changes and print-debugging unit tests without the need for a full compilation (ideally in almost zero time, similar to languages like python and js). There is a probability that it goes nowhere, it might become slower than rustc, or it might need some unreasonable amount of memory, or we may fail to support a common pattern/function that make it unusable for most of the codes.
- Constant evaluation: MIR allows for easier and more correct constant evaluation, on par with rustc. If r-a wants to fully support the type system, it needs full const eval, which means arbitrary code execution, which needs MIR or something similar.
- Supporting more diagnostics: MIR can be used to detect errors, most famously borrow checker and lifetime errors, but also mutability errors and uninitialized variables, which can be difficult/impossible to detect in HIR.
- Lowering closures: With MIR we can find out closure capture modes, which is useful in detecting if a closure implements the `FnMut` or `Fn` traits, and calculating its size and data layout.
But the current PR implements no diagnostics and doesn't support closures. About const eval, I removed the old const eval code and it now uses the mir interpreter. Everything that is supported in stable rustc is either implemented or is super easy to implement. About interpreting unit tests, I added an experimental config, disabled by default, that shows a `pass` or `fail` on hover of unit tests (ideally it should be a button similar to `Run test` button, but I didn't figured out how to add them). Currently, no real world test works, due to missing features including closures, heap allocation, `dyn Trait` and ... so at this point it is only useful for me selecting what to implement next.
The implementation of MIR is based on the design of rustc, the data structures are almost copy paste (so it should be easy to migrate it to a possible future stable-mir), but the lowering and interpreting code is from me.
add openDocs command to context menu in VS Code extension
This adds the `openDocs` command to the VS Code context menu. I believe there are probably many user who are unaware of this command existing in the rust analyzer extension, and that this should enhance the discoverability of the command. Additionally, even if people are aware of this capability, it's helpful to have this in the context menu anyway; for example, one might forget the name of the command, or the keybinding they have assigned to it. I think that opening docs is a common enough action to warrant the extra line added to the context menu.
This makes a few other small changes as well. There are two minor style changes to increase style consistency. First, it changes the titles of the two commands that the rust analyzer extension will contribute to the context menu to title case. All standard VS Code commands that appear in the context menu are in title case. Second, it shortens the title of the `openDocs` command from `Open docs under cursor` to `Open Docs`. The implicit assumption in the standard VS Code context menu command titles is that the action applies to the symbol under the cursor: `Go to Definition`, `Find All References`, etc. Note that since these are changes to the command titles, rather than the command names themselves, these changes will not break any users' existing keybindings for these commands.
Second, this adds further restrictions to the `where` clauses of the two commands that the rust analyzer extension will contribute to the context menu, so that the two commands will appear in the context menu only when in a Rust project **and** within a Rust file. Say you have a Python or bash script inside your Rust project. Having these commands appear in the context menu when you right click a symbol in such a non-Rust file is extraneous and potentially confusing.
![demonstration](https://user-images.githubusercontent.com/6609145/219976062-b46ab21b-5753-48f5-a1da-562566cae71c.gif)
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 🤷
}
```
minor: Explicitly disable the rust-analyzer extension in untrusted workspaces
This is the default, but its always better to be explicit here + we can add a small note as to why.
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.
Rename `checkOnSave` settings to `check`
Now that flychecks can be triggered without saving the setting name doesn't make that much sense anymore. This PR renames it to just `check`, but keeps `checkOnSave` as the enabling setting.
feat: add the ability to limit the number of threads launched by `main_loop`
## Motivation
`main_loop` defaults to launch as many threads as cpus in one machine. When developing on multi-core remote servers on multiple projects, this will lead to thousands of idle threads being created. This is very annoying when one wants check whether his program under developing is running correctly via `htop`.
<img width="756" alt="image" src="https://user-images.githubusercontent.com/41831480/206656419-fa3f0dd2-e554-4f36-be1b-29d54739930c.png">
## Contribution
This patch introduce the configuration option `rust-analyzer.numThreads` to set the desired thread number used by the main thread pool.
This should have no effects on the performance as not all threads are actually used.
<img width="1325" alt="image" src="https://user-images.githubusercontent.com/41831480/206656834-fe625c4c-b993-4771-8a82-7427c297fd41.png">
## Demonstration
The following is a snippet of `lunarvim` configuration using my own build.
```lua
vim.list_extend(lvim.lsp.automatic_configuration.skipped_servers, { "rust_analyzer" })
require("lvim.lsp.manager").setup("rust_analyzer", {
cmd = { "env", "RA_LOG=debug", "RA_LOG_FILE=/tmp/ra-test.log",
"/home/jlhu/Projects/rust-analyzer/target/debug/rust-analyzer",
},
init_options = {
numThreads = 4,
},
settings = {
cachePriming = {
numThreads = 8,
},
},
})
```
## Limitations
The `numThreads` can only be modified via `initializationOptions` in early initialisation because everything has to wait until the thread pool starts including the dynamic settings modification support.
The `numThreads` also does not reflect the end results of how many threads is actually created, because I have not yet tracked down everything that spawns threads.
Use diagnostic code as link to full message
fixes#13823 by adding a vscode setting that will keeping the existing diagnostic code and use it as a link to the full compiler error message.
While I was there I also fixed `index` to fallback to `rendered.length` to make the previewRustcOutput feature work.
feat: Add an option to hide adjustment hints outside of `unsafe` blocks and functions
As the title suggests: this PR adds an option (namely `rust-analyzer.inlayHints.expressionAdjustmentHints.hideOutsideUnsafe`) that allows to hide adjustment hints outside of `unsafe` blocks and functions:
![2022-12-21_23-11](https://user-images.githubusercontent.com/38225716/208986376-d607de62-8290-4e16-b7fe-15b762dc5f60.png)
Requested by `@BoxyUwU` <3
Support multiple targets for checkOnSave (in conjunction with cargo 1.64.0+)
This PR adds support for the ability to pass multiple `--target` flags when using
`cargo` 1.64.0+.
## Questions
I needed to change the type of two configurations options, but I did not plurialize the names to
avoid too much churn, should I ?
## Zulip thread
https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/Issue.2013282.20.28supporting.20multiple.20targets.20with.201.2E64.2B.29
## Example
To see it working, on a macOS machine:
```sh
$ cd /tmp
$ cargo new cargo-multiple-targets-support-ra-test
$ cd !$
$ mkdir .cargo
$ echo '
[build]
target = [
"aarch64-apple-darwin",
"x86_64-apple-darwin",
]
' > .cargo/config.toml
$ echo '
fn main() {
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
{
let a = std::fs::read_to_string("/tmp/test-read");
}
#[cfg(all(target_arch = "x86_64", target_os = "macos"))]
{
let a = std::fs::read_to_string("/tmp/test-read");
}
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
{
let a = std::fs::read_to_string("/tmp/test-read");
}
}
' > src/main.rs
# launch your favorite editor with the version of RA from this PR
#
# You should see warnings under the first two `let a = ...` but not the third
```
## Screen
![Two panes of a terminal emulator, on the left pane is the main.rs file described above, with warnings for the first two let a = declaration, on the right pane is a display of the .cargo/config.toml, an ls of the current files in the directory and a call to cargo build to show the same warnings as in the editor on the left pane](https://user-images.githubusercontent.com/7951708/192122707-7a00606a-e581-4534-b9d5-b81c92694e8e.png)
Helps with #13282
feat: add config for inserting must_use in `generate_enum_as_method`
Should fix#13312
Didn't add a test because I was not sure on how to add test for a specific configuration option, tried to look for the usages for other `AssistConfig` variants but couldn't find any in `tests`. If there is a way to test this, do point me towards it.
I tried to extract the formatting string as a common `template_string` and only have if-else for that, but it didn't compile :(
Also it seems these tests are failing:
```
test config::tests::generate_config_documentation ... FAILED
test config::tests::generate_package_json_config ... FAILED
```
Can you also point me to how to correct these 😅 ( I guess there is some command to automatically generate these? )
Implement invocation strategy config
Fixes https://github.com/rust-lang/rust-analyzer/issues/10793
This allows to change how we run build scripts (and `checkOnSave`), exposing two configs:
- `once`: run the specified command once in the project root (the working dir of the server)
- `per_workspace`: run the specified command per workspace in the corresponding workspace
This also applies to `checkOnSave` likewise, though `once_in_root` is useless there currently, due to https://github.com/rust-lang/cargo/issues/11007
VS Code problem matcher are restricted to be static "regexes". You can't
create a problem matcher dynamically, and you can't use custom code in
lieu of problem matcher.
This creates a problem for rust/cargo compiler errors. They use paths
relative to the root of the Cargo workspace, but VS Code doesn't
necessary know where that root is.
Luckily, there's a way out: our current problem matcher is defined like
this:
"fileLocation": [ "autoDetect", "${workspaceRoot}" ],
That means that relative pahts would be resoleved relative to workspace
root. VS Code allows to specify a command inside `${}`. So we can plug
custom logic there to fetch Cargo's workspace root!
And that's exactly what this PR is doing!
Add a new configuration settings to set env vars when running cargo, rustc, etc. commands: cargo.extraEnv and checkOnSave.extraEnv
It can be extremely useful to be able to set environment variables when rust-analyzer is running various cargo or rustc commands (such as `cargo check`, `cargo --print cfg` or `cargo metadata`): users may want to set custom `RUSTFLAGS`, change `PATH` to use a custom toolchain or set a different `CARGO_HOME`.
There is the existing `server.extraEnv` setting that allows env vars to be set when the rust-analyzer server is launched, but using this as the recommended mechanism to also configure cargo/rust has some drawbacks:
- It convolutes configuring the rust-analyzer server with configuring cargo/rustc (one may want to change the `PATH` for cargo/rustc without affecting the rust-analyzer server).
- The name `server.extraEnv` doesn't indicate that cargo/rustc will be affected but renaming it to `cargo.extraEnv` doesn't indicate that the rust-analyzer server would be affected.
- To make the setting useful, it needs to be dynamically reloaded without requiring that the entire extension is reloaded. It might be possible to do this, but it would require the client communicating to the server what the overwritten env vars were at first launch, which isn't easy to do.
This change adds two new configuration settings: `cargo.extraEnv` and `checkOnSave.extraEnv` that can be used to change the environment for the rust-analyzer server after launch (thus affecting any process that rust-analyzer invokes) and the `cargo check` command respectively. `cargo.extraEnv` supports dynamic changes by keeping track of the pre-change values of environment variables, thus it can undo changes made previously before applying the new configuration (and then requesting a workspace reload).
Allow configuration of annotation location.
I've added the ability to configure where lens annotations render relevant to the item they describe. Previously, these would render directly above the line the item is declared on. Now, there is the ability to render these annotations above the entire item (including doc comments, and attributes).
The names of the config options are up for debate, I did what seemed best to me but if anyone has better ideas let me know.
This is my first contribution so if I've missed anything please let me know.
Here's a preview of what the new option looks like:
<img width="577" alt="Screen Shot 2022-09-11 at 10 39 51 PM" src="https://user-images.githubusercontent.com/33100798/189570298-b4fcbf9c-ee49-4b79-aae6-1037ae4f26af.png">
closes https://github.com/rust-lang/rust-analyzer/issues/13218
Remove the toggleInlayHints command from VSCode
Inlay hints are no longer something specifc to r-a as it has been upstreamed into the LSP, we don't have a reason to give the config for this feature special treatment in regards to toggling. There are plenty of other options out there in the VSCode marketplace to create toggle commands/hotkeys for configurations in general which I believe we should nudge people towards instead.
Previously, annotations would only appear above the name of an item (function signature, struct declaration, etc).
Now, rust-analyzer can be configured to show annotations either above the name or above the whole item (including doc comments and attributes).
Inlay hints are no longer something specifc to r-a as it has been
upstreamed into the LSP, we don't have a reason to give the config
for this feature special treatment in regards to toggling. There are
plenty of other options out there in the VSCode marketplace to create
toggle commands/hotkeys for configurations in general which I believe
we should nudge people towards instead.
Move empty diagnostics workaround back into the server
This only touches on the diagnostics in one place instead of multiple as was previously done, since all published diagnostics will go through this code path anyways.
Closes https://github.com/rust-lang/rust-analyzer/issues/13130
Remove auto-config patching from the VSCode client
This was introduced 4 months ago when we drastically changed the config keys. I'd like to remove this given I always felt uneasy doing edits to a users config from within r-a, and by now most if not all users should've swapped to a new enough version of r-a that should've updated their configs.
The extension will continue to work fine even with the outdated keys afterwards since we still do patching server side as well, and that one we'll have to support for quite some more time (if not until a proper 1.0 release where I assume we can allow ourselves some more user facing breakage)
(There also might've been a small bug in here that prevented users with certain outdated keys to prevent them from enabling certain keys for some reason)