about summary refs log tree commit diff
path: root/docs
diff options
context:
space:
mode:
authorMikhail Rakhmanov <rakhmanov.m@gmail.com>2020-06-03 19:26:01 +0200
committerMikhail Rakhmanov <rakhmanov.m@gmail.com>2020-06-03 19:26:01 +0200
commit6a0083a519680e8d16bde5d7c1940c8dd6d4e9d4 (patch)
tree2b377141d722257cfea18e74b955aea1a8f6cc1a /docs
parent1f7de306f547ecb394a34445fd6ac1d6bc8ab439 (diff)
parent794f6da821c5d6e2490b996baffe162e4753262d (diff)
downloadrust-6a0083a519680e8d16bde5d7c1940c8dd6d4e9d4.tar.gz
rust-6a0083a519680e8d16bde5d7c1940c8dd6d4e9d4.zip
Merge branch 'master' into compute-lazy-assits
# Conflicts:
#	crates/rust-analyzer/src/main_loop/handlers.rs
#	crates/rust-analyzer/src/to_proto.rs
Diffstat (limited to 'docs')
-rw-r--r--docs/dev/README.md105
-rw-r--r--docs/user/generated_assists.adoc1015
-rw-r--r--docs/user/generated_features.adoc298
-rw-r--r--docs/user/manual.adoc51
4 files changed, 155 insertions, 1314 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 65cc9fc12c0..1de5a2aab1d 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -30,7 +30,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0
 
 * [good-first-issue](https://github.com/rust-analyzer/rust-analyzer/labels/good%20first%20issue)
   are good issues to get into the project.
-* [E-mentor](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-mentor)
+* [E-has-instructions](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-has-instructions)
   issues have links to the code in question and tests.
 * [E-easy](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy),
   [E-medium](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-medium),
@@ -117,6 +117,109 @@ Additionally, I use `cargo run --release -p rust-analyzer -- analysis-stats
 path/to/some/rust/crate` to run a batch analysis. This is primarily useful for
 performance optimizations, or for bug minimization.
 
+# Code Style & Review Process
+
+Our approach to "clean code" is two fold:
+
+* We generally don't block PRs on style changes.
+* At the same time, all code in rust-analyzer is constantly refactored.
+
+It is explicitly OK for reviewer to flag only some nits in the PR, and than send a follow up cleanup PR for things which are easier to explain by example, cc-ing the original author.
+Sending small cleanup PRs (like rename a single local variable) is encouraged.
+
+## Scale of Changes
+
+Everyone knows that it's better to send small & focused pull requests.
+The problem is, sometimes you *have* to, eg, rewrite the whole compiler, and that just doesn't fit into a set of isolated PRs.
+
+The main thing too keep an eye on is the boundaries between various components.
+There are three kinds of changes:
+
+1. Internals of a single component are changed.
+   Specifically, you don't change any `pub` items.
+   A good example here would be an addition of a new assist.
+
+2. API of a component is expanded.
+   Specifically, you add a new `pub` function which wasn't there before.
+   A good example here would be expansion of assist API, for example, to implement lazy assists or assists groups.
+
+3. A new dependency between components is introduced.
+   Specifically, you add a `pub use` reexport from another crate or you add a new line to `[dependencies]` section of `Cargo.toml`.
+   A good example here would be adding reference search capability to the assists crates.
+
+For the first group, the change is generally merged as long as:
+
+* it works for the happy case,
+* it has tests,
+* it doesn't panic for unhappy case.
+
+For the second group, the change would be subjected to quite a bit of scrutiny and iteration.
+The new API needs to be right (or at least easy to change later).
+The actual implementation doesn't matter that much.
+It's very important to minimize the amount of changed lines of code for changes of the second kind.
+Often, you start doing change of the first kind, only to realise that you need to elevate to a change of the second kind.
+In this case, we'll probably ask you to split API changes into a separate PR.
+
+Changes of the third group should be pretty rare, so we don't specify any specific process for them.
+That said, adding an innocent-looking `pub use` is a very simple way to break encapsulation, keep an eye on it!
+
+Note: if you enjoyed this abstract hand-waving about boundaries, you might appreciate
+https://www.tedinski.com/2018/02/06/system-boundaries.html
+
+## Order of Imports
+
+We separate import groups with blank lines
+
+```
+mod x;
+mod y;
+
+use std::{ ... }
+
+use crate_foo::{ ... }
+use crate_bar::{ ... }
+
+use crate::{}
+
+use super::{} // but prefer `use crate::`
+```
+
+## Order of Items
+
+Optimize for the reader who sees the file for the first time, and wants to get the general idea about what's going on.
+People read things from top to bottom, so place most important things first.
+
+Specifically, if all items except one are private, always put the non-private item on top.
+
+Put `struct`s and `enum`s first, functions and impls last.
+
+Do
+
+```
+// Good
+struct Foo {
+  bars: Vec<Bar>
+}
+
+struct Bar;
+```
+
+rather than
+
+```
+// Not as good
+struct Bar;
+
+struct Foo {
+  bars: Vec<Bar>
+}
+```
+
+## Documentation
+
+For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines.
+If the line is too long, you want to split the sentence in two :-)
+
 # Logging
 
 Logging is done by both rust-analyzer and VS Code, so it might be tricky to
diff --git a/docs/user/generated_assists.adoc b/docs/user/generated_assists.adoc
deleted file mode 100644
index 4d2fb31d484..00000000000
--- a/docs/user/generated_assists.adoc
+++ /dev/null
@@ -1,1015 +0,0 @@
-[discrete]
-=== `add_custom_impl`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_custom_impl.rs#L14[add_custom_impl.rs]
-
-Adds impl block for derived trait.
-
-.Before
-```rust
-#[derive(Deb┃ug, Display)]
-struct S;
-```
-
-.After
-```rust
-#[derive(Display)]
-struct S;
-
-impl Debug for S {
-    $0
-}
-```
-
-
-[discrete]
-=== `add_derive`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_derive.rs#L9[add_derive.rs]
-
-Adds a new `#[derive()]` clause to a struct or enum.
-
-.Before
-```rust
-struct Point {
-    x: u32,
-    y: u32,┃
-}
-```
-
-.After
-```rust
-#[derive($0)]
-struct Point {
-    x: u32,
-    y: u32,
-}
-```
-
-
-[discrete]
-=== `add_explicit_type`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_explicit_type.rs#L9[add_explicit_type.rs]
-
-Specify type for a let binding.
-
-.Before
-```rust
-fn main() {
-    let x┃ = 92;
-}
-```
-
-.After
-```rust
-fn main() {
-    let x: i32 = 92;
-}
-```
-
-
-[discrete]
-=== `add_from_impl_for_enum`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs#L7[add_from_impl_for_enum.rs]
-
-Adds a From impl for an enum variant with one tuple field.
-
-.Before
-```rust
-enum A { ┃One(u32) }
-```
-
-.After
-```rust
-enum A { One(u32) }
-
-impl From<u32> for A {
-    fn from(v: u32) -> Self {
-        A::One(v)
-    }
-}
-```
-
-
-[discrete]
-=== `add_function`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_function.rs#L19[add_function.rs]
-
-Adds a stub function with a signature matching the function under the cursor.
-
-.Before
-```rust
-struct Baz;
-fn baz() -> Baz { Baz }
-fn foo() {
-    bar┃("", baz());
-}
-
-```
-
-.After
-```rust
-struct Baz;
-fn baz() -> Baz { Baz }
-fn foo() {
-    bar("", baz());
-}
-
-fn bar(arg: &str, baz: Baz) {
-    ${0:todo!()}
-}
-
-```
-
-
-[discrete]
-=== `add_hash`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L65[raw_string.rs]
-
-Adds a hash to a raw string literal.
-
-.Before
-```rust
-fn main() {
-    r#"Hello,┃ World!"#;
-}
-```
-
-.After
-```rust
-fn main() {
-    r##"Hello, World!"##;
-}
-```
-
-
-[discrete]
-=== `add_impl`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_impl.rs#L6[add_impl.rs]
-
-Adds a new inherent impl for a type.
-
-.Before
-```rust
-struct Ctx<T: Clone> {
-    data: T,┃
-}
-```
-
-.After
-```rust
-struct Ctx<T: Clone> {
-    data: T,
-}
-
-impl<T: Clone> Ctx<T> {
-    $0
-}
-```
-
-
-[discrete]
-=== `add_impl_default_members`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_missing_impl_members.rs#L64[add_missing_impl_members.rs]
-
-Adds scaffold for overriding default impl members.
-
-.Before
-```rust
-trait Trait {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl Trait for () {
-    Type X = ();
-    fn foo(&self) {}┃
-
-}
-```
-
-.After
-```rust
-trait Trait {
-    Type X;
-    fn foo(&self);
-    fn bar(&self) {}
-}
-
-impl Trait for () {
-    Type X = ();
-    fn foo(&self) {}
-    $0fn bar(&self) {}
-
-}
-```
-
-
-[discrete]
-=== `add_impl_missing_members`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_missing_impl_members.rs#L24[add_missing_impl_members.rs]
-
-Adds scaffold for required impl members.
-
-.Before
-```rust
-trait Trait<T> {
-    Type X;
-    fn foo(&self) -> T;
-    fn bar(&self) {}
-}
-
-impl Trait<u32> for () {┃
-
-}
-```
-
-.After
-```rust
-trait Trait<T> {
-    Type X;
-    fn foo(&self) -> T;
-    fn bar(&self) {}
-}
-
-impl Trait<u32> for () {
-    fn foo(&self) -> u32 {
-        ${0:todo!()}
-    }
-
-}
-```
-
-
-[discrete]
-=== `add_new`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_new.rs#L12[add_new.rs]
-
-Adds a new inherent impl for a type.
-
-.Before
-```rust
-struct Ctx<T: Clone> {
-     data: T,┃
-}
-```
-
-.After
-```rust
-struct Ctx<T: Clone> {
-     data: T,
-}
-
-impl<T: Clone> Ctx<T> {
-    fn $0new(data: T) -> Self { Self { data } }
-}
-
-```
-
-
-[discrete]
-=== `add_turbo_fish`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/add_turbo_fish.rs#L10[add_turbo_fish.rs]
-
-Adds `::<_>` to a call of a generic method or function.
-
-.Before
-```rust
-fn make<T>() -> T { todo!() }
-fn main() {
-    let x = make┃();
-}
-```
-
-.After
-```rust
-fn make<T>() -> T { todo!() }
-fn main() {
-    let x = make::<${0:_}>();
-}
-```
-
-
-[discrete]
-=== `apply_demorgan`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/apply_demorgan.rs#L5[apply_demorgan.rs]
-
-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)`.
-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
-fn main() {
-    if x != 4 ||┃ !y {}
-}
-```
-
-.After
-```rust
-fn main() {
-    if !(x == 4 && y) {}
-}
-```
-
-
-[discrete]
-=== `auto_import`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/auto_import.rs#L18[auto_import.rs]
-
-If the name is unresolved, provides all possible imports for it.
-
-.Before
-```rust
-fn main() {
-    let map = HashMap┃::new();
-}
-```
-
-.After
-```rust
-use std::collections::HashMap;
-
-fn main() {
-    let map = HashMap::new();
-}
-```
-
-
-[discrete]
-=== `change_return_type_to_result`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/change_return_type_to_result.rs#L8[change_return_type_to_result.rs]
-
-Change the function's return type to Result.
-
-.Before
-```rust
-fn foo() -> i32┃ { 42i32 }
-```
-
-.After
-```rust
-fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
-```
-
-
-[discrete]
-=== `change_visibility`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/change_visibility.rs#L14[change_visibility.rs]
-
-Adds or changes existing visibility specifier.
-
-.Before
-```rust
-┃fn frobnicate() {}
-```
-
-.After
-```rust
-pub(crate) fn frobnicate() {}
-```
-
-
-[discrete]
-=== `convert_to_guarded_return`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/early_return.rs#L21[early_return.rs]
-
-Replace a large conditional with a guarded return.
-
-.Before
-```rust
-fn main() {
-    ┃if cond {
-        foo();
-        bar();
-    }
-}
-```
-
-.After
-```rust
-fn main() {
-    if !cond {
-        return;
-    }
-    foo();
-    bar();
-}
-```
-
-
-[discrete]
-=== `fill_match_arms`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/fill_match_arms.rs#L14[fill_match_arms.rs]
-
-Adds missing clauses to a `match` expression.
-
-.Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        ┃
-    }
-}
-```
-
-.After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        $0Action::Move { distance } => {}
-        Action::Stop => {}
-    }
-}
-```
-
-
-[discrete]
-=== `fix_visibility`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/fix_visibility.rs#L13[fix_visibility.rs]
-
-Makes inaccessible item public.
-
-.Before
-```rust
-mod m {
-    fn frobnicate() {}
-}
-fn main() {
-    m::frobnicate┃() {}
-}
-```
-
-.After
-```rust
-mod m {
-    $0pub(crate) fn frobnicate() {}
-}
-fn main() {
-    m::frobnicate() {}
-}
-```
-
-
-[discrete]
-=== `flip_binexpr`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/flip_binexpr.rs#L5[flip_binexpr.rs]
-
-Flips operands of a binary expression.
-
-.Before
-```rust
-fn main() {
-    let _ = 90 +┃ 2;
-}
-```
-
-.After
-```rust
-fn main() {
-    let _ = 2 + 90;
-}
-```
-
-
-[discrete]
-=== `flip_comma`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/flip_comma.rs#L5[flip_comma.rs]
-
-Flips two comma-separated items.
-
-.Before
-```rust
-fn main() {
-    ((1, 2),┃ (3, 4));
-}
-```
-
-.After
-```rust
-fn main() {
-    ((3, 4), (1, 2));
-}
-```
-
-
-[discrete]
-=== `flip_trait_bound`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/flip_trait_bound.rs#L9[flip_trait_bound.rs]
-
-Flips two trait bounds.
-
-.Before
-```rust
-fn foo<T: Clone +┃ Copy>() { }
-```
-
-.After
-```rust
-fn foo<T: Copy + Clone>() { }
-```
-
-
-[discrete]
-=== `inline_local_variable`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/inline_local_variable.rs#L13[inline_local_variable.rs]
-
-Inlines local variable.
-
-.Before
-```rust
-fn main() {
-    let x┃ = 1 + 2;
-    x * 4;
-}
-```
-
-.After
-```rust
-fn main() {
-    (1 + 2) * 4;
-}
-```
-
-
-[discrete]
-=== `introduce_named_lifetime`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/introduce_named_lifetime.rs#L12[introduce_named_lifetime.rs]
-
-Change an anonymous lifetime to a named lifetime.
-
-.Before
-```rust
-impl Cursor<'_┃> {
-    fn node(self) -> &SyntaxNode {
-        match self {
-            Cursor::Replace(node) | Cursor::Before(node) => node,
-        }
-    }
-}
-```
-
-.After
-```rust
-impl<'a> Cursor<'a> {
-    fn node(self) -> &SyntaxNode {
-        match self {
-            Cursor::Replace(node) | Cursor::Before(node) => node,
-        }
-    }
-}
-```
-
-
-[discrete]
-=== `introduce_variable`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/introduce_variable.rs#L14[introduce_variable.rs]
-
-Extracts subexpression into a variable.
-
-.Before
-```rust
-fn main() {
-    ┃(1 + 2)┃ * 4;
-}
-```
-
-.After
-```rust
-fn main() {
-    let $0var_name = (1 + 2);
-    var_name * 4;
-}
-```
-
-
-[discrete]
-=== `invert_if`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/invert_if.rs#L12[invert_if.rs]
-
-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
-fn main() {
-    if┃ !y { A } else { B }
-}
-```
-
-.After
-```rust
-fn main() {
-    if y { B } else { A }
-}
-```
-
-
-[discrete]
-=== `make_raw_string`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L10[raw_string.rs]
-
-Adds `r#` to a plain string literal.
-
-.Before
-```rust
-fn main() {
-    "Hello,┃ World!";
-}
-```
-
-.After
-```rust
-fn main() {
-    r#"Hello, World!"#;
-}
-```
-
-
-[discrete]
-=== `make_usual_string`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L39[raw_string.rs]
-
-Turns a raw string into a plain string.
-
-.Before
-```rust
-fn main() {
-    r#"Hello,┃ "World!""#;
-}
-```
-
-.After
-```rust
-fn main() {
-    "Hello, \"World!\"";
-}
-```
-
-
-[discrete]
-=== `merge_imports`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/merge_imports.rs#L14[merge_imports.rs]
-
-Merges two imports with a common prefix.
-
-.Before
-```rust
-use std::┃fmt::Formatter;
-use std::io;
-```
-
-.After
-```rust
-use std::{fmt::Formatter, io};
-```
-
-
-[discrete]
-=== `merge_match_arms`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/merge_match_arms.rs#L11[merge_match_arms.rs]
-
-Merges identical match arms.
-
-.Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        ┃Action::Move(..) => foo(),
-        Action::Stop => foo(),
-    }
-}
-```
-
-.After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move(..) | Action::Stop => foo(),
-    }
-}
-```
-
-
-[discrete]
-=== `move_arm_cond_to_match_guard`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/move_guard.rs#L56[move_guard.rs]
-
-Moves if expression from match arm body into a guard.
-
-.Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } => ┃if distance > 10 { foo() },
-        _ => (),
-    }
-}
-```
-
-.After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } if distance > 10 => foo(),
-        _ => (),
-    }
-}
-```
-
-
-[discrete]
-=== `move_bounds_to_where_clause`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/move_bounds.rs#L10[move_bounds.rs]
-
-Moves inline type bounds to a where clause.
-
-.Before
-```rust
-fn apply<T, U, ┃F: FnOnce(T) -> U>(f: F, x: T) -> U {
-    f(x)
-}
-```
-
-.After
-```rust
-fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
-    f(x)
-}
-```
-
-
-[discrete]
-=== `move_guard_to_arm_body`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/move_guard.rs#L8[move_guard.rs]
-
-Moves match guard into match arm body.
-
-.Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } ┃if distance > 10 => foo(),
-        _ => (),
-    }
-}
-```
-
-.After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } => if distance > 10 { foo() },
-        _ => (),
-    }
-}
-```
-
-
-[discrete]
-=== `remove_dbg`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/remove_dbg.rs#L8[remove_dbg.rs]
-
-Removes `dbg!()` macro call.
-
-.Before
-```rust
-fn main() {
-    ┃dbg!(92);
-}
-```
-
-.After
-```rust
-fn main() {
-    92;
-}
-```
-
-
-[discrete]
-=== `remove_hash`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/raw_string.rs#L89[raw_string.rs]
-
-Removes a hash from a raw string literal.
-
-.Before
-```rust
-fn main() {
-    r#"Hello,┃ World!"#;
-}
-```
-
-.After
-```rust
-fn main() {
-    r"Hello, World!";
-}
-```
-
-
-[discrete]
-=== `remove_mut`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/remove_mut.rs#L5[remove_mut.rs]
-
-Removes the `mut` keyword.
-
-.Before
-```rust
-impl Walrus {
-    fn feed(&mut┃ self, amount: u32) {}
-}
-```
-
-.After
-```rust
-impl Walrus {
-    fn feed(&self, amount: u32) {}
-}
-```
-
-
-[discrete]
-=== `reorder_fields`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/reorder_fields.rs#L10[reorder_fields.rs]
-
-Reorder the fields of record literals and record patterns in the same order as in
-the definition.
-
-.Before
-```rust
-struct Foo {foo: i32, bar: i32};
-const test: Foo = ┃Foo {bar: 0, foo: 1}
-```
-
-.After
-```rust
-struct Foo {foo: i32, bar: i32};
-const test: Foo = Foo {foo: 1, bar: 0}
-```
-
-
-[discrete]
-=== `replace_if_let_with_match`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_if_let_with_match.rs#L13[replace_if_let_with_match.rs]
-
-Replaces `if let` with an else branch with a `match` expression.
-
-.Before
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    ┃if let Action::Move { distance } = action {
-        foo(distance)
-    } else {
-        bar()
-    }
-}
-```
-
-.After
-```rust
-enum Action { Move { distance: u32 }, Stop }
-
-fn handle(action: Action) {
-    match action {
-        Action::Move { distance } => foo(distance),
-        _ => bar(),
-    }
-}
-```
-
-
-[discrete]
-=== `replace_let_with_if_let`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_let_with_if_let.rs#L14[replace_let_with_if_let.rs]
-
-Replaces `let` with an `if-let`.
-
-.Before
-```rust
-
-fn main(action: Action) {
-    ┃let x = compute();
-}
-
-fn compute() -> Option<i32> { None }
-```
-
-.After
-```rust
-
-fn main(action: Action) {
-    if let Some(x) = compute() {
-    }
-}
-
-fn compute() -> Option<i32> { None }
-```
-
-
-[discrete]
-=== `replace_qualified_name_with_use`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs#L6[replace_qualified_name_with_use.rs]
-
-Adds a use statement for a given fully-qualified name.
-
-.Before
-```rust
-fn process(map: std::collections::┃HashMap<String, String>) {}
-```
-
-.After
-```rust
-use std::collections::HashMap;
-
-fn process(map: HashMap<String, String>) {}
-```
-
-
-[discrete]
-=== `replace_unwrap_with_match`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs#L17[replace_unwrap_with_match.rs]
-
-Replaces `unwrap` a `match` expression. Works for Result and Option.
-
-.Before
-```rust
-enum Result<T, E> { Ok(T), Err(E) }
-fn main() {
-    let x: Result<i32, i32> = Result::Ok(92);
-    let y = x.┃unwrap();
-}
-```
-
-.After
-```rust
-enum Result<T, E> { Ok(T), Err(E) }
-fn main() {
-    let x: Result<i32, i32> = Result::Ok(92);
-    let y = match x {
-        Ok(a) => a,
-        $0_ => unreachable!(),
-    };
-}
-```
-
-
-[discrete]
-=== `split_import`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/split_import.rs#L7[split_import.rs]
-
-Wraps the tail of import into braces.
-
-.Before
-```rust
-use std::┃collections::HashMap;
-```
-
-.After
-```rust
-use std::{collections::HashMap};
-```
-
-
-[discrete]
-=== `unwrap_block`
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_assists/src/handlers/unwrap_block.rs#L9[unwrap_block.rs]
-
-This assist removes if...else, for, while and loop control statements to just keep the body.
-
-.Before
-```rust
-fn foo() {
-    if true {┃
-        println!("foo");
-    }
-}
-```
-
-.After
-```rust
-fn foo() {
-    println!("foo");
-}
-```
diff --git a/docs/user/generated_features.adoc b/docs/user/generated_features.adoc
deleted file mode 100644
index 12812fa0be7..00000000000
--- a/docs/user/generated_features.adoc
+++ /dev/null
@@ -1,298 +0,0 @@
-=== Expand Macro Recursively
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/expand_macro.rs#L15[expand_macro.rs]
-
-Shows the full macro expansion of the macro at current cursor.
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Expand macro recursively**
-|===
-
-
-=== Extend Selection
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/extend_selection.rs#L15[extend_selection.rs]
-
-Extends the current selection to the encompassing syntactic construct
-(expression, statement, item, module, etc). It works with multiple cursors.
-
-|===
-| Editor  | Shortcut
-
-| VS Code | kbd:[Ctrl+Shift+→]
-|===
-
-
-=== File Structure
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/display/structure.rs#L17[structure.rs]
-
-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
-
-|===
-| Editor  | Shortcut
-
-| VS Code | kbd:[Ctrl+Shift+O]
-|===
-
-
-=== Go to Definition
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_definition.rs#L18[goto_definition.rs]
-
-Navigates to the definition of an identifier.
-
-|===
-| Editor  | Shortcut
-
-| VS Code | kbd:[F12]
-|===
-
-
-=== Go to Implementation
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_implementation.rs#L7[goto_implementation.rs]
-
-Navigates to the impl block of structs, enums or traits. Also implemented as a code lens.
-
-|===
-| Editor  | Shortcut
-
-| VS Code | kbd:[Ctrl+F12]
-|===
-
-
-=== Go to Type Definition
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/goto_type_definition.rs#L6[goto_type_definition.rs]
-
-Navigates to the type of an identifier.
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Go to Type Definition*
-|===
-
-
-=== Hover
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/hover.rs#L63[hover.rs]
-
-Shows additional information, like type of an expression or documentation for definition when "focusing" code.
-Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
-
-
-=== Inlay Hints
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/inlay_hints.rs#L40[inlay_hints.rs]
-
-rust-analyzer shows additional information inline with the source code.
-Editors usually render this using read-only virtual text snippets interspersed with code.
-
-rust-analyzer shows hits for
-
-* types of local variables
-* names of function arguments
-* types of chained expressions
-
-**Note:** VS Code does not have native support for inlay hints https://github.com/microsoft/vscode/issues/16221[yet] and the hints are implemented using decorations.
-This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird:
-https://github.com/rust-analyzer/rust-analyzer/issues/1623[1], https://github.com/rust-analyzer/rust-analyzer/issues/3453[2].
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Toggle inlay hints*
-|===
-
-
-=== Join Lines
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/join_lines.rs#L12[join_lines.rs]
-
-Join selected lines into one, smartly fixing up whitespace, trailing commas, and braces.
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Join lines**
-|===
-
-
-=== Magic Completions
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/completion.rs#L38[completion.rs]
-
-In addition to usual reference completion, rust-analyzer provides some ✨magic✨
-completions as well:
-
-Keywords like `if`, `else` `while`, `loop` are completed with braces, and cursor
-is placed at the appropriate position. Even though `if` is easy to type, you
-still want to complete it, to get ` { }` for free! `return` is inserted with a
-space or `;` depending on the return type of the function.
-
-When completing a function call, `()` are automatically inserted. If a function
-takes arguments, the cursor is positioned inside the parenthesis.
-
-There are postfix completions, which can be triggered by typing something like
-`foo().if`. The word after `.` determines postfix completion. Possible variants are:
-
-- `expr.if` -> `if expr {}` or `if let ... {}` for `Option` or `Result`
-- `expr.match` -> `match expr {}`
-- `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result`
-- `expr.ref` -> `&expr`
-- `expr.refm` -> `&mut expr`
-- `expr.not` -> `!expr`
-- `expr.dbg` -> `dbg!(expr)`
-
-There also snippet completions:
-
-.Expressions
-- `pd` -> `println!("{:?}")`
-- `ppd` -> `println!("{:#?}")`
-
-.Items
-- `tfn` -> `#[test] fn f(){}`
-- `tmod` ->
-```rust
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_fn() {}
-}
-```
-
-
-=== Matching Brace
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/matching_brace.rs#L3[matching_brace.rs]
-
-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.
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Find matching brace**
-|===
-
-
-=== On Typing Assists
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/typing.rs#L35[typing.rs]
-
-Some features trigger on typing certain characters:
-
-- 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
-
-
-=== Parent Module
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/parent_module.rs#L12[parent_module.rs]
-
-Navigates to the parent module of the current module.
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Locate parent module**
-|===
-
-
-=== Run
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/runnables.rs#L45[runnables.rs]
-
-Shows a 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!
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Run**
-|===
-
-
-=== Semantic Syntax Highlighting
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/syntax_highlighting.rs#L33[syntax_highlighting.rs]
-
-rust-analyzer highlights the code semantically.
-For example, `bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait.
-rust-analyzer does not specify colors directly, instead it assigns tag (like `struct`) and a set of modifiers (like `declaration`) to each token.
-It's up to the client to map those to specific colors.
-
-The general rule is that a reference to an entity gets colored the same way as the entity itself.
-We also give special modifier for `mut` and `&mut` local variables.
-
-
-=== Show Syntax Tree
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/syntax_tree.rs#L9[syntax_tree.rs]
-
-Shows the parse tree of the current file. It exists mostly for debugging
-rust-analyzer itself.
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Show Syntax Tree**
-|===
-
-
-=== Status
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/status.rs#L27[status.rs]
-
-Shows internal statistic about memory usage of rust-analyzer.
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Status**
-|===
-
-
-=== Structural Seach and Replace
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/ssr.rs#L26[ssr.rs]
-
-Search and replace with named wildcards that will match any expression.
-The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`.
-A `$<name>:expr` placeholder in the search pattern will match any expression and `$<name>` will reference it in the replacement.
-Available via the command `rust-analyzer.ssr`.
-
-```rust
-// Using structural search replace command [foo($a:expr, $b:expr) ==>> ($a).foo($b)]
-
-// BEFORE
-String::from(foo(y + 5, z))
-
-// AFTER
-String::from((y + 5).foo(z))
-```
-
-|===
-| Editor  | Action Name
-
-| VS Code | **Rust Analyzer: Structural Search Replace**
-|===
-
-
-=== Workspace Symbol
-**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide_db/src/symbol_index.rs#L113[symbol_index.rs]
-
-Uses fuzzy-search to find types, modules and functions by name across your
-project and dependencies. This is **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, including `stdlib`
-- `foo#*` searches for `foo` function among dependencies
-
-That is, `#` switches from "types" to all symbols, `*` switches from the current
-workspace to dependencies.
-
-|===
-| Editor  | Shortcut
-
-| VS Code | kbd:[Ctrl+T]
-|===
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 202783fd953..ea714f49add 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -269,6 +269,57 @@ Gnome Builder currently has support for RLS, and there's no way to configure the
 1. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`).
 2. Enable the Rust Builder plugin.
 
+== Non-Cargo Based Projects
+
+rust-analyzer does not require Cargo.
+However, if you use some other build system, you'll have to describe the structure of your project for rust-analyzer in the `rust-project.json` format:
+
+[source,TypeScript]
+----
+interface JsonProject {
+   /// The set of paths containing the crates for this project.
+   /// Any `Crate` must be nested inside some `root`.
+   roots: string[];
+   /// The set of crates comprising the current project.
+   /// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such).
+   crates: Crate[];
+}
+
+interface Crate {
+    /// Path to the root module of the crate.
+    root_module: string;
+    /// Edition of the crate.
+    edition: "2015" | "2018";
+    /// Dependencies
+    deps: Dep[];
+    /// The set of cfgs activated for a given crate, like `["unix", "feature=foo", "feature=bar"]`.
+    cfg: string[];
+
+    /// value of the OUT_DIR env variable.
+    out_dir?: string;
+    /// For proc-macro crates, path to compiles proc-macro (.so file).
+    proc_macro_dylib_path?: string;
+}
+
+interface Dep {
+    /// Index of a crate in the `crates` array.
+    crate: number,
+    /// Name as should appear in the (implicit) `extern crate name` declaration.
+    name: string,
+}
+----
+
+This format is provisional and subject to change.
+Specifically, the `roots` setup will be different eventually.
+
+There are tree ways to feed `rust-project.json` to rust-analyzer:
+
+* Place `rust-project.json` file at the root of the project, and rust-anlayzer will discover it.
+* Specify `"rust-analyzer.linkedProjects": [ "path/to/rust-project.json" ]` in the settings (and make sure that your LSP client sends settings as a part of initialize request).
+* Specify `"rust-analyzer.linkedProjects": [ { "roots": [...], "crates": [...] }]` inline.
+
+See https://github.com/rust-analyzer/rust-project.json-example for a small example.
+
 == Features
 
 include::./generated_features.adoc[]