fix: ensure there are no cycles in the source_root_parent_map
See #17409
We can view the connections between roots as a graph. The problem is that this graph may contain cycles, so when adding edges, it is necessary to check whether it will lead to a cycle.
Since we ensure that each node has at most one outgoing edge (because each SourceRoot can have only one parent), we can use a disjoint-set to maintain the connectivity between nodes. If an edge’s two nodes belong to the same set, they are already connected.
Additionally, this PR includes the following three changes:
1. Removed the workaround from #17409.
2. Added an optimization: If `map.contains_key(&SourceRootId(*root_id as u32))`, we can skip the current loop iteration since we have already found its parent.
3. Modified the inner loop to iterate in reverse order with `roots[..idx].iter().rev()` at line 319. This ensures that if we are looking for the parent of `a/b/c`, and both `a` and `a/b` meet the criteria, we will choose the longer match (`a/b`).
Term search: new tactic for associated item constants
New tactic to cover some more exotic cases that started bothering me.
Associated constants seem to be common in [axum](806bc26e62/examples/readme/src/main.rs (L53)).
feat: add space after specific keywords in completion
fix#17428.
When completing some specific keywords, it would be convenient if r-a could automatically add a space afterwards.
This PR implements this feature for the following keywords:
- Visibility: `pub`, `pub(crate)`, `pub(super)`, `pub(in xxx)`
- Pattern: `ref` / `mut`
- Others: `unsafe` / `for` / `where`
fix: handle character boundaries for wide chars in extend_selection
fix#17420.
When calling 'extend_selection' within a string, r-a attempts to locate the current word at the cursor. This is done by finding the first char before the cursor which is not a letter, digit, or underscore.
The position of this character is referred to as `start_idx`, and the word is considered to start from `start_idx + 1`. However, for wide characters, `start_idx + 1` is not character boundaries, which leading to panic. We should use `ceil_char_boundary` to ensure that the idx is always on character boundaries.
fix: Only show unlinked-file diagnostic on first line during startup
This partially reverts #17350, based on the feedback in #17397.
If we don't have an autofix, it's more annoying to highlight the whole file. This autofix heuristic fixes the diagnostic being overwhelming during startup.
docs: document omission heuristics for parameter inlay hints
These are not currently documented and could cause users to think that their rust-analyzer configuration is broken.
Partially addresses #17433.
refactor: Prefer plain trait definitions over macros for impl_intern_value_trivial
`impl_intern_value_trivial` can be defined with a trait directly, so prefer that over a macro definition.
This partially reverts #17350, based on the feedback in #17397.
If we don't have an autofix, it's more annoying to highlight the whole line.
This heuristic fixes the diagnostic overwhelming the user during startup.
Allow rust-project.json to include arbitrary shell commands for runnables
This is a follow-up on #16135, resolving the feedback raised :)
Allow rust-project.json to include shell runnables, of the form:
```
{
"build_info": {
"label": "//project/foo:my-crate",
"target_kind": "bin",
"shell_runnables": [
{
"kind": "run",
"program": "buck2",
"args": ["run", "//project/foo:my-crate"]
},
{
"kind": "test_one",
"program": "test_runner",
"args": ["--name=$$TEST_NAME$$"]
}
]
}
}
```
If these runnable configs are present for the current crate in rust-project.json, offer them as runnables in VS Code.
This PR required some boring changes to APIs that previously only handled cargo situations. I've split out these changes as commits labelled 'refactor', so it's easy to see the interesting changes.
feat: show type bounds from containers when hovering on functions
fix#12917.
### Changes
1. Added Support for displaying the container and type bounds from it when hovering on functions with generic types.
2. Added a user config to determine whether to display container bounds (enabled by default).
3. Added regression tests.
4. Simplified and refactored `hir/display.rs` to improve readability.
fix: ensure that the parent of a SourceRoot cannot be itself
fix#17378.
In `FileSetConfig.map`, different roots might be mapped to the same `root_id` due to deduplication in `ProjectFolders::new`:
```rust
// Example from rustup
/Users/roife/code/rustup/target/debug/build/rustup-863a063426b56c51/out
/Users/roife/code/rustup
```
In `source_root_parent_map`, r-a might encounter paths where their SourceRootId (i.e. `root_id`) is identical, yet one the them is the parent of the another. This situation can cause the `root_id` to be its own parent, potentially leading to an infinite loop.
This PR resolves such cases by adding a check.
feat: TOML based config for rust-analyzer
> Important
>
> We don't promise _**any**_ stability with this feature yet, any configs exposed may be removed again, the grouping may change etc.
# TOML Based Config for RA
This PR ( addresses #13529 and this is a follow-up PR on #16639 ) makes rust-analyzer configurable by configuration files called `rust-analyzer.toml`. Files **must** be named `rust-analyzer.toml`. There is not a strict rule regarding where the files should be placed, but it is recommended to put them near a file that triggers server to start (i.e., `Cargo.{toml,lock}`, `rust-project.json`).
## Configuration Types
Previous configuration keys are now split into three different classes.
1. Client keys: These keys only make sense when set by the client (e.g., by setting them in `settings.json` in VSCode). They are but a small portion of this list. One such example is `rust_analyzer.files_watcher`, based on which either the client or the server will be responsible for watching for changes made to project files.
2. Global keys: These keys apply to the entire workspace and can only be set on the very top layers of the hierarchy. The next section gives instructions on which layers these are.
3. Local keys: Keys that can be changed for each crate if desired.
### How Am I Supposed To Know If A Config Is Gl/Loc/Cl ?
#17101
## Configuration Hierarchy
There are 5 levels in the configuration hierarchy. When a key is searched for, it is searched in a bottom-up depth-first fashion.
### Default Configuration
**Scope**: Global, Local, and Client
This is a hard-coded set of configurations. When a configuration key could not be found, then its default value applies.
### User configuration
**Scope**: Global, Local
If you want your configurations to apply to **every** project you have, you can do so by setting them in your `$CONFIG_DIR/rust-analyzer/rust-analyzer.toml` file, where `$CONFIG_DIR` is :
| Platform | Value | Example |
| ------- | ------------------------------------- | ---------------------------------------- |
| Linux | `$XDG_CONFIG_HOME` or `$HOME`/.config | /home/alice/.config |
| macOS | `$HOME`/Library/Application Support | /Users/Alice/Library/Application Support |
| Windows | `{FOLDERID_RoamingAppData}` | C:\Users\Alice\AppData\Roaming |
### Client configuration
**Scope**: Global, Local, and Client
Previously, the only way to configure rust-analyzer was to configure it from the settings of the Client you are using. This level corresponds to that.
> With this PR, you don't need to port anything to benefit from new features. You can continue to use your old settings as they are.
### Workspace Root Configuration
**Scope**: Global, Local
Rust-analyzer already used the path of the workspace you opened in your Client. We used this information to create a configuration file that won't affect your other projects and define global level configurations at the same time.
### Local Configuration
**Scope**: Local
You can also configure rust-analyzer on a crate level. Although it is not an error to define global ( or client ) level keys in such files, they won't be taken into consideration by the server. Defined local keys will affect the crate in which they are defined and crate's descendants. Internally, a Rust project is split into what we call `SourceRoot`s. This, although with exceptions, is equal to splitting a project into crates.
> You may choose to have more than one `rust-analyzer.toml` files within a `SourceRoot`, but among them, the one closer to the project root will be
Add preference modifier for workspace-local crates when using auto import.
`@joshka` pointed out some odd behavior of auto import ordering. It doesn't seem that the current heuristics were applying any sort of precedence to imports from the workspace. I've went ahead and added that.
I hope to get some feedback on the modifier numbers here. I just went with something that felt like it balanced giving more power to workspace crates without completely ignoring relative path distance.
closes https://github.com/rust-lang/rust-analyzer/issues/17303
fix: do not resolve prelude within block modules
fix#17338 (continuing from #17251).
In #17251, we injected preludes into non-top-level modules, which leading to r-a to directly resolve names in preludes in block modules. This PR fix it by checking whether the module is a pseudo-module introduced by blocks. (similar to what we do for extern preludes)
Changed package.json so vscode extension settings have submenus
There are a lot of options that are a part of rust-analyzer, sometimes it can be hard to find an option that you are looking for. To fix this I have put all configurations into categories based on their names. I have also changed the schema in `crates/rust-analyzer/src/config.rs` to reflect this.
Currently for each generated entry the title is redeclared, this does function but I am prepared to change this if it is a problem.
Currently, rust-analyzer highlights the entire region when a `cfg` is
inactive (e.g. `#[cfg(windows)]` on a Linux machine). However,
unlinked files only highlight the first three characters of the file.
This was introduced in #8444, but users have repeatedly found
themselves with no rust-analyzer support for a file and unsure
why (see e.g. #13226 and the intentionally prominent pop-up added in
PR #14366).
(Anecdotally, we see this issue bite our users regularly, particularly
people new to Rust.)
Instead, highlight the entire inactive file, but mark it as all as
unused. This allows users to hover and run the quickfix from any line.
Whilst this is marginally more prominent, it's less invasive than a
pop-up, and users do want to know why they're getting no rust-analyzer
support in certain files.