mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 13:33:31 +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/)
|
[![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
|
# clone the repo
|
||||||
$ cargo test
|
$ git clone https://github.com/rust-analyzer/rust-analyzer && cd rust-analyzer
|
||||||
|
|
||||||
# show syntax tree of a Rust file
|
# install both the language server and VS Code extension
|
||||||
$ cargo run --package ra_cli parse < crates/ra_syntax/src/lib.rs
|
$ cargo install-code
|
||||||
|
|
||||||
# show symbols of a Rust file
|
# alternatively, install only the server. Binary name is `ra_lsp_server`.
|
||||||
$ cargo run --package ra_cli symbols < crates/ra_syntax/src/lib.rs
|
|
||||||
|
|
||||||
# install the language server
|
|
||||||
$ cargo install-lsp
|
$ 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
|
If you want to **contribute** to rust-analyzer or just curious about how things work
|
||||||
features (some of which are VS Code specific).
|
under the hood, check the [./docs/dev](./docs/dev) folder.
|
||||||
|
|
||||||
## Debugging
|
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
|
||||||
See [these instructions](./DEBUGGING.md) on how to debug the vscode extension and the lsp server.
|
you be more productive when using rust-analyzer.
|
||||||
|
|
||||||
## Getting in touch
|
## 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
|
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
|
## License
|
||||||
|
|
||||||
Rust analyzer is primarily distributed under the terms of both the MIT
|
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
|
See also the [guide](./guide.md), which walks through a particular snapshot of
|
||||||
rust-analyzer code base.
|
rust-analyzer code base.
|
||||||
|
|
||||||
For syntax-trees specifically, there's a [video walk
|
Yet another resource is this playlist with videos about various parts of the
|
||||||
through](https://youtu.be/DGAuLWdCCAI) as well.
|
analyzer:
|
||||||
|
|
||||||
|
https://www.youtube.com/playlist?list=PL85XCvVPmGQho7MZkdW-wtPtuJcFpzycE
|
||||||
|
|
||||||
## The Big Picture
|
## The Big Picture
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ processes. These are outlined below:
|
||||||
|
|
||||||
## Code Walk-Through
|
## Code Walk-Through
|
||||||
|
|
||||||
### `crates/ra_syntax`
|
### `crates/ra_syntax`, `crates/ra_parser`
|
||||||
|
|
||||||
Rust syntax tree structure and parser. See
|
Rust syntax tree structure and parser. See
|
||||||
[RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design notes.
|
[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.
|
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
|
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
|
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
|
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`
|
### `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.
|
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`
|
Rust Analyzer has three interesting [systems
|
||||||
- `cargo gen-tests` -- collect inline tests from grammar
|
boundaries](https://www.tedinski.com/2018/04/10/making-tests-a-positive-influence-on-design.html)
|
||||||
- `cargo install-code` -- build and install VS Code extension and server
|
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
|
To test various analysis corner cases and avoid forgetting about old tests, we
|
||||||
`ra_lsp_server` binary and the VS Code extension. To install only the binary, use
|
use so-called marks. See the `marks` module in the `test_utils` crate for more.
|
||||||
`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`.
|
|
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