mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Merge #1000
1000: Clean up some documentation debt r=Xanewok a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com> Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
This commit is contained in:
commit
90ff3ba641
11 changed files with 687 additions and 462 deletions
|
@ -1,18 +0,0 @@
|
|||
The project is in its early stages: contributions are welcome and would be
|
||||
**very** helpful, but the project is not _yet_ optimized for contribution.
|
||||
Moreover, it is doubly experimental, so there's no guarantee that any work here
|
||||
would reach production.
|
||||
|
||||
To get an idea of how rust-analyzer works, take a look at the [ARCHITECTURE.md](./ARCHITECTURE.md)
|
||||
document.
|
||||
|
||||
Useful labels on the issue tracker:
|
||||
* [E-mentor](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-mentor)
|
||||
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),
|
||||
[E-hard](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-hard),
|
||||
labels are *estimates* for how hard would be to write a fix.
|
||||
|
||||
There's no formal PR check list: everything that passes CI (we use [bors](https://bors.tech/)) is valid,
|
||||
but it's a good idea to write nice commit messages, test code thoroughly, maintain consistent style, etc.
|
116
README.md
116
README.md
|
@ -13,32 +13,37 @@ Work on the Rust Analyzer is sponsored by
|
|||
|
||||
[![Ferrous Systems](https://ferrous-systems.com/images/ferrous-logo-text.svg)](https://ferrous-systems.com/)
|
||||
|
||||
## Quick Start
|
||||
## Language Server Quick Start
|
||||
|
||||
Rust analyzer builds on Rust >= 1.31.0 and uses the 2018 edition.
|
||||
Rust Analyzer is a work-in-progress, so you'll have to build it from source, and
|
||||
you might encounter critical bugs. That said, it is complete enough to provide a
|
||||
useful IDE experience and some people use it as a daily driver.
|
||||
|
||||
To build rust-analyzer, you need:
|
||||
|
||||
* latest stable rust for language server itself
|
||||
* latest stable npm and VS Code for VS Code extension (`code` should be in path)
|
||||
|
||||
For setup for other editors, see [./docs/user](./docs/user).
|
||||
|
||||
```
|
||||
# run tests
|
||||
$ cargo test
|
||||
# clone the repo
|
||||
$ git clone https://github.com/rust-analyzer/rust-analyzer && cd rust-analyzer
|
||||
|
||||
# show syntax tree of a Rust file
|
||||
$ cargo run --package ra_cli parse < crates/ra_syntax/src/lib.rs
|
||||
# install both the language server and VS Code extension
|
||||
$ cargo install-code
|
||||
|
||||
# show symbols of a Rust file
|
||||
$ cargo run --package ra_cli symbols < crates/ra_syntax/src/lib.rs
|
||||
|
||||
# install the language server
|
||||
# alternatively, install only the server. Binary name is `ra_lsp_server`.
|
||||
$ cargo install-lsp
|
||||
or
|
||||
$ cargo install --path crates/ra_lsp_server
|
||||
```
|
||||
## Documentation
|
||||
|
||||
See [these instructions](./editors/README.md) for VS Code setup and the list of
|
||||
features (some of which are VS Code specific).
|
||||
If you want to **contribute** to rust-analyzer or just curious about how things work
|
||||
under the hood, check the [./docs/dev](./docs/dev) folder.
|
||||
|
||||
## Debugging
|
||||
|
||||
See [these instructions](./DEBUGGING.md) on how to debug the vscode extension and the lsp server.
|
||||
If you want to **use** rust-analyzer's language server with your editor of
|
||||
choice, check [./docs/user](./docs/user) folder. It also contains some tips & tricks to help
|
||||
you be more productive when using rust-analyzer.
|
||||
|
||||
## Getting in touch
|
||||
|
||||
|
@ -46,83 +51,6 @@ We are on the rust-lang Zulip!
|
|||
|
||||
https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](./CONTRIBUTING.md) and [ARCHITECTURE.md](./ARCHITECTURE.md)
|
||||
|
||||
## Supported LSP features
|
||||
|
||||
### General
|
||||
- [x] [initialize](https://microsoft.github.io/language-server-protocol/specification#initialize)
|
||||
- [x] [initialized](https://microsoft.github.io/language-server-protocol/specification#initialized)
|
||||
- [x] [shutdown](https://microsoft.github.io/language-server-protocol/specification#shutdown)
|
||||
- [ ] [exit](https://microsoft.github.io/language-server-protocol/specification#exit)
|
||||
- [x] [$/cancelRequest](https://microsoft.github.io/language-server-protocol/specification#cancelRequest)
|
||||
|
||||
### Workspace
|
||||
- [ ] [workspace/workspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_workspaceFolders)
|
||||
- [ ] [workspace/didChangeWorkspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWorkspaceFolders)
|
||||
- [x] [workspace/didChangeConfiguration](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeConfiguration)
|
||||
- [ ] [workspace/configuration](https://microsoft.github.io/language-server-protocol/specification#workspace_configuration)
|
||||
- [x] [workspace/didChangeWatchedFiles](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWatchedFiles)
|
||||
- [x] [workspace/symbol](https://microsoft.github.io/language-server-protocol/specification#workspace_symbol)
|
||||
- [x] [workspace/executeCommand](https://microsoft.github.io/language-server-protocol/specification#workspace_executeCommand)
|
||||
- `apply_code_action`
|
||||
- [ ] [workspace/applyEdit](https://microsoft.github.io/language-server-protocol/specification#workspace_applyEdit)
|
||||
|
||||
### Text Synchronization
|
||||
- [x] [textDocument/didOpen](https://microsoft.github.io/language-server-protocol/specification#textDocument_didOpen)
|
||||
- [x] [textDocument/didChange](https://microsoft.github.io/language-server-protocol/specification#textDocument_didChange)
|
||||
- [ ] [textDocument/willSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSave)
|
||||
- [ ] [textDocument/willSaveWaitUntil](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSaveWaitUntil)
|
||||
- [x] [textDocument/didSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_didSave)
|
||||
- [x] [textDocument/didClose](https://microsoft.github.io/language-server-protocol/specification#textDocument_didClose)
|
||||
|
||||
### Diagnostics
|
||||
- [x] [textDocument/publishDiagnostics](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics)
|
||||
|
||||
### Lanuguage Features
|
||||
- [x] [textDocument/completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
|
||||
- open close: false
|
||||
- change: Full
|
||||
- will save: false
|
||||
- will save wait until: false
|
||||
- save: false
|
||||
- [x] [completionItem/resolve](https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve)
|
||||
- resolve provider: none
|
||||
- trigger characters: `:`, `.`
|
||||
- [x] [textDocument/hover](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
|
||||
- [x] [textDocument/signatureHelp](https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp)
|
||||
- trigger characters: `(`, `,`, `)`
|
||||
- [ ] [textDocument/declaration](https://microsoft.github.io/language-server-protocol/specification#textDocument_declaration)
|
||||
- [x] [textDocument/definition](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition)
|
||||
- [ ] [textDocument/typeDefinition](https://microsoft.github.io/language-server-protocol/specification#textDocument_typeDefinition)
|
||||
- [x] [textDocument/implementation](https://microsoft.github.io/language-server-protocol/specification#textDocument_implementation)
|
||||
- [x] [textDocument/references](https://microsoft.github.io/language-server-protocol/specification#textDocument_references)
|
||||
- [x] [textDocument/documentHighlight](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight)
|
||||
- [x] [textDocument/documentSymbol](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol)
|
||||
- [x] [textDocument/codeAction](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction)
|
||||
- rust-analyzer.syntaxTree
|
||||
- rust-analyzer.extendSelection
|
||||
- rust-analyzer.matchingBrace
|
||||
- rust-analyzer.parentModule
|
||||
- rust-analyzer.joinLines
|
||||
- rust-analyzer.run
|
||||
- rust-analyzer.analyzerStatus
|
||||
- [x] [textDocument/codeLens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
|
||||
- [ ] [textDocument/documentLink](https://microsoft.github.io/language-server-protocol/specification#codeLens_resolve)
|
||||
- [ ] [documentLink/resolve](https://microsoft.github.io/language-server-protocol/specification#documentLink_resolve)
|
||||
- [ ] [textDocument/documentColor](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor)
|
||||
- [ ] [textDocument/colorPresentation](https://microsoft.github.io/language-server-protocol/specification#textDocument_colorPresentation)
|
||||
- [x] [textDocument/formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting)
|
||||
- [ ] [textDocument/rangeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting)
|
||||
- [x] [textDocument/onTypeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting)
|
||||
- first trigger character: `=`
|
||||
- more trigger character `.`
|
||||
- [x] [textDocument/rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_rename)
|
||||
- [x] [textDocument/prepareRename](https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename)
|
||||
- [x] [textDocument/foldingRange](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)
|
||||
|
||||
## License
|
||||
|
||||
Rust analyzer is primarily distributed under the terms of both the MIT
|
||||
|
|
77
ROADMAP.md
77
ROADMAP.md
|
@ -1,77 +0,0 @@
|
|||
# Rust Analyzer Roadmap 01
|
||||
|
||||
Written on 2018-11-06, extends approximately to February 2019.
|
||||
After that, we should coordinate with the compiler/rls developers to align goals and share code and experience.
|
||||
|
||||
|
||||
# Overall Goals
|
||||
|
||||
The mission is:
|
||||
* Provide an excellent "code analyzed as you type" IDE experience for the Rust language,
|
||||
* Implement the bulk of the features in Rust itself.
|
||||
|
||||
|
||||
High-level architecture constraints:
|
||||
* Long-term, replace the current rustc frontend.
|
||||
It's *obvious* that the code should be shared, but OTOH, all great IDEs started as from-scratch rewrites.
|
||||
* Don't hard-code a particular protocol or mode of operation.
|
||||
Produce a library which could be used for implementing an LSP server, or for in-process embedding.
|
||||
* As long as possible, stick with stable Rust.
|
||||
|
||||
|
||||
# Current Goals
|
||||
|
||||
Ideally, we would be coordinating with the compiler/rls teams, but they are busy working on making Rust 2018 at the moment.
|
||||
The sync-up point will happen some time after the edition, probably early 2019.
|
||||
In the meantime, the goal is to **experiment**, specifically, to figure out how a from-scratch written RLS might look like.
|
||||
|
||||
|
||||
## Data Storage and Protocol implementation
|
||||
|
||||
The fundamental part of any architecture is who owns which data, how the data is mutated and how the data is exposed to user.
|
||||
For storage we use the [salsa](http://github.com/salsa-rs/salsa) library, which provides a solid model that seems to be the way to go.
|
||||
|
||||
Modification to source files is mostly driven by the language client, but we also should support watching the file system. The current
|
||||
file watching implementation is a stub.
|
||||
|
||||
**Action Item:** implement reliable file watching service.
|
||||
|
||||
We also should extract LSP bits as a reusable library. There's already `gen_lsp_server`, but it is pretty limited.
|
||||
|
||||
**Action Item:** try using `gen_lsp_server` in more than one language server, for example for TOML and Nix.
|
||||
|
||||
The ideal architecture for `gen_lsp_server` is still unclear. I'd rather avoid futures: they bring significant runtime complexity
|
||||
(call stacks become insane) and the performance benefits are negligible for our use case (one thread per request is perfectly OK given
|
||||
the low amount of requests a language server receives). The current interface is based on crossbeam-channel, but it's not clear
|
||||
if that is the best choice.
|
||||
|
||||
|
||||
## Low-effort, high payoff features
|
||||
|
||||
Implementing 20% of type inference will give use 80% of completion.
|
||||
Thus it makes sense to partially implement name resolution, type inference and trait matching, even though there is a chance that
|
||||
this code is replaced later on when we integrate with the compiler
|
||||
|
||||
Specifically, we need to:
|
||||
|
||||
* **Action Item:** implement path resolution, so that we get completion in imports and such.
|
||||
* **Action Item:** implement simple type inference, so that we get completion for inherent methods.
|
||||
* **Action Item:** implement nicer completion infrastructure, so that we have icons, snippets, doc comments, after insert callbacks, ...
|
||||
|
||||
|
||||
## Dragons to kill
|
||||
|
||||
To make experiments most effective, we should try to prototype solutions for the hardest problems.
|
||||
In the case of Rust, the two hardest problems are:
|
||||
* Conditional compilation and source/model mismatch.
|
||||
A single source file might correspond to several entities in the semantic model.
|
||||
For example, different cfg flags produce effectively different crates from the same source.
|
||||
* Macros are intertwined with name resolution in a single fix-point iteration algorithm.
|
||||
This is just plain hard to implement, but also interacts poorly with on-demand.
|
||||
|
||||
|
||||
For the first bullet point, we need to design descriptors infra and explicit mapping step between sources and semantic model, which is intentionally fuzzy in one direction.
|
||||
The **action item** here is basically "write code, see what works, keep high-level picture in mind".
|
||||
|
||||
For the second bullet point, there's hope that salsa with its deep memoization will result in a fast enough solution even without being fully on-demand.
|
||||
Again, the **action item** is to write the code and see what works. Salsa itself uses macros heavily, so it should be a great test.
|
124
docs/dev/README.md
Normal file
124
docs/dev/README.md
Normal file
|
@ -0,0 +1,124 @@
|
|||
# Contributing Quick Start
|
||||
|
||||
Rust Analyzer is just a usual rust project, which is organized as a Cargo
|
||||
workspace, builds on stable and doesn't depend on C libraries. So, just
|
||||
|
||||
```
|
||||
$ cargo test
|
||||
```
|
||||
|
||||
should be enough to get you started!
|
||||
|
||||
To learn more about how rust-analyzer works, see
|
||||
[./architecture.md](./architecture.md) document.
|
||||
|
||||
Various organizational and process issues are discussed here.
|
||||
|
||||
# Getting in Touch
|
||||
|
||||
Rust Analyzer is a part of [RLS-2.0 working
|
||||
group](https://github.com/rust-lang/compiler-team/tree/6a769c13656c0a6959ebc09e7b1f7c09b86fb9c0/working-groups/rls-2.0).
|
||||
Discussion happens in this Zulip stream:
|
||||
|
||||
https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0
|
||||
|
||||
# Issue Labels
|
||||
|
||||
* [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)
|
||||
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),
|
||||
[E-hard](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-hard),
|
||||
labels are *estimates* for how hard would be to write a fix.
|
||||
* [E-fun](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-fun)
|
||||
is for cool, but probably hard stuff.
|
||||
|
||||
# CI
|
||||
|
||||
We use Travis for CI. Most of the things, including formatting, are checked by
|
||||
`cargo test` so, if `cargo test` passes locally, that's a good sign that CI will
|
||||
be green as well. We use bors-ng to enforce the [not rocket
|
||||
science](https://graydon2.dreamwidth.org/1597.html) rule.
|
||||
|
||||
You can run `cargo format-hook` to install git-hook to run rustfmt on commit.
|
||||
|
||||
# Code organization
|
||||
|
||||
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 plugins for VS Code (in
|
||||
typescript) and Emacs (in elisp). The `docs` top-level directory contains both
|
||||
developer and user documentation.
|
||||
|
||||
We have some automation infra in Rust in the `crates/tool` package. It contains
|
||||
stuff like formatting checking, code generation and powers `cargo install-code`.
|
||||
The latter syntax is achieved with the help of cargo aliases (see `.cargo`
|
||||
directory).
|
||||
|
||||
# Launching rust-analyzer
|
||||
|
||||
Debugging language server can be tricky: LSP is rather chatty, so driving it
|
||||
from the command line is not really feasible, driving it via VS Code requires
|
||||
interacting with two processes.
|
||||
|
||||
For this reason, the best way to see how rust-analyzer works is to find a
|
||||
relevant test and execute it (VS Code includes an action for running a single
|
||||
test).
|
||||
|
||||
However, launching a VS Code instance with locally build language server is
|
||||
possible. There's even a VS Code task for this, so just <kbd>F5</kbd> should
|
||||
work (thanks, [@andrew-w-ross](https://github.com/andrew-w-ross)!).
|
||||
|
||||
I often just install development version with `cargo jinstall-lsp` and
|
||||
restart the host VS Code.
|
||||
|
||||
See [./debugging.md](./debugging.md) for how to attach to rust-analyzer with
|
||||
debugger, and don't forget that rust-analyzer has useful `pd` snippet and `dbg`
|
||||
postfix completion for printf debugging :-)
|
||||
|
||||
# Working With VS Code Extension
|
||||
|
||||
To work on the VS Code extension, launch code inside `editors/code` and use `F5`
|
||||
to launch/debug. To automatically apply formatter and linter suggestions, use
|
||||
`npm run fix`.
|
||||
|
||||
# Logging
|
||||
|
||||
Logging is done by both rust-analyzer and VS Code, so it might be tricky to
|
||||
figure out where logs go.
|
||||
|
||||
Inside rust-analyzer, we use the standard `log` crate for logging, and
|
||||
`flexi_logger` for logging frotend. By default, log goes to stderr (the same as
|
||||
with `env_logger`), but the stderr itself is processed by VS Code. To mirror
|
||||
logs to a `./log` directory, set `RA_INTERNAL_MODE=1` environmental variable.
|
||||
|
||||
To see stderr in the running VS Code instance, go to the "Output" tab of the
|
||||
panel and select `rust-analyzer`. This shows `eprintln!` as well. Note that
|
||||
`stdout` is used for the actual protocol, so `println!` will break things.
|
||||
|
||||
To log all communication between the server and the client, there are two choices:
|
||||
|
||||
* you can log on the server side, by running something like
|
||||
```
|
||||
env RUST_LOG=gen_lsp_server=trace code .
|
||||
```
|
||||
|
||||
* you can log on the client side, by enabling `"rust-analyzer.trace.server":
|
||||
"verbose"` workspace setting. These logs are shown in a separate tab in the
|
||||
output and could be used with LSP inspector. Kudos to
|
||||
[@DJMcNab](https://github.com/DJMcNab) for setting this awesome infra up!
|
||||
|
||||
|
||||
There's also two VS Code commands which might be of interest:
|
||||
|
||||
* `Rust Analyzer: Status` shows some memory-usage statistics. To take full
|
||||
advantage of it, you need to compile rust-analyzer with jemalloc support:
|
||||
```
|
||||
$ cargo install --path crates/ra_lsp_server --force --features jemalloc
|
||||
```
|
||||
|
||||
There's an alias for this: `cargo jinstall-lsp`.
|
||||
|
||||
* `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection.
|
|
@ -7,8 +7,10 @@ in the right place!
|
|||
See also the [guide](./guide.md), which walks through a particular snapshot of
|
||||
rust-analyzer code base.
|
||||
|
||||
For syntax-trees specifically, there's a [video walk
|
||||
through](https://youtu.be/DGAuLWdCCAI) as well.
|
||||
Yet another resource is this playlist with videos about various parts of the
|
||||
analyzer:
|
||||
|
||||
https://www.youtube.com/playlist?list=PL85XCvVPmGQho7MZkdW-wtPtuJcFpzycE
|
||||
|
||||
## The Big Picture
|
||||
|
||||
|
@ -61,7 +63,7 @@ processes. These are outlined below:
|
|||
|
||||
## Code Walk-Through
|
||||
|
||||
### `crates/ra_syntax`
|
||||
### `crates/ra_syntax`, `crates/ra_parser`
|
||||
|
||||
Rust syntax tree structure and parser. See
|
||||
[RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design notes.
|
||||
|
@ -145,12 +147,14 @@ throughout its modules.
|
|||
|
||||
An LSP implementation which wraps `ra_ide_api` into a langauge server protocol.
|
||||
|
||||
### `crates/ra_vfs`
|
||||
### `ra_vfs`
|
||||
|
||||
Although `hir` and `ra_ide_api` don't do any IO, we need to be able to read
|
||||
files from disk at the end of the day. This is what `ra_vfs` does. It also
|
||||
manages overlays: "dirty" files in the editor, whose "true" contents is
|
||||
different from data on disk.
|
||||
different from data on disk. This is more or less the single really
|
||||
platform-dependent component, so it lives in a separate repository and has an
|
||||
extensive cross-platform CI testing.
|
||||
|
||||
### `crates/gen_lsp_server`
|
||||
|
||||
|
@ -164,37 +168,32 @@ Run with `RUST_LOG=sync_lsp_server=debug` to see all the messages.
|
|||
|
||||
A CLI interface to rust-analyzer.
|
||||
|
||||
### `crate/tools`
|
||||
|
||||
Custom Cargo tasks used to develop rust-analyzer:
|
||||
## Testing Infrastructure
|
||||
|
||||
- `cargo gen-syntax` -- generate `ast` and `syntax_kinds`
|
||||
- `cargo gen-tests` -- collect inline tests from grammar
|
||||
- `cargo install-code` -- build and install VS Code extension and server
|
||||
Rust Analyzer has three interesting [systems
|
||||
boundaries](https://www.tedinski.com/2018/04/10/making-tests-a-positive-influence-on-design.html)
|
||||
to concentrate tests on.
|
||||
|
||||
### `editors/code`
|
||||
The outermost boundary is the `ra_lsp_server` crate, which defines an LSP
|
||||
interface in terms of stdio. We do integration testing of this component, by
|
||||
feeding it with a stream of LSP requests and checking responses. These tests are
|
||||
known as "heavy", because they interact with Cargo and read real files from
|
||||
disk. For this reason, we try to avoid writing too many tests on this boundary:
|
||||
in a statically typed language, it's hard to make an error in the protocol
|
||||
itself if messages are themselves typed.
|
||||
|
||||
VS Code plugin
|
||||
The middle, and most important, boundary is `ra_ide_api`. Unlike
|
||||
`ra_lsp_server`, which exposes API, `ide_api` uses Rust API and is intended to
|
||||
use by various tools. Typical test creates an `AnalysisHost`, calls some
|
||||
`Analysis` functions and compares the results against expectation.
|
||||
|
||||
The innermost and most elaborate boundary is `hir`. It has a much richer
|
||||
vocabulary of types than `ide_api`, but the basic testing setup is the same: we
|
||||
create a database, run some queries, assert result.
|
||||
|
||||
## Common workflows
|
||||
For comparisons, we use [insta](https://github.com/mitsuhiko/insta/) library for
|
||||
snapshot testing.
|
||||
|
||||
To try out VS Code extensions, run `cargo install-code`. This installs both the
|
||||
`ra_lsp_server` binary and the VS Code extension. To install only the binary, use
|
||||
`cargo install-lsp` (shorthand for `cargo install --path crates/ra_lsp_server --force`)
|
||||
|
||||
To see logs from the language server, set `RUST_LOG=info` env variable. To see
|
||||
all communication between the server and the client, use
|
||||
`RUST_LOG=gen_lsp_server=debug` (this will print quite a bit of stuff).
|
||||
|
||||
There's `rust-analyzer: status` command which prints common high-level debug
|
||||
info. In particular, it prints info about memory usage of various data
|
||||
structures, and, if compiled with jemalloc support (`cargo jinstall-lsp` or
|
||||
`cargo install --path crates/ra_lsp_server --force --features jemalloc`), includes
|
||||
statistic about the heap.
|
||||
|
||||
To run tests, just `cargo test`.
|
||||
|
||||
To work on the VS Code extension, launch code inside `editors/code` and use `F5` to
|
||||
launch/debug. To automatically apply formatter and linter suggestions, use `npm
|
||||
run fix`.
|
||||
To test various analysis corner cases and avoid forgetting about old tests, we
|
||||
use so-called marks. See the `marks` module in the `test_utils` crate for more.
|
74
docs/dev/lsp-features.md
Normal file
74
docs/dev/lsp-features.md
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Supported LSP features
|
||||
|
||||
This list documents LSP features, supported by rust-analyzer.
|
||||
|
||||
## General
|
||||
- [x] [initialize](https://microsoft.github.io/language-server-protocol/specification#initialize)
|
||||
- [x] [initialized](https://microsoft.github.io/language-server-protocol/specification#initialized)
|
||||
- [x] [shutdown](https://microsoft.github.io/language-server-protocol/specification#shutdown)
|
||||
- [ ] [exit](https://microsoft.github.io/language-server-protocol/specification#exit)
|
||||
- [x] [$/cancelRequest](https://microsoft.github.io/language-server-protocol/specification#cancelRequest)
|
||||
|
||||
## Workspace
|
||||
- [ ] [workspace/workspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_workspaceFolders)
|
||||
- [ ] [workspace/didChangeWorkspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWorkspaceFolders)
|
||||
- [x] [workspace/didChangeConfiguration](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeConfiguration)
|
||||
- [ ] [workspace/configuration](https://microsoft.github.io/language-server-protocol/specification#workspace_configuration)
|
||||
- [x] [workspace/didChangeWatchedFiles](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWatchedFiles)
|
||||
- [x] [workspace/symbol](https://microsoft.github.io/language-server-protocol/specification#workspace_symbol)
|
||||
- [x] [workspace/executeCommand](https://microsoft.github.io/language-server-protocol/specification#workspace_executeCommand)
|
||||
- `apply_code_action`
|
||||
- [ ] [workspace/applyEdit](https://microsoft.github.io/language-server-protocol/specification#workspace_applyEdit)
|
||||
|
||||
## Text Synchronization
|
||||
- [x] [textDocument/didOpen](https://microsoft.github.io/language-server-protocol/specification#textDocument_didOpen)
|
||||
- [x] [textDocument/didChange](https://microsoft.github.io/language-server-protocol/specification#textDocument_didChange)
|
||||
- [ ] [textDocument/willSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSave)
|
||||
- [ ] [textDocument/willSaveWaitUntil](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSaveWaitUntil)
|
||||
- [x] [textDocument/didSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_didSave)
|
||||
- [x] [textDocument/didClose](https://microsoft.github.io/language-server-protocol/specification#textDocument_didClose)
|
||||
|
||||
## Diagnostics
|
||||
- [x] [textDocument/publishDiagnostics](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics)
|
||||
|
||||
## Lanuguage Features
|
||||
- [x] [textDocument/completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
|
||||
- open close: false
|
||||
- change: Full
|
||||
- will save: false
|
||||
- will save wait until: false
|
||||
- save: false
|
||||
- [x] [completionItem/resolve](https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve)
|
||||
- resolve provider: none
|
||||
- trigger characters: `:`, `.`
|
||||
- [x] [textDocument/hover](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
|
||||
- [x] [textDocument/signatureHelp](https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp)
|
||||
- trigger characters: `(`, `,`, `)`
|
||||
- [ ] [textDocument/declaration](https://microsoft.github.io/language-server-protocol/specification#textDocument_declaration)
|
||||
- [x] [textDocument/definition](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition)
|
||||
- [ ] [textDocument/typeDefinition](https://microsoft.github.io/language-server-protocol/specification#textDocument_typeDefinition)
|
||||
- [x] [textDocument/implementation](https://microsoft.github.io/language-server-protocol/specification#textDocument_implementation)
|
||||
- [x] [textDocument/references](https://microsoft.github.io/language-server-protocol/specification#textDocument_references)
|
||||
- [x] [textDocument/documentHighlight](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight)
|
||||
- [x] [textDocument/documentSymbol](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol)
|
||||
- [x] [textDocument/codeAction](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction)
|
||||
- rust-analyzer.syntaxTree
|
||||
- rust-analyzer.extendSelection
|
||||
- rust-analyzer.matchingBrace
|
||||
- rust-analyzer.parentModule
|
||||
- rust-analyzer.joinLines
|
||||
- rust-analyzer.run
|
||||
- rust-analyzer.analyzerStatus
|
||||
- [x] [textDocument/codeLens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
|
||||
- [ ] [textDocument/documentLink](https://microsoft.github.io/language-server-protocol/specification#codeLens_resolve)
|
||||
- [ ] [documentLink/resolve](https://microsoft.github.io/language-server-protocol/specification#documentLink_resolve)
|
||||
- [ ] [textDocument/documentColor](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor)
|
||||
- [ ] [textDocument/colorPresentation](https://microsoft.github.io/language-server-protocol/specification#textDocument_colorPresentation)
|
||||
- [x] [textDocument/formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting)
|
||||
- [ ] [textDocument/rangeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting)
|
||||
- [x] [textDocument/onTypeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting)
|
||||
- first trigger character: `=`
|
||||
- more trigger character `.`
|
||||
- [x] [textDocument/rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_rename)
|
||||
- [x] [textDocument/prepareRename](https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename)
|
||||
- [x] [textDocument/foldingRange](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)
|
77
docs/user/README.md
Normal file
77
docs/user/README.md
Normal file
|
@ -0,0 +1,77 @@
|
|||
The main interface to rust-analyzer is the
|
||||
[LSP](https://microsoft.github.io/language-server-protocol/) implementation. To
|
||||
install lsp server, use `cargo install-lsp`, which is a shorthand for `cargo
|
||||
install --package ra_lsp_server`. The binary is named `ra_lsp_server`, you
|
||||
should be able to use it with any LSP-compatible editor. We use custom
|
||||
extensions to LSP, so special client-side support is required to take full
|
||||
advantage of rust-analyzer. This repository contains support code for VS Code
|
||||
and Emacs.
|
||||
|
||||
Rust Analyzer needs sources of rust standard library to work, so you might need
|
||||
to execute
|
||||
|
||||
```
|
||||
$ rustup component add rust-src
|
||||
```
|
||||
|
||||
See [./features.md](./features.md) document for a list of features that are available.
|
||||
|
||||
## VS Code
|
||||
|
||||
Prerequisites:
|
||||
|
||||
In order to build the VS Code plugin, you need to have node.js and npm with
|
||||
a minimum version of 10 installed. Please refer to
|
||||
[node.js and npm documentation](https://nodejs.org) for installation instructions.
|
||||
|
||||
You will also need the most recent version of VS Code: we don't try to
|
||||
maintain compatibility with older versions yet.
|
||||
|
||||
The experimental VS Code plugin can then be built and installed by executing the
|
||||
following commands:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
|
||||
$ cd rust-analyzer
|
||||
$ cargo install-code
|
||||
```
|
||||
|
||||
This will run `cargo install --package ra_lsp_server` to install the server
|
||||
binary into `~/.cargo/bin`, and then will build and install plugin from
|
||||
`editors/code`. See
|
||||
[this](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/crates/tools/src/main.rs#L37-L56)
|
||||
for details. The installation is expected to *just work*, if it doesn't, report
|
||||
bugs!
|
||||
|
||||
It's better to remove existing Rust plugins to avoid interference.
|
||||
|
||||
Beyond basic LSP features, there are some extension commands which you can
|
||||
invoke via <kbd>Ctrl+Shift+P</kbd> or bind to a shortcut. See [./features.md](./features.md)
|
||||
for details.
|
||||
|
||||
### Settings
|
||||
|
||||
* `rust-analyzer.highlightingOn`: enables experimental syntax highlighting
|
||||
* `rust-analyzer.showWorkspaceLoadedNotification`: to ease troubleshooting, a
|
||||
notification is shown by default when a workspace is loaded
|
||||
* `rust-analyzer.enableEnhancedTyping`: by default, rust-analyzer intercepts
|
||||
`Enter` key to make it easier to continue comments
|
||||
* `rust-analyzer.raLspServerPath`: path to `ra_lsp_server` executable
|
||||
* `rust-analyzer.enableCargoWatchOnStartup`: prompt to install & enable `cargo
|
||||
watch` for live error highlighting (note, this **does not** use rust-analyzer)
|
||||
* `rust-analyzer.trace.server`: enables internal logging
|
||||
|
||||
|
||||
## Emacs
|
||||
|
||||
Prerequisites:
|
||||
|
||||
`emacs-lsp`, `dash` and `ht` packages.
|
||||
|
||||
Installation:
|
||||
|
||||
* add
|
||||
[ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/editors/emacs/ra-emacs-lsp.el)
|
||||
to load path and require it in `init.el`
|
||||
* run `lsp` in a rust buffer
|
||||
* (Optionally) bind commands like `rust-analyzer-join-lines` or `rust-analyzer-extend-selection` to keys
|
359
docs/user/features.md
Normal file
359
docs/user/features.md
Normal file
|
@ -0,0 +1,359 @@
|
|||
This documents is an index of features that rust-analyzer language server
|
||||
provides. Shortcuts are for the default VS Code layout. If there's no shortcut,
|
||||
you can use <kbd>Ctrl+Shift+P</kbd> to search for the corresponding action.
|
||||
|
||||
### Workspace Symbol <kbd>ctrl+t</kbd>
|
||||
|
||||
Uses fuzzy-search to find types, modules and function by name across your
|
||||
project and dependencies. This **the** most useful feature, which improves code
|
||||
navigation tremendously. It mostly works on top of the built-in LSP
|
||||
functionality, however `#` and `*` symbols can be used to narrow down the
|
||||
search. Specifically,
|
||||
|
||||
- `Foo` searches for `Foo` type in the current workspace
|
||||
- `foo#` searches for `foo` function in the current workspace
|
||||
- `Foo*` searches for `Foo` type among dependencies, excluding `stdlib`
|
||||
- `foo#*` searches for `foo` function among dependencies.
|
||||
|
||||
That is, `#` switches from "types" to all symbols, `*` switches from the current
|
||||
workspace to dependencies.
|
||||
|
||||
### Document Symbol <kbd>ctrl+shift+o</kbd>
|
||||
|
||||
Provides a tree of the symbols defined in the file. Can be used to
|
||||
|
||||
* fuzzy search symbol in a file (super useful)
|
||||
* draw breadcrumbs to describe the context around the cursor
|
||||
* draw outline of the file
|
||||
|
||||
### On Typing Assists
|
||||
|
||||
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
|
||||
|
||||
### Commands <kbd>ctrl+shift+p</kbd>
|
||||
|
||||
#### Extend Selection
|
||||
|
||||
Extends the current selection to the encompassing syntactic construct
|
||||
(expression, statement, item, module, etc). It works with multiple cursors. Do
|
||||
bind this command to a key, it's super-useful! Expected to be upstreamed to LSP
|
||||
soonish: https://github.com/Microsoft/language-server-protocol/issues/613
|
||||
|
||||
#### Run
|
||||
|
||||
Shows popup suggesting to run a test/benchmark/binary **at the current cursor
|
||||
location**. Super useful for repeatedly running just a single test. Do bind this
|
||||
to a shortcut!
|
||||
|
||||
#### Parent Module
|
||||
|
||||
Navigates to the parent module of the current module.
|
||||
|
||||
#### Matching Brace
|
||||
|
||||
If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
|
||||
moves cursor to the matching brace. It uses the actual parser to determine
|
||||
braces, so it won't confuse generics with comparisons.
|
||||
|
||||
#### Join Lines
|
||||
|
||||
Join selected lines into one, smartly fixing up whitespace and trailing commas.
|
||||
|
||||
#### Show Syntax Tree
|
||||
|
||||
Shows the parse tree of the current file. It exists mostly for debugging
|
||||
rust-analyzer itself.
|
||||
|
||||
#### Status
|
||||
|
||||
Shows internal statistic about memory usage of rust-analyzer
|
||||
|
||||
#### Run garbage collection
|
||||
|
||||
Manually triggers GC
|
||||
|
||||
### Code Actions (Assists)
|
||||
|
||||
These are triggered in a particular context via light bulb. We use custom code on
|
||||
the VS Code side to be able to position cursor. `<|>` signifies cursor
|
||||
|
||||
- Add `#[derive]`
|
||||
|
||||
```rust
|
||||
// before:
|
||||
struct Foo {
|
||||
<|>x: i32
|
||||
}
|
||||
// after:
|
||||
#[derive(<|>)]
|
||||
struct Foo {
|
||||
x: i32
|
||||
}
|
||||
```
|
||||
|
||||
- Add `impl`
|
||||
|
||||
```rust
|
||||
// before:
|
||||
struct Foo<'a, T: Debug> {
|
||||
<|>t: T
|
||||
}
|
||||
// after:
|
||||
struct Foo<'a, T: Debug> {
|
||||
t: T
|
||||
}
|
||||
|
||||
impl<'a, T: Debug> Foo<'a, T> {
|
||||
<|>
|
||||
}
|
||||
```
|
||||
|
||||
- Add missing `impl` members
|
||||
|
||||
```rust
|
||||
// before:
|
||||
trait Foo {
|
||||
fn foo(&self);
|
||||
fn bar(&self);
|
||||
fn baz(&self);
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl Foo for S {
|
||||
fn bar(&self) {}
|
||||
<|>
|
||||
}
|
||||
|
||||
// after:
|
||||
trait Foo {
|
||||
fn foo(&self);
|
||||
fn bar(&self);
|
||||
fn baz(&self);
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl Foo for S {
|
||||
fn bar(&self) {}
|
||||
fn foo(&self) { unimplemented!() }
|
||||
fn baz(&self) { unimplemented!() }<|>
|
||||
}
|
||||
```
|
||||
|
||||
- Import path
|
||||
|
||||
```rust
|
||||
// before:
|
||||
impl std::fmt::Debug<|> for Foo {
|
||||
}
|
||||
|
||||
// after:
|
||||
use std::fmt::Debug;
|
||||
|
||||
impl Debug<|> for Foo {
|
||||
}
|
||||
```
|
||||
|
||||
- Change Visibility
|
||||
|
||||
```rust
|
||||
// before:
|
||||
<|>fn foo() {}
|
||||
|
||||
// after:
|
||||
<|>pub(crate) fn foo() {}
|
||||
|
||||
// after:
|
||||
<|>pub fn foo() {}
|
||||
```
|
||||
|
||||
- Fill match arms
|
||||
|
||||
```rust
|
||||
// before:
|
||||
enum A {
|
||||
As,
|
||||
Bs,
|
||||
Cs(String),
|
||||
Ds(String, String),
|
||||
Es{x: usize, y: usize}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = A::As;
|
||||
match a<|> {}
|
||||
}
|
||||
|
||||
// after:
|
||||
enum A {
|
||||
As,
|
||||
Bs,
|
||||
Cs(String),
|
||||
Ds(String, String),
|
||||
Es{x: usize, y: usize}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = A::As;
|
||||
match <|>a {
|
||||
A::As => (),
|
||||
A::Bs => (),
|
||||
A::Cs(_) => (),
|
||||
A::Ds(_, _) => (),
|
||||
A::Es{x, y} => (),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-- Fill struct fields
|
||||
|
||||
```rust
|
||||
// before:
|
||||
struct S<'a, D> {
|
||||
a: u32,
|
||||
b: String,
|
||||
c: (i32, i32),
|
||||
d: D,
|
||||
r: &'a str,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = S<|> {}
|
||||
}
|
||||
|
||||
// after:
|
||||
struct S<'a, D> {
|
||||
a: u32,
|
||||
b: String,
|
||||
c: (i32, i32),
|
||||
d: D,
|
||||
r: &'a str,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = <|>S {
|
||||
a: (),
|
||||
b: (),
|
||||
c: (),
|
||||
d: (),
|
||||
r: (),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Flip `,`
|
||||
|
||||
```rust
|
||||
// before:
|
||||
fn foo(x: usize,<|> dim: (usize, usize)) {}
|
||||
// after:
|
||||
fn foo(dim: (usize, usize), x: usize) {}
|
||||
```
|
||||
|
||||
- Introduce variable:
|
||||
|
||||
```rust
|
||||
// before:
|
||||
fn foo() {
|
||||
foo(<|>1 + 1<|>);
|
||||
}
|
||||
|
||||
// after:
|
||||
fn foo() {
|
||||
let var_name = 1 + 1;
|
||||
foo(var_name);
|
||||
}
|
||||
```
|
||||
|
||||
-- Remove `dbg!`
|
||||
|
||||
```rust
|
||||
// before:
|
||||
fn foo(n: usize) {
|
||||
if let Some(_) = dbg!(n.<|>checked_sub(4)) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
// after:
|
||||
fn foo(n: usize) {
|
||||
if let Some(_) = n.<|>checked_sub(4) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Replace if-let with match:
|
||||
|
||||
```rust
|
||||
// before:
|
||||
impl VariantData {
|
||||
pub fn is_struct(&self) -> bool {
|
||||
if <|>let VariantData::Struct(..) = *self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// after:
|
||||
impl VariantData {
|
||||
pub fn is_struct(&self) -> bool {
|
||||
<|>match *self {
|
||||
VariantData::Struct(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Split import
|
||||
|
||||
```rust
|
||||
// before:
|
||||
use algo:<|>:visitor::{Visitor, visit};
|
||||
//after:
|
||||
use algo::{<|>visitor::{Visitor, visit}};
|
||||
```
|
||||
|
||||
### Magic Completions
|
||||
|
||||
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 function
|
||||
takes arguments, cursor is positioned inside the parenthesis.
|
||||
|
||||
There are postifx completions, which can be triggerd by typing something like
|
||||
`foo().if`. The word after `.` determines postifx completion, possible variants are:
|
||||
|
||||
- `expr.if` -> `if expr {}`
|
||||
- `expr.match` -> `match expr {}`
|
||||
- `expr.while` -> `while expr {}`
|
||||
- `expr.ref` -> `&expr`
|
||||
- `expr.refm` -> `&mut expr`
|
||||
- `expr.not` -> `!expr`
|
||||
- `expr.dbg` -> `dbg!(expr)`
|
||||
|
||||
There also snippet completions:
|
||||
|
||||
#### Inside Expressions
|
||||
|
||||
- `pd` -> `println!("{:?}")`
|
||||
- `ppd` -> `println!("{:#?}")`
|
||||
|
||||
#### Inside Modules
|
||||
|
||||
- `tfn` -> `#[test] fn f(){}`
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
|
||||
Prerequisites:
|
||||
|
||||
In order to build the VS Code plugin, you need to have node.js and npm with
|
||||
a minimum version of 10 installed. Please refer to
|
||||
[node.js and npm documentation](https://nodejs.org) for installation instructions.
|
||||
|
||||
You will also need the most recent version of VS Code: we don't try to
|
||||
maintain compatibility with older versions yet.
|
||||
|
||||
The experimental VS Code plugin can then be built and installed by executing the
|
||||
following commands:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
|
||||
$ cd rust-analyzer
|
||||
$ cargo install-code
|
||||
|
||||
# for stdlib support
|
||||
$ rustup component add rust-src
|
||||
```
|
||||
|
||||
This will run `cargo install --package ra_lsp_server` to install the server
|
||||
binary into `~/.cargo/bin`, and then will build and install plugin from
|
||||
`editors/code`. See
|
||||
[this](https://github.com/rust-analyzer/rust-analyzer/blob/0199572a3d06ff66eeae85a2d2c9762996f0d2d8/crates/tools/src/main.rs#L150)
|
||||
for details. The installation is expected to *just work*, if it doesn't, report
|
||||
bugs!
|
||||
|
||||
It's better to remove existing Rust plugins to avoid interference.
|
||||
|
||||
## Rust Analyzer Specific Features
|
||||
|
||||
These features are implemented as extensions to the language server protocol.
|
||||
They are more experimental in nature and work only with VS Code.
|
||||
|
||||
### Syntax highlighting
|
||||
|
||||
It overrides built-in highlighting, and works only with a specific theme
|
||||
(zenburn). `rust-analyzer.highlightingOn` setting can be used to disable it.
|
||||
|
||||
### Go to symbol in workspace <kbd>ctrl+t</kbd>
|
||||
|
||||
It mostly works on top of the built-in LSP functionality, however `#` and `*`
|
||||
symbols can be used to narrow down the search. Specifically,
|
||||
|
||||
- `#Foo` searches for `Foo` type in the current workspace
|
||||
- `#foo#` searches for `foo` function in the current workspace
|
||||
- `#Foo*` searches for `Foo` type among dependencies, excluding `stdlib`
|
||||
- `#foo#*` searches for `foo` function among dependencies.
|
||||
|
||||
That is, `#` switches from "types" to all symbols, `*` switches from the current
|
||||
workspace to dependencies.
|
||||
|
||||
### Commands <kbd>ctrl+shift+p</kbd>
|
||||
|
||||
#### Show Rust Syntax Tree
|
||||
|
||||
Shows the parse tree of the current file. It exists mostly for debugging
|
||||
rust-analyzer itself.
|
||||
|
||||
#### Extend Selection
|
||||
|
||||
Extends the current selection to the encompassing syntactic construct
|
||||
(expression, statement, item, module, etc). It works with multiple cursors. Do
|
||||
bind this command to a key, its super-useful! Expected to be upstreamed to LSP soonish:
|
||||
https://github.com/Microsoft/language-server-protocol/issues/613
|
||||
|
||||
#### Matching Brace
|
||||
|
||||
If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
|
||||
moves cursor to the matching brace. It uses the actual parser to determine
|
||||
braces, so it won't confuse generics with comparisons.
|
||||
|
||||
#### Parent Module
|
||||
|
||||
Navigates to the parent module of the current module.
|
||||
|
||||
#### Join Lines
|
||||
|
||||
Join selected lines into one, smartly fixing up whitespace and trailing commas.
|
||||
|
||||
#### Run
|
||||
|
||||
Shows popup suggesting to run a test/benchmark/binary **at the current cursor
|
||||
location**. Super useful for repeatedly running just a single test. Do bind this
|
||||
to a shortcut!
|
||||
|
||||
|
||||
### On Typing Assists
|
||||
|
||||
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
|
||||
|
||||
|
||||
### Code Actions (Assists)
|
||||
|
||||
These are triggered in a particular context via light bulb. We use custom code on
|
||||
the VS Code side to be able to position cursor.
|
||||
|
||||
|
||||
- Flip `,`
|
||||
|
||||
```rust
|
||||
// before:
|
||||
fn foo(x: usize,<|> dim: (usize, usize))
|
||||
// after:
|
||||
fn foo(dim: (usize, usize), x: usize)
|
||||
```
|
||||
|
||||
- Add `#[derive]`
|
||||
|
||||
```rust
|
||||
// before:
|
||||
struct Foo {
|
||||
<|>x: i32
|
||||
}
|
||||
// after:
|
||||
#[derive(<|>)]
|
||||
struct Foo {
|
||||
x: i32
|
||||
}
|
||||
```
|
||||
|
||||
- Add `impl`
|
||||
|
||||
```rust
|
||||
// before:
|
||||
struct Foo<'a, T: Debug> {
|
||||
<|>t: T
|
||||
}
|
||||
// after:
|
||||
struct Foo<'a, T: Debug> {
|
||||
t: T
|
||||
}
|
||||
|
||||
impl<'a, T: Debug> Foo<'a, T> {
|
||||
<|>
|
||||
}
|
||||
```
|
||||
|
||||
- Change visibility
|
||||
|
||||
```rust
|
||||
// before:
|
||||
fn<|> foo() {}
|
||||
|
||||
// after
|
||||
pub(crate) fn foo() {}
|
||||
```
|
||||
|
||||
- Introduce variable:
|
||||
|
||||
```rust
|
||||
// before:
|
||||
fn foo() {
|
||||
foo(<|>1 + 1<|>);
|
||||
}
|
||||
|
||||
// after:
|
||||
fn foo() {
|
||||
let var_name = 1 + 1;
|
||||
foo(var_name);
|
||||
}
|
||||
```
|
||||
|
||||
- Replace if-let with match:
|
||||
|
||||
```rust
|
||||
// before:
|
||||
impl VariantData {
|
||||
pub fn is_struct(&self) -> bool {
|
||||
if <|>let VariantData::Struct(..) = *self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// after:
|
||||
impl VariantData {
|
||||
pub fn is_struct(&self) -> bool {
|
||||
<|>match *self {
|
||||
VariantData::Struct(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Split import
|
||||
|
||||
```rust
|
||||
// before:
|
||||
use algo:<|>:visitor::{Visitor, visit};
|
||||
//after:
|
||||
use algo::{<|>visitor::{Visitor, visit}};
|
||||
```
|
||||
|
||||
## LSP features
|
||||
|
||||
* **Go to definition**: works correctly for local variables and some paths,
|
||||
falls back to heuristic name matching for other things for the time being.
|
||||
|
||||
* **Completion**: completes paths, including dependencies and standard library.
|
||||
Does not handle glob imports and macros. Completes fields and inherent
|
||||
methods.
|
||||
|
||||
* **Outline** <kbd>alt+shift+o</kbd>
|
||||
|
||||
* **Signature Info**
|
||||
|
||||
* **Format document**. Formats the current file with rustfmt. Rustfmt must be
|
||||
installed separately with `rustup component add rustfmt`.
|
||||
|
||||
* **Hover** shows types of expressions and docstings
|
||||
|
||||
* **Rename** works for local variables
|
||||
|
||||
* **Code Lens** for running tests
|
||||
|
||||
* **Folding**
|
||||
|
||||
* **Diagnostics**
|
||||
- missing module for `mod foo;` with a fix to create `foo.rs`.
|
||||
- struct field shorthand
|
||||
- unnecessary braces in use item
|
||||
|
||||
|
||||
## Performance
|
||||
|
||||
Rust Analyzer is expected to be pretty fast. Specifically, the initial analysis
|
||||
of the project (i.e, when you first invoke completion or symbols) typically
|
||||
takes dozen of seconds at most. After that, everything is supposed to be more or
|
||||
less instant. However currently all analysis results are kept in memory, so
|
||||
memory usage is pretty high. Working with `rust-lang/rust` repo, for example,
|
||||
needs about 5 gigabytes of ram.
|
Loading…
Reference in a new issue