Commit graph

59 commits

Author SHA1 Message Date
Lukas Wirth
8b1e8197fe Merge iter_for_each_to_for and for_to_iter_for_each assists modules 2021-09-21 10:34:11 +02:00
Lukas Wirth
8b2be8572f Rename some assists 2021-09-21 00:54:09 +02:00
Andrzej Głuszak
11a56f886b assists: turn while into loop 2021-09-16 22:20:27 +02:00
Aleksey Kladov
076c972e3b internal: prevent possible bugs when adding magical comments 2021-09-13 13:43:13 +03:00
Dawer
535761e63f minor: update test 2021-09-04 15:19:44 +05:00
DropDemBits
3bafb5f025
feat: Use enum's visibility for extracted struct fields 2021-08-30 21:33:19 -04:00
bors[bot]
59aa091866
Merge #9855
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>
2021-08-19 15:19:06 +00:00
Yoshua Wuyts
586d6fca8c Fix codegen for is_method documentation
Previously the generated paths were invalid. This fixes that.
2021-08-19 13:31:16 +02:00
BooksBaum
d0cf28322a
Add generated doctest 2021-08-17 19:23:06 +02:00
Aleksey Kladov
beca92b245 internal: make invert binary op more robust
Previously, we only inverted comparison operators (< and the like) if
the type implemented Ord. This doesn't make sense: if `<` works, then
`>=` will work as well!

Extra semantic checks greatly reduce robustness and predictability of
the assist, it's better to keep things simple.
2021-08-14 16:40:00 +03:00
Lukas Wirth
b7d7dd6163 Implement bool_then_to_if assist 2021-08-10 13:17:45 +02:00
bors[bot]
caac771439
Merge #9735
9735: Add assist to sort members alphabetically. r=matklad a=vsrs

Supports traits, impls, structs, unions and enums (including inner struct variants). Does not support modules yet.

```rust
en┃um Animal {
  Dog(String, f64),
  Cat { weight: f64, name: String },
}
```
->
```rust
enum Animal {
  Cat { weight: f64, name: String },
  Dog(String, f64),
}
```
---
```rust
enum Animal {
  Dog(String, f64),
  Cat {┃ weight: f64, name: String },
}
```
->
```rust
enum Animal {
  Dog(String, f64),
  Cat { name: String, weight: f64 },
}
```
---
More samples in docs 0b7835619a/crates/ide_assists/src/handlers/sort_items.rs (L12-L83).

Relates #6110


Co-authored-by: vsrs <vit@conrlab.com>
2021-08-09 10:21:14 +00:00
bors[bot]
5664a2b0b3
Merge #9814
9814: Generate default impl when converting `#[derive(Debug)]` to manual impl r=yoshuawuyts a=yoshuawuyts

This patch makes it so when you convert `#[derive(Debug)]` to a manual impl, a default body is provided that's equivalent to the original output of `#[derive(Debug)]`. This should make it drastically easier to write custom `Debug` impls, especially when all you want to do is quickly omit a single field which is `!Debug`.

This is implemented for enums, record structs, tuple structs, empty structs - and it sets us up to implement variations on this in the future for other traits (like `PartialEq` and `Hash`).

Thanks!

## Codegen diff
This is the difference in codegen for record structs with this patch:
```diff
struct Foo {
    bar: String,
}

impl fmt::Debug for Foo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        todo!();
+        f.debug_struct("Foo").field("bar", &self.bar).finish()
    }
}
```

Co-authored-by: Irina Shestak <shestak.irina@gmail.com>
Co-authored-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
Co-authored-by: Yoshua Wuyts <yoshuawuyts+github@gmail.com>
2021-08-08 22:30:37 +00:00
Lukas Wirth
3b7c713af3 Implement if_to_bool_then assist 2021-08-08 17:56:34 +02:00
Yoshua Wuyts
fd7236c791 debug for record field structs 2021-08-08 16:26:25 +02:00
Yoshua Wuyts
e2ab2e12a0 wip 2021-08-08 16:24:54 +02:00
vsrs
cc33b0dc82 Update the docs 2021-08-02 20:24:18 +03:00
vsrs
e71b239d37 fix generated tests 2021-08-02 19:49:36 +03:00
vsrs
0088f84c88 Allow several samples in "// Assist:" comments. 2021-08-02 19:49:36 +03:00
Lukas Wirth
17a47a830b Add replace_char_with_string assist 2021-07-30 16:46:06 +02:00
Lukas Wirth
46c42166d6 Yeet replace_unwrap_with_match in favor of inline_call 2021-07-05 15:47:55 +02:00
Lukas Wirth
2579dc6d82 Update inline_call assist doc example 2021-07-05 14:24:25 +02:00
bors[bot]
2bc4f9e371
Merge #9474
9474: fix: Inline parameters in `inline_call` if possible r=Veykril a=Veykril

Fixes #9491

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
2021-07-05 11:50:18 +00:00
Lukas Wirth
ea02d27a1e Fixup emitted whitespace in most cases 2021-07-05 13:44:42 +02:00
Lukas Wirth
e41b5348b8 replace_qualified_name_with_use insert qualified import paths 2021-07-03 23:42:59 +02:00
Lukas Wirth
6181154d50 Add some more inline_call tests 2021-07-03 21:42:59 +02:00
bors[bot]
336194c09b
Merge #9476
9476: internal: overhaul codegen r=matklad a=matklad

bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
2021-07-03 19:26:04 +00:00
Aleksey Kladov
58d2ece88a internal: overhaul code generation
* Keep codegen adjacent to the relevant crates.
* Remove codgen deps from xtask, speeding-up from-source installation.

This regresses the release process a bit, as it now needs to run the
tests (and, by extension, compile the code).
2021-07-03 22:11:03 +03:00
Lukas Wirth
14e18bfa38 Merge the inline function/method assists into inline_call 2021-07-03 18:07:03 +02:00
Lukas Wirth
fbdcb49d48 Simplify 2021-07-03 01:31:41 +02:00
Aleksey Kladov
3762cc7465 minor: use minicore 2021-06-18 23:59:47 +03:00
Domantas Jadenkus
8d2e3816bc tidy 2021-05-24 22:17:16 +03:00
Aleksey Kladov
479a7387c2 feat: generate getter avoids generating types like &Vec<T> 2021-05-24 00:15:23 +03:00
Aleksey Kladov
8696c82777 feat: generate getter assist places the cursor at the generated function 2021-05-23 23:43:33 +03:00
Aleksey Kladov
cea589b3b5 internal: rewrite assoc item manipulaion to use mutable trees 2021-05-14 18:47:08 +03:00
Aleksey Kladov
4f3c0adc5a internal: introduce ast::make::ext module with common shortcuts
There's a tension between keeping a well-architectured minimal
orthogonal set of constructs, and providing convenience functions.
Relieve this pressure by introducing an dedicated module for
non-orthogonal shortcuts.

This is inspired by the django.shortcuts module which serves a similar
purpose architecturally.
2021-05-09 19:55:43 +03:00
bors[bot]
85bab7539a
Merge #8317
8317: Convert tuple struct to named struct assist r=Veykril a=unexge

Closes https://github.com/rust-analyzer/rust-analyzer/issues/8192

Co-authored-by: unexge <unexge@gmail.com>
2021-04-23 13:37:48 +00:00
unexge
e0a60e71d7 Add larger example for "Convert to named struct" assist 2021-04-21 10:57:36 +03:00
jake
a624e2ea8d Adds impl Deref assist 2021-04-11 00:42:05 -07:00
unexge
8d4be829e0 Add convert tuple struct to named struct assist 2021-04-04 20:52:43 +03:00
Graeme Coupar
ee03849017 Convert Into to From assist
This adds a "Convert Into to From" assist, useful since clippy has
recently started adding lints on every `Into`.

It covers converting the signature, and converting any `self`/`Self`
references within the body to the correct types.

It does assume that every instance of `Into` can be converted to a
`From`, which I _think_ is the case now.  Let me know if there's
something I'm not thinking of and I can try and make it smarter.
2021-04-03 15:48:35 +01:00
Jonas Schievink
3c6c1c99b4 Don't use snippets 2021-03-29 13:23:07 +02:00
Jonas Schievink
b494e47920 Snippet support in extract_type_alias 2021-03-27 18:53:13 +01:00
Jonas Schievink
e39979aa91 Implement "Extract type alias" assist 2021-03-26 19:39:20 +01:00
Chetan Khilosiya
0c2d4a8a77 7709: Updated the implementation.
The get function from impl method is updated.
and now same method used to get len and is_empty function.
2021-03-15 22:48:50 +05:30
Chetan Khilosiya
2bf3802f21 7709: Added the assist to generate is_empty function
the assist will be shown when the len function is implemented.
is_empty internally uses len function.
2021-03-15 21:31:52 +05:30
Lukas Wirth
6d35c67b6e Fix convert_iter_for_each_to_for doctest 2021-03-12 15:42:53 +01:00
Luiz Carlos Mourão Paes de Carvalho
e505752442 fix: generated test fixture 2021-03-12 08:53:57 -03:00
Chetan Khilosiya
135c9e2027 7708: Fixed many documentaion example issues. 2021-03-07 00:49:03 +05:30
Aleksey Kladov
406d96c7d4 Use consistent naming for assist 2021-02-28 21:14:34 +03:00