mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-15 12:39:31 +03:00
Move assists documentation into the manual
This commit is contained in:
@@ -1,18 +1,16 @@
|
||||
# Assists
|
||||
|
||||
Cursor position or selection is signified by `┃` character.
|
||||
|
||||
|
||||
## `add_custom_impl`
|
||||
[discrete]
|
||||
=== `add_custom_impl`
|
||||
|
||||
Adds impl block for derived trait.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
#[derive(Deb┃ug, Display)]
|
||||
struct S;
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
#[derive(Display)]
|
||||
struct S;
|
||||
|
||||
@@ -21,18 +19,22 @@ impl Debug for S {
|
||||
}
|
||||
```
|
||||
|
||||
## `add_derive`
|
||||
|
||||
[discrete]
|
||||
=== `add_derive`
|
||||
|
||||
Adds a new `#[derive()]` clause to a struct or enum.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
struct Point {
|
||||
x: u32,
|
||||
y: u32,┃
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
#[derive($0)]
|
||||
struct Point {
|
||||
x: u32,
|
||||
@@ -40,31 +42,39 @@ struct Point {
|
||||
}
|
||||
```
|
||||
|
||||
## `add_explicit_type`
|
||||
|
||||
[discrete]
|
||||
=== `add_explicit_type`
|
||||
|
||||
Specify type for a let binding.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
let x┃ = 92;
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
let x: i32 = 92;
|
||||
}
|
||||
```
|
||||
|
||||
## `add_from_impl_for_enum`
|
||||
|
||||
[discrete]
|
||||
=== `add_from_impl_for_enum`
|
||||
|
||||
Adds a From impl for an enum variant with one tuple field.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
enum A { ┃One(u32) }
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
enum A { One(u32) }
|
||||
|
||||
impl From<u32> for A {
|
||||
@@ -74,20 +84,24 @@ impl From<u32> for A {
|
||||
}
|
||||
```
|
||||
|
||||
## `add_function`
|
||||
|
||||
[discrete]
|
||||
=== `add_function`
|
||||
|
||||
Adds a stub function with a signature matching the function under the cursor.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
struct Baz;
|
||||
fn baz() -> Baz { Baz }
|
||||
fn foo() {
|
||||
bar┃("", baz());
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
struct Baz;
|
||||
fn baz() -> Baz { Baz }
|
||||
fn foo() {
|
||||
@@ -100,33 +114,41 @@ fn bar(arg: &str, baz: Baz) {
|
||||
|
||||
```
|
||||
|
||||
## `add_hash`
|
||||
|
||||
[discrete]
|
||||
=== `add_hash`
|
||||
|
||||
Adds a hash to a raw string literal.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
r#"Hello,┃ World!"#;
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
r##"Hello, World!"##;
|
||||
}
|
||||
```
|
||||
|
||||
## `add_impl`
|
||||
|
||||
[discrete]
|
||||
=== `add_impl`
|
||||
|
||||
Adds a new inherent impl for a type.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
struct Ctx<T: Clone> {
|
||||
data: T,┃
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
struct Ctx<T: Clone> {
|
||||
data: T,
|
||||
}
|
||||
@@ -136,12 +158,14 @@ impl<T: Clone> Ctx<T> {
|
||||
}
|
||||
```
|
||||
|
||||
## `add_impl_default_members`
|
||||
|
||||
[discrete]
|
||||
=== `add_impl_default_members`
|
||||
|
||||
Adds scaffold for overriding default impl members.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
trait Trait {
|
||||
Type X;
|
||||
fn foo(&self);
|
||||
@@ -153,8 +177,10 @@ impl Trait for () {
|
||||
fn foo(&self) {}┃
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
trait Trait {
|
||||
Type X;
|
||||
fn foo(&self);
|
||||
@@ -169,12 +195,14 @@ impl Trait for () {
|
||||
}
|
||||
```
|
||||
|
||||
## `add_impl_missing_members`
|
||||
|
||||
[discrete]
|
||||
=== `add_impl_missing_members`
|
||||
|
||||
Adds scaffold for required impl members.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
trait Trait<T> {
|
||||
Type X;
|
||||
fn foo(&self) -> T;
|
||||
@@ -184,8 +212,10 @@ trait Trait<T> {
|
||||
impl Trait<u32> for () {┃
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
trait Trait<T> {
|
||||
Type X;
|
||||
fn foo(&self) -> T;
|
||||
@@ -200,17 +230,21 @@ impl Trait<u32> for () {
|
||||
}
|
||||
```
|
||||
|
||||
## `add_new`
|
||||
|
||||
[discrete]
|
||||
=== `add_new`
|
||||
|
||||
Adds a new inherent impl for a type.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
struct Ctx<T: Clone> {
|
||||
data: T,┃
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
struct Ctx<T: Clone> {
|
||||
data: T,
|
||||
}
|
||||
@@ -221,25 +255,31 @@ impl<T: Clone> Ctx<T> {
|
||||
|
||||
```
|
||||
|
||||
## `add_turbo_fish`
|
||||
|
||||
[discrete]
|
||||
=== `add_turbo_fish`
|
||||
|
||||
Adds `::<_>` to a call of a generic method or function.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn make<T>() -> T { todo!() }
|
||||
fn main() {
|
||||
let x = make┃();
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn make<T>() -> T { todo!() }
|
||||
fn main() {
|
||||
let x = make::<${0:_}>();
|
||||
}
|
||||
```
|
||||
|
||||
## `apply_demorgan`
|
||||
|
||||
[discrete]
|
||||
=== `apply_demorgan`
|
||||
|
||||
Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
|
||||
This transforms expressions of the form `!l || !r` into `!(l && r)`.
|
||||
@@ -247,29 +287,35 @@ This also works with `&&`. This assist can only be applied with the cursor
|
||||
on either `||` or `&&`, with both operands being a negation of some kind.
|
||||
This means something of the form `!x` or `x != y`.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
if x != 4 ||┃ !y {}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
if !(x == 4 && y) {}
|
||||
}
|
||||
```
|
||||
|
||||
## `auto_import`
|
||||
|
||||
[discrete]
|
||||
=== `auto_import`
|
||||
|
||||
If the name is unresolved, provides all possible imports for it.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
let map = HashMap┃::new();
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
@@ -277,12 +323,14 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## `change_lifetime_anon_to_named`
|
||||
|
||||
[discrete]
|
||||
=== `change_lifetime_anon_to_named`
|
||||
|
||||
Change an anonymous lifetime to a named lifetime.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
impl Cursor<'_┃> {
|
||||
fn node(self) -> &SyntaxNode {
|
||||
match self {
|
||||
@@ -290,8 +338,10 @@ impl Cursor<'_┃> {
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
impl<'a> Cursor<'a> {
|
||||
fn node(self) -> &SyntaxNode {
|
||||
match self {
|
||||
@@ -301,44 +351,56 @@ impl<'a> Cursor<'a> {
|
||||
}
|
||||
```
|
||||
|
||||
## `change_return_type_to_result`
|
||||
|
||||
[discrete]
|
||||
=== `change_return_type_to_result`
|
||||
|
||||
Change the function's return type to Result.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn foo() -> i32┃ { 42i32 }
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
|
||||
```
|
||||
|
||||
## `change_visibility`
|
||||
|
||||
[discrete]
|
||||
=== `change_visibility`
|
||||
|
||||
Adds or changes existing visibility specifier.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
┃fn frobnicate() {}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
pub(crate) fn frobnicate() {}
|
||||
```
|
||||
|
||||
## `convert_to_guarded_return`
|
||||
|
||||
[discrete]
|
||||
=== `convert_to_guarded_return`
|
||||
|
||||
Replace a large conditional with a guarded return.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
┃if cond {
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
if !cond {
|
||||
return;
|
||||
@@ -348,12 +410,14 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## `fill_match_arms`
|
||||
|
||||
[discrete]
|
||||
=== `fill_match_arms`
|
||||
|
||||
Adds missing clauses to a `match` expression.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -361,8 +425,10 @@ fn handle(action: Action) {
|
||||
┃
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -373,20 +439,24 @@ fn handle(action: Action) {
|
||||
}
|
||||
```
|
||||
|
||||
## `fix_visibility`
|
||||
|
||||
[discrete]
|
||||
=== `fix_visibility`
|
||||
|
||||
Makes inaccessible item public.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
mod m {
|
||||
fn frobnicate() {}
|
||||
}
|
||||
fn main() {
|
||||
m::frobnicate┃() {}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
mod m {
|
||||
$0pub(crate) fn frobnicate() {}
|
||||
}
|
||||
@@ -395,154 +465,192 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## `flip_binexpr`
|
||||
|
||||
[discrete]
|
||||
=== `flip_binexpr`
|
||||
|
||||
Flips operands of a binary expression.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
let _ = 90 +┃ 2;
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
let _ = 2 + 90;
|
||||
}
|
||||
```
|
||||
|
||||
## `flip_comma`
|
||||
|
||||
[discrete]
|
||||
=== `flip_comma`
|
||||
|
||||
Flips two comma-separated items.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
((1, 2),┃ (3, 4));
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
((3, 4), (1, 2));
|
||||
}
|
||||
```
|
||||
|
||||
## `flip_trait_bound`
|
||||
|
||||
[discrete]
|
||||
=== `flip_trait_bound`
|
||||
|
||||
Flips two trait bounds.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn foo<T: Clone +┃ Copy>() { }
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn foo<T: Copy + Clone>() { }
|
||||
```
|
||||
|
||||
## `inline_local_variable`
|
||||
|
||||
[discrete]
|
||||
=== `inline_local_variable`
|
||||
|
||||
Inlines local variable.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
let x┃ = 1 + 2;
|
||||
x * 4;
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
(1 + 2) * 4;
|
||||
}
|
||||
```
|
||||
|
||||
## `introduce_variable`
|
||||
|
||||
[discrete]
|
||||
=== `introduce_variable`
|
||||
|
||||
Extracts subexpression into a variable.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
┃(1 + 2)┃ * 4;
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
let $0var_name = (1 + 2);
|
||||
var_name * 4;
|
||||
}
|
||||
```
|
||||
|
||||
## `invert_if`
|
||||
|
||||
[discrete]
|
||||
=== `invert_if`
|
||||
|
||||
Apply invert_if
|
||||
This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
|
||||
This also works with `!=`. This assist can only be applied with the cursor
|
||||
on `if`.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
if┃ !y { A } else { B }
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
if y { B } else { A }
|
||||
}
|
||||
```
|
||||
|
||||
## `make_raw_string`
|
||||
|
||||
[discrete]
|
||||
=== `make_raw_string`
|
||||
|
||||
Adds `r#` to a plain string literal.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
"Hello,┃ World!";
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
r#"Hello, World!"#;
|
||||
}
|
||||
```
|
||||
|
||||
## `make_usual_string`
|
||||
|
||||
[discrete]
|
||||
=== `make_usual_string`
|
||||
|
||||
Turns a raw string into a plain string.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
r#"Hello,┃ "World!""#;
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
"Hello, \"World!\"";
|
||||
}
|
||||
```
|
||||
|
||||
## `merge_imports`
|
||||
|
||||
[discrete]
|
||||
=== `merge_imports`
|
||||
|
||||
Merges two imports with a common prefix.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
use std::┃fmt::Formatter;
|
||||
use std::io;
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
use std::{fmt::Formatter, io};
|
||||
```
|
||||
|
||||
## `merge_match_arms`
|
||||
|
||||
[discrete]
|
||||
=== `merge_match_arms`
|
||||
|
||||
Merges identical match arms.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -551,8 +659,10 @@ fn handle(action: Action) {
|
||||
Action::Stop => foo(),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -562,12 +672,14 @@ fn handle(action: Action) {
|
||||
}
|
||||
```
|
||||
|
||||
## `move_arm_cond_to_match_guard`
|
||||
|
||||
[discrete]
|
||||
=== `move_arm_cond_to_match_guard`
|
||||
|
||||
Moves if expression from match arm body into a guard.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -576,8 +688,10 @@ fn handle(action: Action) {
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -588,28 +702,34 @@ fn handle(action: Action) {
|
||||
}
|
||||
```
|
||||
|
||||
## `move_bounds_to_where_clause`
|
||||
|
||||
[discrete]
|
||||
=== `move_bounds_to_where_clause`
|
||||
|
||||
Moves inline type bounds to a where clause.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U {
|
||||
f(x)
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
|
||||
f(x)
|
||||
}
|
||||
```
|
||||
|
||||
## `move_guard_to_arm_body`
|
||||
|
||||
[discrete]
|
||||
=== `move_guard_to_arm_body`
|
||||
|
||||
Moves match guard into match arm body.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -618,8 +738,10 @@ fn handle(action: Action) {
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -630,75 +752,93 @@ fn handle(action: Action) {
|
||||
}
|
||||
```
|
||||
|
||||
## `remove_dbg`
|
||||
|
||||
[discrete]
|
||||
=== `remove_dbg`
|
||||
|
||||
Removes `dbg!()` macro call.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
┃dbg!(92);
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
92;
|
||||
}
|
||||
```
|
||||
|
||||
## `remove_hash`
|
||||
|
||||
[discrete]
|
||||
=== `remove_hash`
|
||||
|
||||
Removes a hash from a raw string literal.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn main() {
|
||||
r#"Hello,┃ World!"#;
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn main() {
|
||||
r"Hello, World!";
|
||||
}
|
||||
```
|
||||
|
||||
## `remove_mut`
|
||||
|
||||
[discrete]
|
||||
=== `remove_mut`
|
||||
|
||||
Removes the `mut` keyword.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
impl Walrus {
|
||||
fn feed(&mut┃ self, amount: u32) {}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
impl Walrus {
|
||||
fn feed(&self, amount: u32) {}
|
||||
}
|
||||
```
|
||||
|
||||
## `reorder_fields`
|
||||
|
||||
[discrete]
|
||||
=== `reorder_fields`
|
||||
|
||||
Reorder the fields of record literals and record patterns in the same order as in
|
||||
the definition.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
struct Foo {foo: i32, bar: i32};
|
||||
const test: Foo = ┃Foo {bar: 0, foo: 1}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
struct Foo {foo: i32, bar: i32};
|
||||
const test: Foo = Foo {foo: 1, bar: 0}
|
||||
```
|
||||
|
||||
## `replace_if_let_with_match`
|
||||
|
||||
[discrete]
|
||||
=== `replace_if_let_with_match`
|
||||
|
||||
Replaces `if let` with an else branch with a `match` expression.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -708,8 +848,10 @@ fn handle(action: Action) {
|
||||
bar()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
enum Action { Move { distance: u32 }, Stop }
|
||||
|
||||
fn handle(action: Action) {
|
||||
@@ -720,20 +862,24 @@ fn handle(action: Action) {
|
||||
}
|
||||
```
|
||||
|
||||
## `replace_let_with_if_let`
|
||||
|
||||
[discrete]
|
||||
=== `replace_let_with_if_let`
|
||||
|
||||
Replaces `let` with an `if-let`.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
|
||||
fn main(action: Action) {
|
||||
┃let x = compute();
|
||||
}
|
||||
|
||||
fn compute() -> Option<i32> { None }
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
|
||||
fn main(action: Action) {
|
||||
if let Some(x) = compute() {
|
||||
@@ -743,33 +889,41 @@ fn main(action: Action) {
|
||||
fn compute() -> Option<i32> { None }
|
||||
```
|
||||
|
||||
## `replace_qualified_name_with_use`
|
||||
|
||||
[discrete]
|
||||
=== `replace_qualified_name_with_use`
|
||||
|
||||
Adds a use statement for a given fully-qualified name.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn process(map: std::collections::┃HashMap<String, String>) {}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn process(map: HashMap<String, String>) {}
|
||||
```
|
||||
|
||||
## `replace_unwrap_with_match`
|
||||
|
||||
[discrete]
|
||||
=== `replace_unwrap_with_match`
|
||||
|
||||
Replaces `unwrap` a `match` expression. Works for Result and Option.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
enum Result<T, E> { Ok(T), Err(E) }
|
||||
fn main() {
|
||||
let x: Result<i32, i32> = Result::Ok(92);
|
||||
let y = x.┃unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
enum Result<T, E> { Ok(T), Err(E) }
|
||||
fn main() {
|
||||
let x: Result<i32, i32> = Result::Ok(92);
|
||||
@@ -780,31 +934,39 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## `split_import`
|
||||
|
||||
[discrete]
|
||||
=== `split_import`
|
||||
|
||||
Wraps the tail of import into braces.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
use std::┃collections::HashMap;
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
use std::{collections::HashMap};
|
||||
```
|
||||
|
||||
## `unwrap_block`
|
||||
|
||||
[discrete]
|
||||
=== `unwrap_block`
|
||||
|
||||
This assist removes if...else, for, while and loop control statements to just keep the body.
|
||||
|
||||
.Before
|
||||
```rust
|
||||
// BEFORE
|
||||
fn foo() {
|
||||
if true {┃
|
||||
println!("foo");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
// AFTER
|
||||
.After
|
||||
```rust
|
||||
fn foo() {
|
||||
println!("foo");
|
||||
}
|
||||
@@ -278,5 +278,6 @@ include::./generated_features.adoc[]
|
||||
|
||||
Assists, or code actions, are small local refactorings, available in a particular context.
|
||||
They are usually triggered by a shortcut or by clicking a light bulb icon in the editor.
|
||||
Cursor position or selection is signified by `┃` character.
|
||||
|
||||
See [assists.md](./assists.md) for the list of available assists.
|
||||
include::./generated_assists.adoc[]
|
||||
|
||||
+30
-3
@@ -10,9 +10,12 @@
|
||||
mod gen_assists_docs;
|
||||
mod gen_feature_docs;
|
||||
|
||||
use std::{mem, path::Path};
|
||||
use std::{
|
||||
fmt, mem,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::{not_bash::fs2, Result};
|
||||
use crate::{not_bash::fs2, project_root, Result};
|
||||
|
||||
pub use self::{
|
||||
gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs,
|
||||
@@ -29,7 +32,6 @@
|
||||
|
||||
const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
|
||||
const ASSISTS_TESTS: &str = "crates/ra_assists/src/tests/generated.rs";
|
||||
const ASSISTS_DOCS: &str = "docs/user/assists.md";
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Mode {
|
||||
@@ -107,3 +109,28 @@ fn do_extract_comment_blocks(text: &str, allow_blocks_with_empty_lines: bool) ->
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Location {
|
||||
file: PathBuf,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
fn new(file: PathBuf) -> Self {
|
||||
Self { file }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Location {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let path = self.file.strip_prefix(&project_root()).unwrap().display().to_string();
|
||||
let path = path.replace('\\', "/");
|
||||
let name = self.file.file_name().unwrap();
|
||||
write!(
|
||||
f,
|
||||
"https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]",
|
||||
path,
|
||||
name.to_str().unwrap()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
//! Generates `assists.md` documentation.
|
||||
|
||||
use std::{fs, path::Path};
|
||||
use std::{fmt, fs, path::Path};
|
||||
|
||||
use crate::{
|
||||
codegen::{self, extract_comment_blocks_with_empty_lines, Mode},
|
||||
codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode},
|
||||
project_root, rust_files, Result,
|
||||
};
|
||||
|
||||
pub fn generate_assists_docs(mode: Mode) -> Result<()> {
|
||||
let assists = Assist::collect()?;
|
||||
generate_tests(&assists, mode)?;
|
||||
generate_docs(&assists, mode)?;
|
||||
|
||||
let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n");
|
||||
let contents = contents.trim().to_string() + "\n";
|
||||
let dst = project_root().join("docs/user/generated_assists.adoc");
|
||||
codegen::update(&dst, &contents, mode)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Assist {
|
||||
id: String,
|
||||
location: Location,
|
||||
doc: String,
|
||||
before: String,
|
||||
after: String,
|
||||
@@ -58,7 +64,8 @@ fn collect_file(acc: &mut Vec<Assist>, path: &Path) -> Result<()> {
|
||||
assert_eq!(lines.next().unwrap().as_str(), "->");
|
||||
assert_eq!(lines.next().unwrap().as_str(), "```");
|
||||
let after = take_until(lines.by_ref(), "```");
|
||||
acc.push(Assist { id, doc, before, after })
|
||||
let location = Location::new(path.to_path_buf());
|
||||
acc.push(Assist { id, location, doc, before, after })
|
||||
}
|
||||
|
||||
fn take_until<'a>(lines: impl Iterator<Item = &'a String>, marker: &str) -> String {
|
||||
@@ -76,6 +83,31 @@ fn take_until<'a>(lines: impl Iterator<Item = &'a String>, marker: &str) -> Stri
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Assist {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let before = self.before.replace("<|>", "┃"); // Unicode pseudo-graphics bar
|
||||
let after = self.after.replace("<|>", "┃");
|
||||
writeln!(
|
||||
f,
|
||||
"[discrete]\n=== `{}`
|
||||
|
||||
{}
|
||||
|
||||
.Before
|
||||
```rust
|
||||
{}```
|
||||
|
||||
.After
|
||||
```rust
|
||||
{}```",
|
||||
self.id,
|
||||
self.doc,
|
||||
hide_hash_comments(&before),
|
||||
hide_hash_comments(&after)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_tests(assists: &[Assist], mode: Mode) -> Result<()> {
|
||||
let mut buf = String::from("use super::check_doc_test;\n");
|
||||
|
||||
@@ -103,37 +135,6 @@ fn doctest_{}() {{
|
||||
codegen::update(&project_root().join(codegen::ASSISTS_TESTS), &buf, mode)
|
||||
}
|
||||
|
||||
fn generate_docs(assists: &[Assist], mode: Mode) -> Result<()> {
|
||||
let mut buf = String::from(
|
||||
"# Assists\n\nCursor position or selection is signified by `┃` character.\n\n",
|
||||
);
|
||||
|
||||
for assist in assists {
|
||||
let before = assist.before.replace("<|>", "┃"); // Unicode pseudo-graphics bar
|
||||
let after = assist.after.replace("<|>", "┃");
|
||||
let docs = format!(
|
||||
"
|
||||
## `{}`
|
||||
|
||||
{}
|
||||
|
||||
```rust
|
||||
// BEFORE
|
||||
{}
|
||||
// AFTER
|
||||
{}```
|
||||
",
|
||||
assist.id,
|
||||
assist.doc,
|
||||
hide_hash_comments(&before),
|
||||
hide_hash_comments(&after)
|
||||
);
|
||||
buf.push_str(&docs);
|
||||
}
|
||||
|
||||
codegen::update(&project_root().join(codegen::ASSISTS_DOCS), &buf, mode)
|
||||
}
|
||||
|
||||
fn hide_hash_comments(text: &str) -> String {
|
||||
text.split('\n') // want final newline
|
||||
.filter(|&it| !(it.starts_with("# ") || it == "#"))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use std::{fmt, fs, path::PathBuf};
|
||||
|
||||
use crate::{
|
||||
codegen::{self, extract_comment_blocks_with_empty_lines, Mode},
|
||||
codegen::{self, extract_comment_blocks_with_empty_lines, Location, Mode},
|
||||
project_root, rust_files, Result,
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn generate_feature_docs(mode: Mode) -> Result<()> {
|
||||
#[derive(Debug)]
|
||||
struct Feature {
|
||||
id: String,
|
||||
path: PathBuf,
|
||||
location: Location,
|
||||
doc: String,
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ fn collect_file(acc: &mut Vec<Feature>, path: PathBuf) -> Result<()> {
|
||||
let id = block.id;
|
||||
assert!(is_valid_feature_name(&id), "invalid feature name: {:?}", id);
|
||||
let doc = block.contents.join("\n");
|
||||
acc.push(Feature { id, path: path.clone(), doc })
|
||||
acc.push(Feature { id, location: Location::new(path.clone()), doc })
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -69,20 +69,6 @@ fn is_valid_feature_name(feature: &str) -> bool {
|
||||
|
||||
impl fmt::Display for Feature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "=== {}", self.id)?;
|
||||
let path = self.path.strip_prefix(&project_root()).unwrap().display().to_string();
|
||||
let path = path.replace('\\', "/");
|
||||
let name = self.path.file_name().unwrap();
|
||||
|
||||
//FIXME: generate line number as well
|
||||
writeln!(
|
||||
f,
|
||||
"**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/{}[{}]",
|
||||
path,
|
||||
name.to_str().unwrap(),
|
||||
)?;
|
||||
|
||||
writeln!(f, "{}", self.doc)?;
|
||||
Ok(())
|
||||
writeln!(f, "=== {}\n**Source:** {}\n{}", self.id, self.location, self.doc)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -191,7 +191,7 @@ pub fn run_release(dry_run: bool) -> Result<()> {
|
||||
let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
|
||||
fs2::write(&path, &contents)?;
|
||||
|
||||
for &adoc in ["manual.adoc", "generated_features.adoc"].iter() {
|
||||
for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() {
|
||||
let src = project_root().join("./docs/user/").join(adoc);
|
||||
let dst = website_root.join(adoc);
|
||||
fs2::copy(src, dst)?;
|
||||
|
||||
Reference in New Issue
Block a user