From d605ec9c321392d9c7ee4b440c560e1e405d92e6 Mon Sep 17 00:00:00 2001 From: veetaha Date: Sun, 31 May 2020 05:13:08 +0300 Subject: Change Runnable.bin -> Runnable.kind As per matklad, we now pass the responsibility for finding the binary to the frontend. Also, added caching for finding the binary path to reduce the amount of filesystem interactions. --- docs/dev/lsp-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index dbc95be38..d06da355d 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -417,7 +417,7 @@ interface Runnable { /// The label to show in the UI. label: string; /// The following fields describe a process to spawn. - bin: string; + kind: "cargo" | "rustc" | "rustup"; args: string[]; /// Args for cargo after `--`. extraArgs: string[]; -- cgit v1.2.3 From a83ab820a4633bac718ee0fd11f06d1b3142be6b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 2 Jun 2020 17:34:18 +0200 Subject: Spec better runnables --- docs/dev/lsp-extensions.md | 80 +++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 36 deletions(-) (limited to 'docs') diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index b7237ee90..647cf6107 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -311,6 +311,50 @@ Moreover, it would be cool if editors didn't need to implement even basic langua This is how `SelectionRange` request works. * Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs? +## Runnables + +**Issue:** https://github.com/microsoft/language-server-protocol/issues/944 + +**Server Capability:** `{ "runnables": { "kinds": string[] } }` + +This request is send from client to server to get the list of things that can be run (tests, binaries, `cargo check -p`). + +**Method:** `experimental/runnables` + +**Request:** + +```typescript +interface RunnablesParams { + textDocument: TextDocumentIdentifier; + /// If null, compute runnables for the whole file. + position?: Position; +} +``` + +**Response:** `Runnable[]` + +```typescript +interface Runnable { + label: string; + /// If this Runnable is associated with a specific function/module, etc, the location of this item + location?: LocationLink; + /// Running things is necessary technology specific, `kind` needs to be advertised via server capabilities, + // the type of `args` is specific to `kind`. The actual running is handled by the client. + kind: string; + args: any; +} +``` + +rust-analyzer supports only one `kind`, `"cargo"`. The `args` for `"cargo"` look like this: + +```typescript +{ + workspaceRoot?: string; + cargoArgs: string[]; + executableArgs: string[]; +} +``` + ## Analyzer Status **Method:** `rust-analyzer/analyzerStatus` @@ -399,39 +443,3 @@ interface InlayHint { label: string, } ``` - -## Runnables - -**Method:** `rust-analyzer/runnables` - -This request is send from client to server to get the list of things that can be run (tests, binaries, `cargo check -p`). -Note that we plan to move this request to `experimental/runnables`, as it is not really Rust-specific, but the current API is not necessary the right one. -Upstream issue: https://github.com/microsoft/language-server-protocol/issues/944 - -**Request:** - -```typescript -interface RunnablesParams { - textDocument: TextDocumentIdentifier; - /// If null, compute runnables for the whole file. - position?: Position; -} -``` - -**Response:** `Runnable[]` - -```typescript -interface Runnable { - /// The range this runnable is applicable for. - range: lc.Range; - /// The label to show in the UI. - label: string; - /// The following fields describe a process to spawn. - kind: "cargo" | "rustc" | "rustup"; - args: string[]; - /// Args for cargo after `--`. - extraArgs: string[]; - env: { [key: string]: string }; - cwd: string | null; -} -``` -- cgit v1.2.3 From 994006585be6850b250b21aac76a58f1324cad5d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 2 Jun 2020 11:16:49 +0200 Subject: Start documenting review process --- docs/dev/README.md | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 65cc9fc12..1de5a2aab 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 +} + +struct Bar; +``` + +rather than + +``` +// Not as good +struct Bar; + +struct Foo { + bars: Vec +} +``` + +## 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 -- cgit v1.2.3 From ed866892640214d315d3e9503ccaed96ca87ccc0 Mon Sep 17 00:00:00 2001 From: Aaron Loucks Date: Wed, 3 Jun 2020 06:55:27 -0400 Subject: Update generated feature docs --- docs/user/generated_features.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/user/generated_features.adoc b/docs/user/generated_features.adoc index 12812fa0b..4b93b759f 100644 --- a/docs/user/generated_features.adoc +++ b/docs/user/generated_features.adoc @@ -76,7 +76,7 @@ Navigates to the type of an identifier. === Hover -**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/hover.rs#L63[hover.rs] +**Source:** https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_ide/src/hover.rs#L58[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. -- cgit v1.2.3 From fa019c8f562326a720d2ef9165626c4c5703f67b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 3 Jun 2020 14:48:38 +0200 Subject: Document rust-project.json --- docs/user/manual.adoc | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'docs') diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 202783fd9..ea714f49a 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[] -- cgit v1.2.3 From 5315934d888797432d62ec4a55303aeacb8cd286 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 3 Jun 2020 18:22:05 +0200 Subject: Don't store generated docs in the repo --- docs/user/generated_assists.adoc | 1015 ------------------------------------- docs/user/generated_features.adoc | 298 ----------- 2 files changed, 1313 deletions(-) delete mode 100644 docs/user/generated_assists.adoc delete mode 100644 docs/user/generated_features.adoc (limited to 'docs') diff --git a/docs/user/generated_assists.adoc b/docs/user/generated_assists.adoc deleted file mode 100644 index 4d2fb31d4..000000000 --- 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 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 { - data: T,┃ -} -``` - -.After -```rust -struct Ctx { - data: T, -} - -impl Ctx { - $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 { - Type X; - fn foo(&self) -> T; - fn bar(&self) {} -} - -impl Trait for () {┃ - -} -``` - -.After -```rust -trait Trait { - Type X; - fn foo(&self) -> T; - fn bar(&self) {} -} - -impl Trait 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 { - data: T,┃ -} -``` - -.After -```rust -struct Ctx { - data: T, -} - -impl Ctx { - 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 { todo!() } -fn main() { - let x = make┃(); -} -``` - -.After -```rust -fn make() -> 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 { 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() { } -``` - -.After -```rust -fn foo() { } -``` - - -[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 U>(f: F, x: T) -> U { - f(x) -} -``` - -.After -```rust -fn apply(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 { None } -``` - -.After -```rust - -fn main(action: Action) { - if let Some(x) = compute() { - } -} - -fn compute() -> Option { 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) {} -``` - -.After -```rust -use std::collections::HashMap; - -fn process(map: HashMap) {} -``` - - -[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 { Ok(T), Err(E) } -fn main() { - let x: Result = Result::Ok(92); - let y = x.┃unwrap(); -} -``` - -.After -```rust -enum Result { Ok(T), Err(E) } -fn main() { - let x: Result = 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 4b93b759f..000000000 --- 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#L58[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 ` ==>> `. -A `$:expr` placeholder in the search pattern will match any expression and `$` 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] -|=== -- cgit v1.2.3 From 1f7de306f547ecb394a34445fd6ac1d6bc8ab439 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Wed, 3 Jun 2020 18:57:50 +0200 Subject: Add documentation --- docs/dev/lsp-extensions.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'docs') diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 647cf6107..7f7940d0b 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -97,6 +97,30 @@ Invoking code action at this position will yield two code actions for importing * Is a fixed two-level structure enough? * Should we devise a general way to encode custom interaction protocols for GUI refactorings? +## Lazy assists with `ResolveCodeAction` + +**Issue:** https://github.com/microsoft/language-server-protocol/issues/787 + +**Client Capability** `{ "resolveCodeAction": boolean }` + +If this capability is set, the assists will be computed lazily. Thus `CodeAction` returned from the server will only contain `id` but not `edit` or `command` fields. The only exclusion from the rule is the diagnostic edits. + +After the client got the id, it should then call `experimental/resolveCodeAction` command on the server and provide the following payload: + +```typescript +interface ResolveCodeActionParams { + id: string; + codeActionParams: lc.CodeActionParams; +} +``` + +As a result of the command call the client will get the respective workspace edit (`lc.WorkspaceEdit`). + +### Unresolved Questions + +* Apply smarter filtering for ids? +* Upon `resolveCodeAction` command only call the assits which should be resolved and not all of them? + ## Parent Module **Issue:** https://github.com/microsoft/language-server-protocol/issues/1002 -- cgit v1.2.3 From 41ae7ed79f75d52179e3553e30e47709a82e693b Mon Sep 17 00:00:00 2001 From: Veetaha Date: Thu, 4 Jun 2020 01:48:47 +0300 Subject: Bufgix --- docs/dev/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 1de5a2aab..194a40e15 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -170,7 +170,7 @@ https://www.tedinski.com/2018/02/06/system-boundaries.html We separate import groups with blank lines -``` +```rust mod x; mod y; @@ -195,7 +195,7 @@ Put `struct`s and `enum`s first, functions and impls last. Do -``` +```rust // Good struct Foo { bars: Vec @@ -206,7 +206,7 @@ struct Bar; rather than -``` +```rust // Not as good struct Bar; -- cgit v1.2.3 From da7ec4b3398ffaf672a755bf57066e17ac42303a Mon Sep 17 00:00:00 2001 From: vsrs Date: Wed, 3 Jun 2020 14:34:11 +0300 Subject: Add hover actions LSP extension documentation. --- docs/dev/lsp-extensions.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'docs') diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 7f7940d0b..a0847dad3 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -467,3 +467,41 @@ interface InlayHint { label: string, } ``` + +## Hover Actions + +**Client Capability:** `{ "hoverActions": boolean }` + +If this capability is set, `Hover` request returned from the server might contain an additional field, `actions`: + +```typescript +interface Hover { + ... + actions?: CommandLinkGroup[]; +} + +interface CommandLink extends Command { + /** + * A tooltip for the command, when represented in the UI. + */ + tooltip?: string; +} + +interface CommandLinkGroup { + title?: string; + commands: CommandLink[]; +} +``` + +Such actions on the client side are appended to a hover bottom as command links: +``` + +-----------------------------+ + | Hover content | + | | + +-----------------------------+ + | _Action1_ | _Action2_ | <- first group, no TITLE + +-----------------------------+ + | TITLE _Action1_ | _Action2_ | <- second group + +-----------------------------+ + ... +``` \ No newline at end of file -- cgit v1.2.3 From ae1acbd09c8e98e4e23f01f633ad551dabd5c578 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 6 Jun 2020 19:32:45 +0200 Subject: Document import style --- docs/dev/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 194a40e15..6f74d4223 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -184,6 +184,27 @@ use crate::{} use super::{} // but prefer `use crate::` ``` +## Import Style + +Items from `hir` and `ast` should be used qualified: + +```rust +// Good +use ra_syntax::ast; + +fn frobnicate(func: hir::Function, strukt: ast::StructDef) {} + +// Not as good +use hir::Function; +use ra_syntax::ast::StructDef; + +fn frobnicate(func: Function, strukt: StructDef) {} +``` + +Avoid local `use MyEnum::*` imports. + +Prefer `use crate::foo::bar` to `use super::bar`. + ## 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. -- cgit v1.2.3 From 81ffe973ac265507419024048c166bbeef9aa275 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 6 Jun 2020 19:54:41 +0200 Subject: Document certain invariants --- docs/dev/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 6f74d4223..903cb4055 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -241,6 +241,33 @@ struct Foo { 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 :-) +# Architecture Invariants + +This section tries to document high-level design constraints, which are not +always obvious from the low-level code. + +## Incomplete syntax trees + +Syntax trees are by design incomplete and do not enforce well-formedness. +If ast method returns an `Option`, it *can* be `None` at runtime, even if this is forbidden by the grammar. + +## LSP indenpendence + +rust-analyzer is independent from LSP. +It provides features for a hypothetical perfect Rust-specific IDE client. +Internal representations are lowered to LSP in the `rust-analyzer` crate (the only crate which is allowed to use LSP types). + +## IDE/Compiler split + +There's a semi-hard split between "compiler" and "IDE", at the `ra_hir` crate. +Compiler derives new facts about source code. +It explicitly acknowledges that not all info is available (ie, you can't look at types during name resolution). + +IDE assumes that all information is available at all times. + +IDE should use only types from `ra_hir`, and should not depend on the underling compiler types. +`ra_hir` is a facade. + # Logging Logging is done by both rust-analyzer and VS Code, so it might be tricky to -- cgit v1.2.3 From ee8dec5dc11cfecf219b6510b0eadd9691a82ba5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 8 Jun 2020 12:52:28 +0200 Subject: IDE API --- docs/dev/README.md | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 903cb4055..64d595b68 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -268,6 +268,13 @@ IDE assumes that all information is available at all times. IDE should use only types from `ra_hir`, and should not depend on the underling compiler types. `ra_hir` is a facade. +## IDE API + +The main IDE crate (`ra_ide`) uses "Plain Old Data" for the API. +Rather than talking in definitions and references, it talks in Strings and textual offsets. +In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath. +The results are 100% Rust specific though. + # Logging Logging is done by both rust-analyzer and VS Code, so it might be tricky to -- cgit v1.2.3 From cc07c82fefb2affc1772e12b8357471cccc8d578 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 8 Jun 2020 12:54:48 +0200 Subject: Preconditions style --- docs/dev/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 64d595b68..5a9c0a148 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -241,6 +241,26 @@ struct Foo { 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 :-) +## Preconditions + +Function preconditions should generally be expressed in types and provided by the caller (rather than checked by callee): + +```rust +// Good +fn frbonicate(walrus: Walrus) { + ... +} + +// Not as good +fn frobnicate(walrus: Option) { + let walrus = match walrus { + Some(it) => it, + None => return, + }; + ... +} +``` + # Architecture Invariants This section tries to document high-level design constraints, which are not -- cgit v1.2.3 From 4968321706fc5c24d9f2c35cdbbd5e9047c97c96 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 8 Jun 2020 13:19:32 +0200 Subject: Don't @ people in commit messages --- docs/dev/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 5a9c0a148..46ee030fc 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -261,6 +261,14 @@ fn frobnicate(walrus: Option) { } ``` +## Commit Style + +We don't have specific rules around git history hygiene. +Maintaining clean git history is encouraged, but not enforced. +We use rebase workflow, it's OK to rewrite history during PR review process. + +Avoid @mentioning people in commit messages, as such messages create a lot of duplicate notification traffic during rebases. + # Architecture Invariants This section tries to document high-level design constraints, which are not -- cgit v1.2.3 From e3663d60bfe1e8505e6db8bffab997b87be03913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 8 Jun 2020 18:50:27 +0300 Subject: Dev docs nits --- docs/dev/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 46ee030fc..0330939b6 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -55,7 +55,7 @@ You can run `cargo xtask install-pre-commit-hook` to install git-hook to run rus All Rust code lives in the `crates` top-level directory, and is organized as a single Cargo workspace. The `editors` top-level directory contains code for integrating with editors. Currently, it contains the plugin for VS Code (in -typescript). The `docs` top-level directory contains both developer and user +TypeScript). The `docs` top-level directory contains both developer and user documentation. We have some automation infra in Rust in the `xtask` package. It contains @@ -79,8 +79,8 @@ possible. There's **"Run Extension (Debug Build)"** launch configuration for thi In general, I use one of the following workflows for fixing bugs and implementing features. -If the problem concerns only internal parts of rust-analyzer (ie, I don't need -to touch `rust-analyzer` crate or typescript code), there is a unit-test for it. +If the problem concerns only internal parts of rust-analyzer (i.e. I don't need +to touch `rust-analyzer` crate or TypeScript code), there is a unit-test for it. So, I use **Rust Analyzer: Run** action in VS Code to run this single test, and then just do printf-driven development/debugging. As a sanity check after I'm done, I use `cargo xtask install --server` and **Reload Window** action in VS @@ -279,7 +279,7 @@ always obvious from the low-level code. Syntax trees are by design incomplete and do not enforce well-formedness. If ast method returns an `Option`, it *can* be `None` at runtime, even if this is forbidden by the grammar. -## LSP indenpendence +## LSP independence rust-analyzer is independent from LSP. It provides features for a hypothetical perfect Rust-specific IDE client. @@ -289,7 +289,7 @@ Internal representations are lowered to LSP in the `rust-analyzer` crate (the on There's a semi-hard split between "compiler" and "IDE", at the `ra_hir` crate. Compiler derives new facts about source code. -It explicitly acknowledges that not all info is available (ie, you can't look at types during name resolution). +It explicitly acknowledges that not all info is available (i.e. you can't look at types during name resolution). IDE assumes that all information is available at all times. @@ -345,8 +345,8 @@ There's also two VS Code commands which might be of interest: rust code that it refers to and the rust editor will also highlight the proper text range. - If you press Ctrl (i.e. trigger goto definition) in the inspected - Rust source file the syntax tree read-only editor should scroll to and select the + If you trigger Go to Definition in the inspected Rust source file, + the syntax tree read-only editor should scroll to and select the appropriate syntax node token. ![demo](https://user-images.githubusercontent.com/36276403/78225773-6636a480-74d3-11ea-9d9f-1c9d42da03b0.png) -- cgit v1.2.3 From 1538206609dbb88f10ff2525523096bab0c65740 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 10 Jun 2020 14:12:08 +0200 Subject: Explain inline tests --- docs/dev/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index 0330939b6..cf93135ee 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -303,6 +303,17 @@ Rather than talking in definitions and references, it talks in Strings and textu In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath. The results are 100% Rust specific though. +## Parser Tests + +Test for parser (`ra_parser`) live in `ra_syntax` crate (see `test_data` direcotory). +There are two kinds of tests: + +* Manually written test cases in `parser/ok` and `parser/error` +* "Inline" tests in `parser/inline` (these are generated) from comments in `ra_parser` crate. + +The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for. +If you are tempted to add a large inline test, it might be a good idea to leave only the simplest example in place, and move the test to a manual `parser/ok` test. + # Logging Logging is done by both rust-analyzer and VS Code, so it might be tricky to -- cgit v1.2.3 From f280407d7350c2abc4cc35389d389acdc5d93e28 Mon Sep 17 00:00:00 2001 From: Jacek Generowicz Date: Wed, 10 Jun 2020 20:32:29 +0200 Subject: Fix parser test directory name in dev docs --- docs/dev/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/dev/README.md b/docs/dev/README.md index cf93135ee..ef5ffbf59 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -308,7 +308,7 @@ The results are 100% Rust specific though. Test for parser (`ra_parser`) live in `ra_syntax` crate (see `test_data` direcotory). There are two kinds of tests: -* Manually written test cases in `parser/ok` and `parser/error` +* Manually written test cases in `parser/ok` and `parser/err` * "Inline" tests in `parser/inline` (these are generated) from comments in `ra_parser` crate. The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for. -- cgit v1.2.3