10406: internal: Restructure syntax element highlighting into node and token branches r=Veykril a=Veykril
Gets rid of all the unseemly unwraps
bors r+
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
10398: Give defaultLibrary semantic token modifier to items from standard library r=Veykril a=lhvy
Fixes#8999, fixes#2155
`builtInCrates` could be an alternate name to `defaultLibrary`, which one is better?
> P.S. I'm participating in [Hacktoberfest 2021](https://hacktoberfest.digitalocean.com/). If this PR is up to standard and merged, I'd appreciate if the `hacktoberfest-accepted` label could be added. Thanks!
Co-authored-by: lhvy <me@lhvy.dev>
Co-authored-by: Lucas <me@lhvy.dev>
10400: fix: fix format string highlighting for `todo!` and `unimplemented!` r=jonas-schievink a=jonas-schievink
Part of https://github.com/rust-analyzer/rust-analyzer/issues/10394
These macros require us to see through the `const_format_args!` invocation the panic macros generate, for that we have to add it to our supported built-in macros.
I've also made the macros in the test `#[macro_export]` (turns out they didn't all resolve correctly before this), which changes the output slightly.
bors r+
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
10399: minor: don't drop binders when doing autoderef r=lnicola a=iDawer
This fixes#10396 panic introduced in #10373
Co-authored-by: Dawer <7803845+iDawer@users.noreply.github.com>
10389: fix: use the right `HirFileId` when expanding macros in fn parameters r=Veykril a=SkiFire13
Fixes#10388
Co-authored-by: Giacomo Stevanato <giaco.stevanato@gmail.com>
10181: Begining of lsif r=HKalbasi a=HKalbasi
This PR adds a `lsif` command to cli, which can be used as `rust-analyzer lsif /path/to/project > dump.lsif`. It now generates a valid, but pretty useless lsif (only supports folding ranges). The propose of this PR is to discussing about the structure of lsif generator, before starting anything serious.
cc `@matklad` #8696#3098
Co-authored-by: hamidreza kalbasi <hamidrezakalbasi@protonmail.com>
10385: Make `extern crate test;` work r=jonas-schievink a=jonas-schievink
This implements support for dependencies that are not added to the extern prelude of a crate, and add the `test` crate from the sysroot as such a dependency.
This does mean we now index `test` on startup, but I didn't notice much of a difference (and also, r-a can be used while it is still indexing).
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/6714
bors r+
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
10375: minor: Use SmallVec<[_; 1]> in `descend_into_macros_impl` r=Veykril a=Veykril
A lot of descends don't actually descend in which case we don't wanna allocate
bors r+
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
Consider these expples
{ 92 }
async { 92 }
'a: { 92 }
#[a] { 92 }
Previously the tree for them were
BLOCK_EXPR
{ ... }
EFFECT_EXPR
async
BLOCK_EXPR
{ ... }
EFFECT_EXPR
'a:
BLOCK_EXPR
{ ... }
BLOCK_EXPR
#[a]
{ ... }
As you see, it gets progressively worse :) The last two items are
especially odd. The last one even violates the balanced curleys
invariant we have (#10357) The new approach is to say that the stuff in
`{}` is stmt_list, and the block is stmt_list + optional modifiers
BLOCK_EXPR
STMT_LIST
{ ... }
BLOCK_EXPR
async
STMT_LIST
{ ... }
BLOCK_EXPR
'a:
STMT_LIST
{ ... }
BLOCK_EXPR
#[a]
STMT_LIST
{ ... }
Originally we tried to maintain the invariant that `{}` always match.
That is, that in the parse tree the pair of corresponding `{}` is always
first and last tokens of some nodes.
We had the code to validate that, but apparently it's been broken for
**years** since we introduced tokens/nodes split. Fixing it now makes
some tests fail.
It's unclear if we want to keep this invariant: there's a strong
motivation for breaking it in the following case:
```
use std::{ // unclosed paren
fn main() {
}
} // don't actually want to pair up this with the one from `use`
```
So let's fix the code, but disable it for the time being
Previously we swapped to events in the buffer, but that might be wrong
if there aer `forward_parent` links pointing to the swapped-out node.
Let's do the same via parent links instead, keeping the nodes in place
10334: Give rustfmt spawn error context. r=jonas-schievink a=aDotInTheVoid
This mean if you misconfigure to
```json
{
"rust-analyzer.rustfmt.overrideCommand": [
"./nonono"
]
}
```
The error message is
```
[Error - 17:54:33] Request textDocument/formatting failed.
Message: Failed to spawn "./nonono"
Code: -32603
```
instead of
```
[Error - 17:56:12] Request textDocument/formatting failed.
Message: No such file or directory (os error 2)
Code: -32603
```
I'm not sure how to test this, or if it needs a test.
Co-authored-by: Nixon Enraght-Moony <nixon.emoony@gmail.com>
10105: RfC: Use `todo!()` instead of `()` for missing fields r=jonas-schievink a=jo-so
Most commonly a field of a struct can be initialized with its default value than an empty tuple.
Co-authored-by: Jörg Sommer <joerg@jo-so.de>
10332: minor: Allow overwriting RUST_BACKTRACE for the server manually r=jonas-schievink a=Veykril
Trying to figure out why we aren't getting backtraces for windows builds from CI, this let's one set the backtraces to `FULL`
Might be cc https://github.com/rust-lang/rust/issues/87481
bors r+
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
10284: internal: definition based hover functions r=Veykril a=HKalbasi
This is part of #10181 but since it is blocked and `hover.rs` is moving quickly so will cause conflicts, I submitted this PR.
This PR extract some parts of `hover` to `find_definition` (maybe this need to be moved to some other file?) and `hover_for_definition`, with those functions I will be able to calculate definition of every token, and calculate hover (and probably other queries) for each definition only once.
Co-authored-by: hamidreza kalbasi <hamidrezakalbasi@protonmail.com>
The code here is intentionally dense and does exactly what is written.
Explaining semantic difference between Rust 2015 and 2018 doesn't help
with understanding syntax. Better to just add more targeted tests.
With this patch, in these examples
```rust
fn main() {
"⊞$0";
}
```
```rust
struct S {
д$0 u8
}
```
entering ':' character in `$0` places shouldn't cause panics.
10257: assists: turn while into loop r=Veykril a=agluszak
Implements an assist to turn a `while` loop into a `loop` loop, as requested in #10214.
I'm not sure sure what the guidelines are regarding naming assists convert_x_to_y vs replace_x_with_y.
This is my first commit to rust-analyzer :D Thank you `@matklad` for your awesome Explaining rust-analyzer series <3
Closes#10214
Co-authored-by: Andrzej Głuszak <gluszak.andrzej@gmail.com>
# This is the 1st commit message:
add multi-token mappings for hover
# The commit message #2 will be skipped:
# make fallback an Option instead of vec
# The commit message #3 will be skipped:
# fix indentation
10204: feat: Show the type of what is being dereferenced in a deref expression. r=theo-lw a=theo-lw
Addresses issue #10106.
In-progress - I'm trying to figure out why `hover_deref_expr_with_coercion` is failing.
Co-authored-by: Teddy_Wang <wangtheo662@gmail.com>
10230: fix: fix expansion order for fn-like macros and attributes in token descending r=Veykril a=Veykril
Second attempt(now with a test 🎉).
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/10115
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
10213: minor: Improve resilience of match checking r=flodiebold a=iDawer
In bug condition the match checking strives to recover giving false no-error diagnostic.
Suggested in https://github.com/rust-analyzer/rust-analyzer/pull/9105#discussion_r644656085
Co-authored-by: Dawer <7803845+iDawer@users.noreply.github.com>
Should fix#10090, #10046, #10179.
This is only a workaround, but the proper fix requires some bigger
refactoring (also related to fixing #10058), and this at least prevents
the crash.
10177: fix: Treat path dependencies like workspace members r=jonas-schievink a=jonas-schievink
Closes https://github.com/rust-analyzer/rust-analyzer/issues/9070
Fixes diagnostics not showing up in path dependencies.
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
The generated code with `()` doesn't compile in most of the cases. To signal
the developer there's something to do, fill in `todo!()`.
Because the file *missing_fields.rs* contains the string `todo!()` it needs
an exception for the test *check_todo*.
10152: feat: Add completion for raw identifiers r=matklad a=nabakin
![rust_analyzer_pr](https://user-images.githubusercontent.com/894305/132110362-c21b713d-acaf-4a6d-9749-ff812172cbce.gif)
Adds support for valid Rust completion of raw identifiers.
Previously, code completion of fields made via raw identifiers would not re-insert those raw identifiers, resulting in invalid Rust code. Now, code completion of fields made via raw identifiers do re-insert those raw identifiers, resulting in valid Rust code.
The same is true for all code completion instances for fields and compatible Rust identifiers.
Co-authored-by: Blake Wyatt <894305+nabakin@users.noreply.github.com>
10154: feat: Complete `#![recursion_limit = "N"]` instead of `#![recursion_limit = N]` r=lnicola a=hkmatsumoto
Currently ra emits `#![recursion_limit = 128]`, but this should rather be `#![recursion_limit = "128"]`
Co-authored-by: Hirochika Matsumoto <git@hkmatsumoto.com>
FragmentKind played two roles:
* entry point to the parser
* syntactic category of a macro call
These are different use-cases, and warrant different types. For example,
macro can't expand to visibility, but we have such fragment today.
This PR introduces `ExpandsTo` enum to separate this two use-cases.
I suspect we might further split `FragmentKind` into `$x:specifier` enum
specific to MBE, and a general parser entry point, but that's for
another PR!
10146: fix: use placeholder as default type in `Generate function` and `Extract into function`. r=matklad a=iDawer
Closes#10123
Co-authored-by: Dawer <7803845+iDawer@users.noreply.github.com>
10139: Fix replacing for loops over ranges with for_each. r=yotamofek a=yotamofek
Previously, the assist would turn this:
```rust
for x in 0..92 {
...
}
```
into the syntactically incorrect code below:
```rust
0..92.for_each(|x| ...)
```
This fixes the assist by parenthesizing range expressions.
Co-authored-by: Yotam Ofek <yotam.ofek@gmail.com>
9954: feat: Show try operator propogated types on ranged hover r=matklad a=Veykril
Basically this just shows the type of the inner expression of the `?` expression as well as the type of the expression that the `?` returns from:
![Code_wIrCxMqLH9](https://user-images.githubusercontent.com/3757771/130111025-f7ee0742-214a-493b-947a-b4a671e4be92.png)
Unless both of these types are `core::result::Result` in which case we show the error types only.
![Code_Xruw5FCBNI](https://user-images.githubusercontent.com/3757771/130111024-f9caef82-92e4-4070-b3dd-f2ff9e5d87a9.png)
If both types are `core::option::Option` with different type params we do not show this special hover either as it would be pointless(instead fallback to default type hover)
Very much open to changes to the hover text here(I suppose we also want to show the actual type of the `?` expression, that is its output type?).
Fixes#9931
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
When dealing with proc macros, there are two very different kinds of
errors:
* first, usual errors of "proc macro panicked on this particular input"
* second, the proc macro server might day if the user, eg, kills it
First kind of errors are expected and are a normal output, while the
second kind are genuine IO-errors.
For this reason, we use a curious nested result here: `Result<Result<T,
E1>, E2>` pattern, which is 100% inspired by http://sled.rs/errors.html
10095: internal: Augment panic context when resolving path r=jonas-schievink a=jonas-schievink
Should help with debugging https://github.com/rust-analyzer/rust-analyzer/issues/10084 and similar issues.
Might have a perf impact since the string is created on every function call.
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
10097: fix: Allow inherent impls for arrays r=jonas-schievink a=jonas-schievink
Part of https://github.com/rust-analyzer/rust-analyzer/issues/9992 (method resolution of these methods still does not work)
bors r+
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
10091: fix: fix "disjunction in conjunction" panic r=matklad a=jonas-schievink
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/10073
The DNF construction code created expressions that were combined in a way that made us "forget" to make their contents valid DNF again. This PR fixes that by flattening nested `any(any())` and `all(all())` predicates. There was also a typo that led to a redundant call to `make_nnf` instead of the correct recursive call to `make_dnf` (but this didn't seem to break/fix anything).
This also adds some light property testing, though I'm not really sure this is the best way to do it.
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
10092: feat: Improve `extract_struct_from_enum_variant` output r=matklad a=DropDemBits
Improves the struct generated by `extract_struct_from_enum_variant`.
Summary of changes:
- Indent the generated struct and enum to the same indent level
- Preserve comments & attributes from the enum variant (something I missed when doing the same thing for the variant fields)
- Use enum's visibility for fields without any visibility, instead of filling it in with `pub`
Co-authored-by: DropDemBits <r3usrlnd@gmail.com>
10076: Use struct init shorthand when applicable in fill struct fields assist r=matklad a=nathanwhit
This PR tweaks the fill struct fields assist to use the struct init shorthand when a local variable with a matching name and type is in scope.
For example:
```rust
struct Foo {
a: usize,
b: i32,
c: char,
}
fn main() {
let a = 1;
let b = 2;
let c = 3;
let foo = Foo { <|> };
}
```
Before we would insert
```rust
Foo {
a: (),
b: (),
c: (),
}
```
now we would insert
```rust
Foo {
a,
b,
c: ()
}
```
Co-authored-by: nathan.whitaker <nathan.whitaker01@gmail.com>
closes#9922
Turned out to be trivial after preliminary refactor.
The intended behavior is that we schedule cache priming once ws become
quiescent (that is, we fully load cargo project), and we continue to
rschedule it until it completes (priming might get cancelled by user
typing into a file).
Group related stuff together, use only on path for parsing extern blocks
(they actually have modifiers).
Perhaps we should get rid of items_without_modifiers altogether? Better
to handle these kinds on diagnostics in validation layer...
10005: Extend `CargoConfig.unset_test_crates` r=matklad a=regexident
This is to allow for efficiently disabling `#[cfg(test)]` on all crates (by passing `unset_test_crates: UnsetTestCrates::All`) without having to first load the crate graph, when using rust-analyzer as a library.
(FYI: The change doesn't seem to be covered by any existing tests.)
Co-authored-by: Vincent Esche <regexident@gmail.com>
10080: internal: don't shut up the compiler when it says the code's buggy r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
10066: internal: improve compile times a bit r=matklad a=matklad
I wanted to *quickly* remove `smol_str = {features = "serde"}`, and figured out that the simplest way to do that is to replace our straightforward proc macro serialization with something significantly more obscure.
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
9970: feat: Implement attribute input token mapping, fix attribute item token mapping r=Veykril a=Veykril
![image](https://user-images.githubusercontent.com/3757771/130328577-4c1ad72c-51b1-47c3-8d3d-3242ec44a355.png)
The token mapping for items with attributes got overwritten partially by the attributes non-item input, since attributes have two different inputs, the item and the direct input both.
This PR gives attributes a second TokenMap for its direct input. We now shift all normal input IDs by the item input maximum(we maybe wanna swap this see below) similar to what we do for macro-rules/def. For mapping down we then have to figure out whether we are inside the direct attribute input or its item input to pick the appropriate mapping which can be done with some token range comparisons.
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/9867
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
10030: fix: Fix multiple derives in one attribute not expanding all in expand_macro r=Veykril a=Veykril
It's probably better to only expand the exact derive the cursor is on(if possible) instead of all derives in the attribute the cursor is one.
follow up to #10029
bors r+
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
10029: internal: Improve expand_macro r=Veykril a=Veykril
- Adds a few more newlines to the output making it more readable
- Fixes a bug with multiple derives not being expandable
There seems to be an issue with multiple derives in one attribute only showing the expansion of the last derive which I'll have to investigate.
bors r+
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
9944: internal: introduce in-place indenting API r=matklad a=iDawer
Introduce `edit_in_place::Indent` that uses mutable tree API and intended to replace `edit::AstNodeEdit`.
Closes#9903
Co-authored-by: Dawer <7803845+iDawer@users.noreply.github.com>
10001: Sort enum variant r=Veykril a=vsrs
A small fix to the problem noted by `@lnicola` :
> ![sort-fields](https://user-images.githubusercontent.com/308347/129513196-4ffc7937-be58-44d4-9ec7-ba8745dcb460.gif)
>
> (note the slight inconsistency here: to sort the variants of `Animal` I have to select the enum name, but to sort the fields of `Cat` I have to select the fields themselves)
Co-authored-by: vsrs <vit@conrlab.com>
9989: Fix two more “a”/“an” typos (this time the other way) r=lnicola a=steffahn
Follow-up to #9987
you guys are still merging these fast 😅
_this time I thought – for sure – that I’d get this commit into #9987 before it’s merged…_
Co-authored-by: Frank Steffahn <frank.steffahn@stu.uni-kiel.de>
It's good that rust-analyzer doesn't belly-up on a panic in some random
assist.
It is less good that rust-analyzer devs only know that the assists are
buggy when they are actively looking at the logs.
9972: refactor : function generation assists r=Veykril a=mahdi-frms
Separated code generation from finding position for generated code. This will be ground work for introducing static associated function generation.
Co-authored-by: mahdi-frms <mahdif1380@outlook.com>
9979: fix: Incorrect up-mapping for tokens in derive attributes r=Veykril a=Veykril
Merely detaching the attributes causes incorrect spans to appear when mapping tokens up as the token ids resolve to the ranges of the stripped item so all the text ranges of its tokens are actually lower than the non-stripped ones.
Same fix as with attributes can be applied here, just replace the derive attribute with an equal amount of whitespace.
Fixes#9387
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
I don't think there's anything wrong with project_model depending on
proc_macro_api directly -- fundamentally, both are about gluing our pure
data model to the messy outside world.
However, it's easy enough to avoid the dependency, so why not.
As an additional consideration, `proc_macro_api` now pulls in `base_db`.
project_model should definitely not depend on that!
9975: minor: Fix panic caused by #9966 r=flodiebold a=flodiebold
Chalk can introduce new type variables when doing lazy normalization, so we have to do the proper 'fudging' after all.
Co-authored-by: Florian Diebold <flodiebold@gmail.com>
9965: minor: Don't ask for the builtin attribute input twice r=Veykril a=Veykril
`tt` and `item` here were the same, I misunderstood what the main input for attributes was in #9943
bors r+
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
9962: Add empty-body check to replace_match_with_if_let and re-prioritize choices r=elkowar a=elkowar
This PR changes some behaviour of the `replace_match_with_if_let` ide-assist.
Concretely, it makes two changes:
it introduces a check for empty expression bodies. This means that checks of the shape
```rs
match x {
A => {}
B => {
println!("hi");
}
}
```
will prefer to use the B branch as the first (and only) variant.
It also reprioritizes the importance of "happy" and "sad" patterns.
Concretely, if there are reasons to prefer having the sad pattern be the first (/only) pattern,
it will follow these.
This means that in the case of
```rs
match x {
Ok(_) => {
println!("Success");
}
Err(e) => {
println!("Failure: {}", e);
}
}
```
the `Err` variant will correctly be used as the first expression in the generated if.
Up until now, the generated code was actually invalid, as it would generate
```rs
if let Ok(_) = x {
println!("Success");
} else {
println!("Failure: {}", e);
}
```
where `e` in the else branch is not defined.
Co-authored-by: elkowar <5300871+elkowar@users.noreply.github.com>
9955: fix: Rename fails on renaming definitions created by macros instead of renaming the macro invocation r=Veykril a=Veykril
bors r+
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
9855: feature: Destructure Tuple Assist r=Veykril a=Booksbaum
Part of #8673. This PR only handles tuples, not TupleStruct and RecordStruct.
Code Assist to destructure a tuple into its items:
![Destructure_Tuple_Assist](https://user-images.githubusercontent.com/15612932/129020107-775d7c94-dca7-4d1f-a0a2-cd63cabf4132.gif)
* Should work in nearly all pattern positions, like let assignment, function parameters, match arms, for loops, and nested variables (`if let Some($0t) = Some((1,2))`)
-> everywhere `IdentPat` is allowed
* Exception: If there's a sub-pattern (``@`):`
```rust
if let t @ (1..=3, 1..=3) = ... {}
// ^
```
-> `t` must be a `Name`; `TuplePat` (`(_0, _1)`) isn't allowed
* inside subpattern is ok:
```rust
let t @ (a, _) = ((1,2), 3);
// ^
```
->
```rust
let t @ ((_0, _1), _) = ((1,2), 3);
```
* Assist triggers only at tuple declaration, not tuple usage.
(might be useful especially when it creates a sub-pattern (after ``@`)` and only changes the usage under cursor -- but not part of this PR).
### References
References can be destructured:
```rust
let t = &(1,2);
// ^
let v = t.0;
```
->
```rust
let (_0, _1) = &(1,2);
let v = _0;
```
BUT: `t.0` and `_0` have different types (`i32` vs. `&i32`) -> `v` has now a different type.
I think that's acceptable: I think the destructure assist is mostly used in simple, immediate scopes and not huge existing code.
Additional Notes:
* `ref` has same behaviour (-> `ref` is kept for items)
```rust
let ref t = (1,2);
// ^
```
->
```rust
let (ref _0, ref _1) = (1,2);
```
* Rust IntelliJ Plugin: doesn't trigger with `&` or `ref` at all
### mutable
```rust
let mut t = (1,2);
// ^
```
->
```rust
let (mut _0, mut _1) = (1,2);
```
and
```rust
let t = &mut (1,2);
// ^
```
->
```rust
let (_0, _1) = &mut (1,2);
```
Again: with reference (`&mut`), `t.0` and `_0` have different types (`i32` vs `&mut i32`).
And there's an additional issue with `&mut` and assignment:
```rust
let t = &mut (1,2);
// ^
t.0 = 9;
```
->
```rust
let (_0, _1) = &mut (1,2);
_0 = 9;
// ^
// mismatched types
// expected `&mut {integer}`, found integer
// consider dereferencing here to assign to the mutable borrowed piece of memory
```
But I think that's quite a niche use case, so I don't catch that (`*_0 = 9;`)
Additional Notes:
* Rust IntelliJ Plugin: removes the `mut` (`let mut t = ...` -> `let (_0, _1) = ...`), doesn't trigger with `&mut`
### Binding after ``@``
Destructure tuple in sub-pattern is implemented:
```rust
let t = (1,2);
// ^
let v = t.0;
let f = t.into();
```
->
```rust
let t @ (_0, _1) = (1,2);
let v = _0;
let f = t.into();
```
BUT: Bindings after ``@`` aren't currently in stable and require `#![feature(bindings_after_at)]` (though should be generally [available quite soon](https://github.com/rust-lang/rust/pull/85305#event-5072889913) (with `1.56.0`)).
But I don't know how to check for an enabled feature -> Destructure tuple in sub-pattern [isn't enabled](a4ee6c7954/crates/ide_assists/src/handlers/destructure_tuple_binding.rs (L32)) yet.
* When Destructure in sub-pattern is enabled there are two assists:
* `Destructure tuple in place`:
```rust
let t = (1,2);
// ^
```
->
```rust
let (_0, _1) = (1,2);
let v = _0;
let f = /*t*/.into();
```
* `Destructure tuple in sub-pattern`:
```rust
let t = (1,2);
// ^
let v = t.0;
let f = t.into();
```
->
```rust
let t @ (_0, _1) = (1,2);
let v = _0;
let f = t.into();
```
* When Destructure in sub-pattern is disabled, only the first one is available and just named `Destructure tuple`
<br/>
<br/>
### Caveats
* Unlike in #8673 or IntelliJ rust plugin, I'm not leaving the previous tuple name at function calls.
**Reasoning**: It's not too unlikely the tuple variable shadows another variable. Destructuring the tuple while leaving the function call untouched, results in still a valid function call -- but now with another variable:
```rust
let t = (8,9);
let t = (1,2);
// ^
t.into()
```
=> Destructure Tuple
```rust
let t = (8,9);
let (_0, _1) = (1,2);
t.into()
```
`t.into()` is still valid -- using the first tuple.
Instead I comment out the tuple usage, which results in invalid code -> must be handled by user:
```rust
/*t*/.into()
```
* (though that might be a biased decision: For testing I just declared a lot of `t`s and quite ofen in lines next to each other...)
* Issue: there are some cases that results in still valid code:
* macro that accept the tuple as well as no arguments:
```rust
macro_rules! m {
() => { "foo" };
($e:expr) => { $e; "foo" };
}
let t = (1,2);
m!(t);
m!(/*t*/);
```
-> both calls are valid ([test](a4ee6c7954/crates/ide_assists/src/handlers/destructure_tuple_binding.rs (L1474)))
* Probably with tuple as return value. Changing the return value most likely results in an error -- but in another place; not where the tuple usage was.
-> not sure that's the best way....
Additional the tuple name surrounded by comment is more difficult to edit than just the name.
* Code Assists don't support snippet placeholder, and rust analyzer just the first `$0` -> unfortunately no editing of generated tuple item variables. Cursor (`$0`) is placed on first generated item.
<br/>
<br/>
### Issues
* Tuple index usage in macro calls aren't converted:
```rust
let t = (1,2);
// ^
let v = t.0;
println!("{}", t.0);
```
->
```rust
let (_0, _1) = (1,2);
let v = _0;
println!("{}", /*t*/.0);
```
([tests](a4ee6c7954/crates/ide_assists/src/handlers/destructure_tuple_binding.rs (L1294)))
* Issue is:
[name.syntax()](a4ee6c7954/crates/ide_assists/src/handlers/destructure_tuple_binding.rs (L242-L244)) in each [usage](a4ee6c7954/crates/ide_assists/src/handlers/destructure_tuple_binding.rs (L108-L113)) of a tuple is syntax & text_range in its file.
EXCEPT when tuple usage is in a macro call (`m!(t.0)`), the macro is expanded and syntax (and range) is based on that expanded macro, not in actual file.
That leads to several things:
* I cannot differentiate between calling the macro with the tuple or with tuple item:
```rust
macro_rules! m {
($t:expr, $i:expr) => { $t.0 + $i };
}
let t = (1,2);
m!(t, t.0);
```
-> both `t` usages are resolved as tuple index usage
* Range of resolved tuple index usage is in expanded macro, not in actual file
-> don't know where to replace index usage
-> tuple items passed into a macro are ignored, and only the tuple name itself is handled (uncommented)
* I'm not checking if the generated names conflict with already existing variables.
```rust
let _0 = 42; // >-|
let t = (1,2); // |
let v = _0; // <-|
// ^ 42
```
=> deconstruct tuple
```rust
let _0 = 42;
let (_0, _1) = (1,2); // >-|
let v = _0; // <-|
// ^ now 1
```
* I tried to get the scope at tuple declaration and its usages. And then iterate all names with [`process_all_names`](145b51f9da/crates/hir/src/semantics.rs (L935)). But that doesn't find all local names for declarations (`let t = (1,2)`) (for usages it does)
* This isn't unique to this Code Assist, but happen in others too (like `extract into variable` or `extract into function`). But here a name conflict is more likely (when destructuring multiple tuples, for examples nested ones (`let t = ((1,2),3)` -> `let (_0, _1) = ...` -> `let ((_0, _1), _1) = ...` -> error))
* IntelliJ rust plugin does handle this (-> name is `_00`)
Co-authored-by: BooksBaum <15612932+Booksbaum@users.noreply.github.com>
Note:
2nd Assist description is moved down: generated doc tests extracts now
all tests (previously only the first one). But it uses the first
`Assist` name -- which is the wrong one for the 2nd test. And 2nd assist
is currently disabled -> would fail anyway.
9921: Only add entries to SourceToDef dynmaps when they come from the same file r=matklad a=Veykril
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/9919
Running the test as described in the issue I do not get any eprintln output at all anymore.
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
cargo llvm-lines shows that path_to_error bloats the code. I don't think
I've needed this functionality recently, seems that we've fixed most of
the serialization problems. So let's just remove it. Should be easy to
add back if we ever need it, and it does make sense to keep the
`from_json` function around.