rust/docs/user/features.md

324 lines
5.6 KiB
Markdown
Raw Normal View History

2019-03-20 05:05:03 -05:00
This documents is an index of features that rust-analyzer language server
provides. Shortcuts are for the default VS Code layout. If there's no shortcut,
you can use <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action.
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
### Workspace Symbol <kbd>ctrl+t</kbd>
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Uses fuzzy-search to find types, modules and function by name across your
project and dependencies. This **the** most useful feature, which improves code
navigation tremendously. It mostly works on top of the built-in LSP
functionality, however `#` and `*` symbols can be used to narrow down the
search. Specifically,
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
- `Foo` searches for `Foo` type in the current workspace
- `foo#` searches for `foo` function in the current workspace
- `Foo*` searches for `Foo` type among dependencies, excluding `stdlib`
- `foo#*` searches for `foo` function among dependencies.
2019-03-20 04:17:12 -05:00
That is, `#` switches from "types" to all symbols, `*` switches from the current
workspace to dependencies.
2019-03-20 05:05:03 -05:00
### Document Symbol <kbd>ctrl+shift+o</kbd>
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Provides a tree of the symbols defined in the file. Can be used to
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
* fuzzy search symbol in a file (super useful)
* draw breadcrumbs to describe the context around the cursor
* draw outline of the file
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
### On Typing Assists
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Some features trigger on typing certain characters:
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression.
- Enter inside comments automatically inserts `///`
- typing `.` in a chain method call auto-indents
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
### Commands <kbd>ctrl+shift+p</kbd>
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
#### Extend Selection
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Extends the current selection to the encompassing syntactic construct
(expression, statement, item, module, etc). It works with multiple cursors. Do
bind this command to a key, it's super-useful! Expected to be upstreamed to LSP
soonish: https://github.com/Microsoft/language-server-protocol/issues/613
2019-03-20 04:17:12 -05:00
#### Run
Shows popup suggesting to run a test/benchmark/binary **at the current cursor
location**. Super useful for repeatedly running just a single test. Do bind this
to a shortcut!
2019-03-20 05:05:03 -05:00
#### Parent Module
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Navigates to the parent module of the current module.
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
#### Matching Brace
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
moves cursor to the matching brace. It uses the actual parser to determine
braces, so it won't confuse generics with comparisons.
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
#### Join Lines
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Join selected lines into one, smartly fixing up whitespace and trailing commas.
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
#### Show Syntax Tree
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Shows the parse tree of the current file. It exists mostly for debugging
rust-analyzer itself.
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
#### Status
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Shows internal statistic about memory usage of rust-analyzer
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
#### Run garbage collection
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
Manually triggers GC
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
### Code Actions (Assists)
These are triggered in a particular context via light bulb. We use custom code on
the VS Code side to be able to position cursor. `<|>` signifies cursor
2019-03-20 04:17:12 -05:00
- Add `#[derive]`
```rust
// before:
struct Foo {
<|>x: i32
}
// after:
#[derive(<|>)]
struct Foo {
x: i32
}
```
- Add `impl`
```rust
// before:
struct Foo<'a, T: Debug> {
<|>t: T
}
// after:
struct Foo<'a, T: Debug> {
t: T
}
impl<'a, T: Debug> Foo<'a, T> {
<|>
}
```
2019-03-20 05:05:03 -05:00
- Add missing `impl` members
2019-03-20 04:17:12 -05:00
```rust
// before:
2019-03-20 05:05:03 -05:00
trait Foo {
fn foo(&self);
fn bar(&self);
fn baz(&self);
}
struct S;
impl Foo for S {
fn bar(&self) {}
<|>
}
// after:
trait Foo {
fn foo(&self);
fn bar(&self);
fn baz(&self);
}
2019-03-20 04:17:12 -05:00
2019-03-20 05:05:03 -05:00
struct S;
impl Foo for S {
fn bar(&self) {}
fn foo(&self) { unimplemented!() }
fn baz(&self) { unimplemented!() }<|>
}
```
- Import path
```rust
// before:
impl std::fmt::Debug<|> for Foo {
}
// after:
use std::fmt::Debug
impl Debug<|> for Foo {
}
```
- Change Visibility
```rust
// before:
<|>fn foo() {}
// after:
<|>pub(crate) fn foo() {}
// after:
<|>pub fn foo() {}
```
- Fill match arms
```rust
// before:
enum A {
As,
Bs,
Cs(String),
Ds(String, String),
Es{x: usize, y: usize}
}
fn main() {
let a = A::As;
match a<|> {}
}
// after:
enum A {
As,
Bs,
Cs(String),
Ds(String, String),
Es{x: usize, y: usize}
}
fn main() {
let a = A::As;
match <|>a {
A::As => (),
A::Bs => (),
A::Cs(_) => (),
A::Ds(_, _) => (),
A::Es{x, y} => (),
}
}
```
-- Fill struct fields
```rust
// before:
struct S<'a, D> {
a: u32,
b: String,
c: (i32, i32),
d: D,
r: &'a str,
}
fn main() {
let s = S<|> {}
}
// after:
struct S<'a, D> {
a: u32,
b: String,
c: (i32, i32),
d: D,
r: &'a str,
}
fn main() {
let s = <|>S {
a: (),
b: (),
c: (),
d: (),
r: (),
}
}
```
- Flip `,`
```rust
// before:
fn foo(x: usize,<|> dim: (usize, usize)) {}
// after:
fn foo(dim: (usize, usize), x: usize) {}
2019-03-20 04:17:12 -05:00
```
- Introduce variable:
```rust
// before:
fn foo() {
foo(<|>1 + 1<|>);
}
// after:
fn foo() {
let var_name = 1 + 1;
foo(var_name);
}
```
2019-03-20 05:05:03 -05:00
-- Remove `dbg!`
```rust
// before:
fn foo(n: usize) {
if let Some(_) = dbg!(n.<|>checked_sub(4)) {
// ...
}
}
// after:
fn foo(n: usize) {
if let Some(_) = n.<|>checked_sub(4) {
// ...
}
}
```
2019-03-20 04:17:12 -05:00
- Replace if-let with match:
```rust
// before:
impl VariantData {
pub fn is_struct(&self) -> bool {
if <|>let VariantData::Struct(..) = *self {
true
} else {
false
}
}
}
// after:
impl VariantData {
pub fn is_struct(&self) -> bool {
<|>match *self {
VariantData::Struct(..) => true,
_ => false,
}
}
}
```
- Split import
```rust
// before:
use algo:<|>:visitor::{Visitor, visit};
//after:
use algo::{<|>visitor::{Visitor, visit}};
```