diff --git a/docs/user/features.md b/docs/user/features.md
index 5df606aee0..aa3bf5157e 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -1,52 +1,30 @@
-This documents is an index of features that rust-analyzer language server provides.
+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 Ctrl+Shift+P to search for the corresponding action.
-### Go to symbol in workspace ctrl+t
+### Workspace Symbol ctrl+t
-It mostly works on top of the built-in LSP functionality, however `#` and `*`
-symbols can be used to narrow down the search. Specifically,
+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,
-- `#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.
+- `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.
That is, `#` switches from "types" to all symbols, `*` switches from the current
workspace to dependencies.
-### Commands ctrl+shift+p
+### Document Symbol ctrl+shift+o
-#### Show Rust Syntax Tree
-
-Shows the parse tree of the current file. It exists mostly for debugging
-rust-analyzer itself.
-
-#### Extend Selection
-
-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, its super-useful! Expected to be upstreamed to LSP soonish:
-https://github.com/Microsoft/language-server-protocol/issues/613
-
-#### Matching Brace
-
-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.
-
-#### Parent Module
-
-Navigates to the parent module of the current module.
-
-#### Join Lines
-
-Join selected lines into one, smartly fixing up whitespace and trailing commas.
-
-#### 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!
+Provides a tree of the symbols defined in the file. Can be used to
+* fuzzy search symbol in a file (super useful)
+* draw breadcrumbs to describe the context around the cursor
+* draw outline of the file
### On Typing Assists
@@ -56,24 +34,52 @@ Some features trigger on typing certain characters:
- Enter inside comments automatically inserts `///`
- typing `.` in a chain method call auto-indents
+### Commands ctrl+shift+p
+#### Extend Selection
+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
+#### 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!
+
+#### Parent Module
+
+Navigates to the parent module of the current module.
+
+#### Matching Brace
+
+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.
+
+#### Join Lines
+
+Join selected lines into one, smartly fixing up whitespace and trailing commas.
+
+#### Show Syntax Tree
+
+Shows the parse tree of the current file. It exists mostly for debugging
+rust-analyzer itself.
+
+#### Status
+
+Shows internal statistic about memory usage of rust-analyzer
+
+#### Run garbage collection
+
+Manually triggers GC
### 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.
-
-
-- Flip `,`
-
-```rust
-// before:
-fn foo(x: usize,<|> dim: (usize, usize))
-// after:
-fn foo(dim: (usize, usize), x: usize)
-```
+the VS Code side to be able to position cursor. `<|>` signifies cursor
- Add `#[derive]`
@@ -106,14 +112,147 @@ impl<'a, T: Debug> Foo<'a, T> {
}
```
-- Change visibility
+- Add missing `impl` members
```rust
// before:
-fn<|> foo() {}
+trait Foo {
+ fn foo(&self);
+ fn bar(&self);
+ fn baz(&self);
+}
-// after
-pub(crate) fn foo() {}
+struct S;
+
+impl Foo for S {
+ fn bar(&self) {}
+ <|>
+}
+
+// after:
+trait Foo {
+ fn foo(&self);
+ fn bar(&self);
+ fn baz(&self);
+}
+
+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) {}
```
- Introduce variable:
@@ -131,6 +270,24 @@ fn foo() {
}
```
+-- 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) {
+ // ...
+ }
+}
+```
+
- Replace if-let with match:
```rust
@@ -164,5 +321,3 @@ use algo:<|>:visitor::{Visitor, visit};
//after:
use algo::{<|>visitor::{Visitor, visit}};
```
-
-