From 91203699eccf63ee21fee236f493c361c64b5d86 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 09:37:51 +0300 Subject: [PATCH 01/15] introduce docs dir --- README.md | 72 -------------------- ARCHITECTURE.md => docs/dev/ARCHITECTURE.md | 0 CONTRIBUTING.md => docs/dev/CONTRIBUTING.md | 0 DEBUGGING.md => docs/dev/DEBUGGING.md | 0 ROADMAP.md => docs/dev/ROADMAP.md | 0 guide.md => docs/dev/guide.md | 0 docs/dev/lsp-features.md | 74 +++++++++++++++++++++ {editors => docs/user}/README.md | 0 8 files changed, 74 insertions(+), 72 deletions(-) rename ARCHITECTURE.md => docs/dev/ARCHITECTURE.md (100%) rename CONTRIBUTING.md => docs/dev/CONTRIBUTING.md (100%) rename DEBUGGING.md => docs/dev/DEBUGGING.md (100%) rename ROADMAP.md => docs/dev/ROADMAP.md (100%) rename guide.md => docs/dev/guide.md (100%) create mode 100644 docs/dev/lsp-features.md rename {editors => docs/user}/README.md (100%) diff --git a/README.md b/README.md index 5bc90a3f01..acce7219e1 100644 --- a/README.md +++ b/README.md @@ -50,78 +50,6 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 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 diff --git a/ARCHITECTURE.md b/docs/dev/ARCHITECTURE.md similarity index 100% rename from ARCHITECTURE.md rename to docs/dev/ARCHITECTURE.md diff --git a/CONTRIBUTING.md b/docs/dev/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to docs/dev/CONTRIBUTING.md diff --git a/DEBUGGING.md b/docs/dev/DEBUGGING.md similarity index 100% rename from DEBUGGING.md rename to docs/dev/DEBUGGING.md diff --git a/ROADMAP.md b/docs/dev/ROADMAP.md similarity index 100% rename from ROADMAP.md rename to docs/dev/ROADMAP.md diff --git a/guide.md b/docs/dev/guide.md similarity index 100% rename from guide.md rename to docs/dev/guide.md diff --git a/docs/dev/lsp-features.md b/docs/dev/lsp-features.md new file mode 100644 index 0000000000..212d132eed --- /dev/null +++ b/docs/dev/lsp-features.md @@ -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) diff --git a/editors/README.md b/docs/user/README.md similarity index 100% rename from editors/README.md rename to docs/user/README.md From 206bbe9c93f3fd33922c9e00cfb263b980a79ca2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 10:00:54 +0300 Subject: [PATCH 02/15] README is short and up to the point --- README.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index acce7219e1..4cada764de 100644 --- a/README.md +++ b/README.md @@ -13,32 +13,37 @@ Work on the Rust Analyzer is sponsored by [![Ferrous Systems](https://ferrous-systems.com/images/ferrous-logo-text.svg)](https://ferrous-systems.com/) -## Quick Start +## Language Server Quick Start -Rust analyzer builds on Rust >= 1.31.0 and uses the 2018 edition. +Rust Analyzer is a work-in-progress, so you'll have to build it from source, and +you might encounter critical bugs. That said, it is complete enough to provide a +useful IDE experience and some people use it as a daily driver. + +To build rust-analyzer, you need: + +* latest stable rust for language server itself +* latest stable npm and VS Code for VS Code extension (`code` should be a path) + +For setup for other languages, see [./docs/users]. ``` -# run tests -$ cargo test +# clone the repo +$ git clone https://github.com/rust-analyzer/rust-analyzer && cd rust-analyzer -# show syntax tree of a Rust file -$ cargo run --package ra_cli parse < crates/ra_syntax/src/lib.rs +# install both the language server and VS Code extension +$ cargo install-code -# show symbols of a Rust file -$ cargo run --package ra_cli symbols < crates/ra_syntax/src/lib.rs - -# install the language server +# alternatively, install only the server. Binary name is `ra_lsp_server`. $ cargo install-lsp -or -$ cargo install --path crates/ra_lsp_server ``` +## Documentation -See [these instructions](./editors/README.md) for VS Code setup and the list of -features (some of which are VS Code specific). +If you want to **contribute** to rust-analyzer or just curious about how things work +under the hood, check the [./docs/dev] folder. -## Debugging - -See [these instructions](./DEBUGGING.md) on how to debug the vscode extension and the lsp server. +If you want to **use** rust-analyzer's language server with your editor of +choice, check [./docs/users] folder. It also contains some tips & tricks to help +you be more productive when using rust-analyzer. ## Getting in touch @@ -46,11 +51,6 @@ We are on the rust-lang Zulip! https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 -## Contributing - -See [CONTRIBUTING.md](./CONTRIBUTING.md) and [ARCHITECTURE.md](./ARCHITECTURE.md) - - ## License Rust analyzer is primarily distributed under the terms of both the MIT From 192a5cd11d413fdbaeb8d2e5106d82ae3b4a05c1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 12:17:12 +0300 Subject: [PATCH 03/15] better user docs --- docs/user/README.md | 248 +++++++----------------------------------- docs/user/features.md | 168 ++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+), 206 deletions(-) create mode 100644 docs/user/features.md diff --git a/docs/user/README.md b/docs/user/README.md index ddc6ee0485..b25e152d0a 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -1,3 +1,22 @@ +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] document for a list of features that are available. + +## VS Code Prerequisites: @@ -15,227 +34,44 @@ 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) +[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. -## Rust Analyzer Specific Features +Beyond basic LSP features, there are some extension commands which you can +invoke via Ctrl+Shift+P or bind to a shortcut. See [./features.md] +for details. -These features are implemented as extensions to the language server protocol. -They are more experimental in nature and work only with VS Code. +### Settings -### 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 ctrl+t - -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 ctrl+shift+p - -#### 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! +* `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 -### On Typing Assists +## Emacs -Some features trigger on typing certain characters: +Prerequisites: -- 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 +`emacs-lsp`, `dash` and `ht` packages. +Installation: -### 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** alt+shift+o - -* **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. +* 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 `join-lines` or `extend-selection` to keys diff --git a/docs/user/features.md b/docs/user/features.md new file mode 100644 index 0000000000..5df606aee0 --- /dev/null +++ b/docs/user/features.md @@ -0,0 +1,168 @@ +This documents is an index of features that rust-analyzer language server provides. + +### Go to symbol in workspace ctrl+t + +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 ctrl+shift+p + +#### 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}}; +``` + + From 56ad19ef025ddf8461b56c5f42ca074e4f2ebe23 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 12:21:55 +0300 Subject: [PATCH 04/15] fix links --- README.md | 6 +++--- docs/user/README.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4cada764de..7debf7c3b3 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ 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 a path) -For setup for other languages, see [./docs/users]. +For setup for other languages, see [./docs/users](./docs/users). ``` # clone the repo @@ -39,10 +39,10 @@ $ cargo install-lsp ## Documentation If you want to **contribute** to rust-analyzer or just curious about how things work -under the hood, check the [./docs/dev] folder. +under the hood, check the [./docs/dev](./docs/dev) folder. If you want to **use** rust-analyzer's language server with your editor of -choice, check [./docs/users] folder. It also contains some tips & tricks to help +choice, check [./docs/users](./docs/users) folder. It also contains some tips & tricks to help you be more productive when using rust-analyzer. ## Getting in touch diff --git a/docs/user/README.md b/docs/user/README.md index b25e152d0a..8de46981b0 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -14,7 +14,7 @@ to execute $ rustup component add rust-src ``` -See [./features.md] document for a list of features that are available. +See [./features.md](./features.md) document for a list of features that are available. ## VS Code @@ -46,7 +46,7 @@ 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 Ctrl+Shift+P or bind to a shortcut. See [./features.md] +invoke via Ctrl+Shift+P or bind to a shortcut. See [./features.md](./features.md) for details. ### Settings From 505bd45bcc44ee58090e514f46cbe884924e3574 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 12:24:12 +0300 Subject: [PATCH 05/15] fix links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7debf7c3b3..638804632a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ 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 a path) -For setup for other languages, see [./docs/users](./docs/users). +For setup for other languages, see [./docs/user](./docs/user). ``` # clone the repo @@ -42,7 +42,7 @@ If you want to **contribute** to rust-analyzer or just curious about how things under the hood, check the [./docs/dev](./docs/dev) folder. If you want to **use** rust-analyzer's language server with your editor of -choice, check [./docs/users](./docs/users) folder. It also contains some tips & tricks to help +choice, check [./docs/user](./docs/user) folder. It also contains some tips & tricks to help you be more productive when using rust-analyzer. ## Getting in touch From ab9fef1ee26c185cdf2b14c3d21ecfae7b0905ae Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 12:25:03 +0300 Subject: [PATCH 06/15] sadly, we support only a single language atm --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 638804632a..ad3ad22c31 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ 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 a path) -For setup for other languages, see [./docs/user](./docs/user). +For setup for other editors, see [./docs/user](./docs/user). ``` # clone the repo From 07a9e5c0e1c20f66730f608647e96ce29359b91d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 13:05:03 +0300 Subject: [PATCH 07/15] document assists --- docs/user/features.md | 269 +++++++++++++++++++++++++++++++++--------- 1 file changed, 212 insertions(+), 57 deletions(-) diff --git a/docs/user/features.md b/docs/user/features.md index 5df606aee0..aa3bf5157e 100644 --- a/docs/user/features.md +++ b/docs/user/features.md @@ -1,52 +1,30 @@ -This documents is an index of features that rust-analyzer language server provides. +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 Ctrl+Shift+P to search for the corresponding action. -### Go to symbol in workspace ctrl+t +### Workspace Symbol ctrl+t -It mostly works on top of the built-in LSP functionality, however `#` and `*` -symbols can be used to narrow down the search. Specifically, +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. +- `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 ctrl+shift+p +### Document Symbol ctrl+shift+o -#### 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! +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 @@ -56,24 +34,52 @@ Some features trigger on typing certain characters: - Enter inside comments automatically inserts `///` - typing `.` in a chain method call auto-indents +### Commands ctrl+shift+p +#### 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. - - -- Flip `,` - -```rust -// before: -fn foo(x: usize,<|> dim: (usize, usize)) -// after: -fn foo(dim: (usize, usize), x: usize) -``` +the VS Code side to be able to position cursor. `<|>` signifies cursor - Add `#[derive]` @@ -106,14 +112,147 @@ impl<'a, T: Debug> Foo<'a, T> { } ``` -- Change visibility +- Add missing `impl` members ```rust // before: -fn<|> foo() {} +trait Foo { + fn foo(&self); + fn bar(&self); + fn baz(&self); +} -// after -pub(crate) fn foo() {} +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: @@ -131,6 +270,24 @@ fn foo() { } ``` +-- 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 @@ -164,5 +321,3 @@ use algo:<|>:visitor::{Visitor, visit}; //after: use algo::{<|>visitor::{Visitor, visit}}; ``` - - From dbed0f0e9960904193fd56327201b91bf585e016 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 13:19:46 +0300 Subject: [PATCH 08/15] document some nice things --- docs/user/features.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/user/features.md b/docs/user/features.md index aa3bf5157e..90f182f357 100644 --- a/docs/user/features.md +++ b/docs/user/features.md @@ -321,3 +321,39 @@ 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(){}` + From fbf35c839b706286307b673a3dd6231c81ad4661 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 14:49:06 +0300 Subject: [PATCH 09/15] kill old roadmap: it is completed --- docs/dev/ROADMAP.md | 77 --------------------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 docs/dev/ROADMAP.md diff --git a/docs/dev/ROADMAP.md b/docs/dev/ROADMAP.md deleted file mode 100644 index 3856ebc5bb..0000000000 --- a/docs/dev/ROADMAP.md +++ /dev/null @@ -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. From 728990a5807882276e34f1f581f70a59f61ba991 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 15:22:05 +0300 Subject: [PATCH 10/15] start dev readme --- docs/dev/README.md | 37 +++++++++++++++++++ docs/dev/{ARCHITECTURE.md => arhictecture.md} | 0 2 files changed, 37 insertions(+) create mode 100644 docs/dev/README.md rename docs/dev/{ARCHITECTURE.md => arhictecture.md} (100%) diff --git a/docs/dev/README.md b/docs/dev/README.md new file mode 100644 index 0000000000..74bf86f68a --- /dev/null +++ b/docs/dev/README.md @@ -0,0 +1,37 @@ +# 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. + diff --git a/docs/dev/ARCHITECTURE.md b/docs/dev/arhictecture.md similarity index 100% rename from docs/dev/ARCHITECTURE.md rename to docs/dev/arhictecture.md From ac6749d18ca9f32eedbc88a68ec41dbb3342a1e1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 15:25:05 +0300 Subject: [PATCH 11/15] fixes --- docs/user/README.md | 2 +- docs/user/features.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user/README.md b/docs/user/README.md index 8de46981b0..439c4e6ae5 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -74,4 +74,4 @@ Installation: [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 `join-lines` or `extend-selection` to keys +* (Optionally) bind commands like `rust-analyzer-join-lines` or `rust-analyzer-extend-selection` to keys diff --git a/docs/user/features.md b/docs/user/features.md index 90f182f357..b9d2aa84f8 100644 --- a/docs/user/features.md +++ b/docs/user/features.md @@ -153,7 +153,7 @@ impl std::fmt::Debug<|> for Foo { } // after: -use std::fmt::Debug +use std::fmt::Debug; impl Debug<|> for Foo { } From 1ad322236dbe54ada2c284bda4a2b72830b3ff3d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 15:34:09 +0300 Subject: [PATCH 12/15] remove old contributing --- docs/dev/CONTRIBUTING.md | 18 ------------------ docs/dev/README.md | 6 ++++++ 2 files changed, 6 insertions(+), 18 deletions(-) delete mode 100644 docs/dev/CONTRIBUTING.md diff --git a/docs/dev/CONTRIBUTING.md b/docs/dev/CONTRIBUTING.md deleted file mode 100644 index a2efc7afa5..0000000000 --- a/docs/dev/CONTRIBUTING.md +++ /dev/null @@ -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. diff --git a/docs/dev/README.md b/docs/dev/README.md index 74bf86f68a..0c09dddfc9 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -35,3 +35,9 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 * [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. From d56c2f24252d5d444267e33950825f0a7cb438ca Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 16:05:49 +0300 Subject: [PATCH 13/15] explain how to launch the thing --- docs/dev/README.md | 81 +++++++++++++++++++ docs/dev/{arhictecture.md => architecture.md} | 46 +++-------- docs/dev/{DEBUGGING.md => debugging.md} | 0 3 files changed, 91 insertions(+), 36 deletions(-) rename docs/dev/{arhictecture.md => architecture.md} (83%) rename docs/dev/{DEBUGGING.md => debugging.md} (100%) diff --git a/docs/dev/README.md b/docs/dev/README.md index 0c09dddfc9..ac7f4fd71b 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -41,3 +41,84 @@ 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 F5 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. diff --git a/docs/dev/arhictecture.md b/docs/dev/architecture.md similarity index 83% rename from docs/dev/arhictecture.md rename to docs/dev/architecture.md index 57f76ebaec..3cd63bf732 100644 --- a/docs/dev/arhictecture.md +++ b/docs/dev/architecture.md @@ -7,8 +7,10 @@ in the right place! See also the [guide](./guide.md), which walks through a particular snapshot of rust-analyzer code base. -For syntax-trees specifically, there's a [video walk -through](https://youtu.be/DGAuLWdCCAI) as well. +Yet another resource is this playlist with videos about various parts of the +analyzer: + +https://www.youtube.com/playlist?list=PL85XCvVPmGQho7MZkdW-wtPtuJcFpzycE ## The Big Picture @@ -61,7 +63,7 @@ processes. These are outlined below: ## Code Walk-Through -### `crates/ra_syntax` +### `crates/ra_syntax`, `crates/ra_parser` Rust syntax tree structure and parser. See [RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design notes. @@ -145,12 +147,14 @@ throughout its modules. An LSP implementation which wraps `ra_ide_api` into a langauge server protocol. -### `crates/ra_vfs` +### `ra_vfs` Although `hir` and `ra_ide_api` don't do any IO, we need to be able to read files from disk at the end of the day. This is what `ra_vfs` does. It also manages overlays: "dirty" files in the editor, whose "true" contents is -different from data on disk. +different from data on disk. This is more or less the single really +platform-dependent component, so it lives in a separate repository and has an +extensive cross-platform CI testing. ### `crates/gen_lsp_server` @@ -164,37 +168,7 @@ Run with `RUST_LOG=sync_lsp_server=debug` to see all the messages. A CLI interface to rust-analyzer. -### `crate/tools` -Custom Cargo tasks used to develop rust-analyzer: - -- `cargo gen-syntax` -- generate `ast` and `syntax_kinds` -- `cargo gen-tests` -- collect inline tests from grammar -- `cargo install-code` -- build and install VS Code extension and server - -### `editors/code` - -VS Code plugin +## Testing Infrastructure -## Common workflows - -To try out VS Code extensions, run `cargo install-code`. This installs both the -`ra_lsp_server` binary and the VS Code extension. To install only the binary, use -`cargo install-lsp` (shorthand for `cargo install --path crates/ra_lsp_server --force`) - -To see logs from the language server, set `RUST_LOG=info` env variable. To see -all communication between the server and the client, use -`RUST_LOG=gen_lsp_server=debug` (this will print quite a bit of stuff). - -There's `rust-analyzer: status` command which prints common high-level debug -info. In particular, it prints info about memory usage of various data -structures, and, if compiled with jemalloc support (`cargo jinstall-lsp` or -`cargo install --path crates/ra_lsp_server --force --features jemalloc`), includes - statistic about the heap. - -To run tests, just `cargo test`. - -To work on the VS Code extension, launch code inside `editors/code` and use `F5` to -launch/debug. To automatically apply formatter and linter suggestions, use `npm -run fix`. diff --git a/docs/dev/DEBUGGING.md b/docs/dev/debugging.md similarity index 100% rename from docs/dev/DEBUGGING.md rename to docs/dev/debugging.md From 86d5c32e4a96dc18ebc3f834ee74d403e4deceba Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Mar 2019 17:22:22 +0300 Subject: [PATCH 14/15] describe how do we test things --- docs/dev/architecture.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index 3cd63bf732..f990d5bf0e 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md @@ -171,4 +171,29 @@ A CLI interface to rust-analyzer. ## Testing Infrastructure +Rust Analyzer has three interesting [systems +boundaries](https://www.tedinski.com/2018/04/10/making-tests-a-positive-influence-on-design.html) +to concentrate tests on. +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. + +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. + +For comparisons, we use [insta](https://github.com/mitsuhiko/insta/) library for +snapshot testing. + +To test various analysis corner cases and avoid forgetting about old tests, we +use so-called marks. See the `marks` module in the `test_utils` crate for more. From 290237d2eb472522191721397d0c4db905cdc565 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 20 Mar 2019 17:39:56 +0300 Subject: [PATCH 15/15] Update README.md Co-Authored-By: matklad --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad3ad22c31..3a0c9dee16 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ 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 a path) +* 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).