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:
bors[bot] 2019-03-20 14:48:25 +00:00
commit 90ff3ba641
11 changed files with 687 additions and 462 deletions

View file

@ -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
View file

@ -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

View file

@ -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
View 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.

View file

@ -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
View 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
View 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
View 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(){}`

View file

@ -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.