Skip to content

Latest commit

 

History

History
450 lines (301 loc) · 14.4 KB

generated_features.adoc

File metadata and controls

450 lines (301 loc) · 14.4 KB

Auto Import

Source: auto_import.rs

Using the auto-import assist it is possible to insert missing imports for unresolved items. When inserting an import it will do so in a structured manner by keeping imports grouped, separated by a newline in the following order:

  • std and core

  • External Crates

  • Current Crate, paths prefixed by crate

  • Current Module, paths prefixed by self

  • Super Module, paths prefixed by super

Example:

use std::fs::File;

use itertools::Itertools;
use syntax::ast;

use crate::utils::insert_use;

use self::auto_import;

use super::AssistContext;
Merge Behaviour

It is possible to configure how use-trees are merged with the importMergeBehaviour setting. It has the following configurations:

  • full: This setting will cause auto-import to always completely merge use-trees that share the same path prefix while also merging inner trees that share the same path-prefix. This kind of nesting is only supported in Rust versions later than 1.24.

  • last: This setting will cause auto-import to merge use-trees as long as the resulting tree will only contain a nesting of single segment paths at the very end.

  • none: This setting will cause auto-import to never merge use-trees keeping them as simple paths.

In VS Code the configuration for this is rust-analyzer.assist.importMergeBehaviour.

Import Prefix

The style of imports in the same crate is configurable through the importPrefix setting. It has the following configurations:

  • by_crate: This setting will force paths to be always absolute, starting with the crate prefix, unless the item is defined outside of the current crate.

  • by_self: This setting will force paths that are relative to the current module to always start with self. This will result in paths that always start with either crate, self, super or an extern crate identifier.

  • plain: This setting does not impose any restrictions in imports.

In VS Code the configuration for this is rust-analyzer.assist.importPrefix.

Expand Macro Recursively

Source: 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

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

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]

Format String Completion.

Source: format_like.rs

"Result {result} is {2 + 2}" is expanded to the "Result {} is {}", result, 2 + 2.

The following postfix snippets are available:

  • formatformat!(…​)

  • panicpanic!(…​)

  • printlnprintln!(…​)

  • log: + logdlog::debug!(…​) + logtlog::trace!(…​) + logilog::info!(…​) + logwlog::warn!(…​) + logelog::error!(…​)

Go to Definition

Navigates to the definition of an identifier.

Editor Shortcut

VS Code

kbd:[F12]

Go to Implementation

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

Navigates to the type of an identifier.

Editor Action Name

VS Code

*Go to Type Definition

Hover

Source: 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: 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 hints for

  • types of local variables

  • names of function arguments

  • types of chained expressions

Note: VS Code does not have native support for inlay hints 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: 1, 2.

Editor Action Name

VS Code

*Rust Analyzer: Toggle inlay hints

Join Lines

Source: 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: lib.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.ifif expr {} or if let …​ {} for Option or Result

  • expr.matchmatch expr {}

  • expr.whilewhile expr {} or while let …​ {} for Option or Result

  • expr.ref&expr

  • expr.refm&mut expr

  • expr.not!expr

  • expr.dbgdbg!(expr)

  • expr.dbgrdbg!(&expr)

  • expr.call(expr)

There also snippet completions:

Expressions
  • pdeprintln!(" = {:?}", );

  • ppdeprintln!(" = {:#?}", );

Items
  • tfn#[test] fn feature(){}

  • tmod

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_name() {}
}

Matching Brace

If the cursor is on any brace (<>(){}[]||) which is a part of a brace-pair, moves cursor to the matching brace. It uses the actual parser to determine braces, so it won’t confuse generics with comparisons.

Editor Action Name

VS Code

Rust Analyzer: Find matching brace

Memory Usage

Source: apply_change.rs

Clears rust-analyzer’s internal database and prints memory usage statistics.

Editor Action Name

VS Code

Rust Analyzer: Memory Usage (Clears Database)

On Enter

Source: on_enter.rs

rust-analyzer can override kbd:[Enter] key to make it smarter:

  • kbd:[Enter] inside triple-slash comments automatically inserts ///

  • kbd:[Enter] in the middle or after a trailing space in // inserts //

This action needs to be assigned to shortcut explicitly.

VS Code

Add the following to keybindings.json:

{
  "key": "Enter",
  "command": "rust-analyzer.onEnter",
  "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust"
}

On Typing Assists

Source: typing.rs

Some features trigger on typing certain characters:

  • typing let = tries to smartly add ; if = is followed by an existing expression

  • typing . in a chain method call auto-indents

    VS Code

    Add the following to settings.json:

"editor.formatOnType": true,

Parent Module

Navigates to the parent module of the current module.

Editor Action Name

VS Code

Rust Analyzer: Locate parent module

Run

Source: 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

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: 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: status.rs

Shows internal statistic about memory usage of rust-analyzer.

Editor Action Name

VS Code

Rust Analyzer: Status

Structural Search and Replace

Source: lib.rs

Search and replace with named wildcards that will match any expression, type, path, pattern or item. The syntax for a structural search replace command is <search_pattern> =⇒> <replace_pattern>. A $<name> placeholder in the search pattern will match any AST node and $<name> will reference it in the replacement. Within a macro call, a placeholder will match up until whatever token follows the placeholder.

All paths in both the search pattern and the replacement template must resolve in the context in which this command is invoked. Paths in the search pattern will then match the code if they resolve to the same item, even if they’re written differently. For example if we invoke the command in the module foo with a pattern of Bar, then code in the parent module that refers to foo::Bar will match.

Paths in the replacement template will be rendered appropriately for the context in which the replacement occurs. For example if our replacement template is foo::Bar and we match some code in the foo module, we’ll insert just Bar.

Inherent method calls should generally be written in UFCS form. e.g. foo::Bar::baz($s, $a) will match $s.baz($a), provided the method call baz resolves to the method foo::Bar::baz. When a placeholder is the receiver of a method call in the search pattern (e.g. $s.foo()), but not in the replacement template (e.g. bar($s)), then *, & and &mut will be added as needed to mirror whatever autoderef and autoref was happening implicitly in the matched code.

The scope of the search / replace will be restricted to the current selection if any, otherwise it will apply to the whole workspace.

Placeholders may be given constraints by writing them as ${<name>:<constraint1>:<constraint2>…​}.

Supported constraints:

Constraint Restricts placeholder

kind(literal)

Is a literal (e.g. 42 or "forty two")

not(a)

Negates the constraint a

Available via the command rust-analyzer.ssr.

// Using structural search replace command [foo($a, $b) ==>> ($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: 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]