mirror of
https://github.com/rust-lang/rust.git
synced 2026-03-27 15:26:29 +00:00
Merge branch 'master' into compute-lazy-assits
# Conflicts: # crates/rust-analyzer/src/main_loop/handlers.rs # crates/rust-analyzer/src/to_proto.rs
This commit is contained in:
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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]
|
||||
|===
|
||||
@@ -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[]
|
||||
|
||||
Reference in New Issue
Block a user