diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index a2efc7afa5..0000000000
--- a/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/README.md b/README.md
index 5bc90a3f01..3a0c9dee16 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 in path)
+
+For setup for other editors, see [./docs/user](./docs/user).
```
-# run tests
-$ cargo test
+# clone the repo
+$ git clone https://github.com/rust-analyzer/rust-analyzer && cd rust-analyzer
-# show syntax tree of a Rust file
-$ cargo run --package ra_cli parse < crates/ra_syntax/src/lib.rs
+# install both the language server and VS Code extension
+$ cargo install-code
-# show symbols of a Rust file
-$ cargo run --package ra_cli symbols < crates/ra_syntax/src/lib.rs
-
-# install the language server
+# alternatively, install only the server. Binary name is `ra_lsp_server`.
$ cargo install-lsp
-or
-$ cargo install --path crates/ra_lsp_server
```
+## Documentation
-See [these instructions](./editors/README.md) for VS Code setup and the list of
-features (some of which are VS Code specific).
+If you want to **contribute** to rust-analyzer or just curious about how things work
+under the hood, check the [./docs/dev](./docs/dev) folder.
-## Debugging
-
-See [these instructions](./DEBUGGING.md) on how to debug the vscode extension and the lsp server.
+If you want to **use** rust-analyzer's language server with your editor of
+choice, check [./docs/user](./docs/user) folder. It also contains some tips & tricks to help
+you be more productive when using rust-analyzer.
## Getting in touch
@@ -46,83 +51,6 @@ We are on the rust-lang Zulip!
https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0
-## Contributing
-
-See [CONTRIBUTING.md](./CONTRIBUTING.md) and [ARCHITECTURE.md](./ARCHITECTURE.md)
-
-## Supported LSP features
-
-### General
-- [x] [initialize](https://microsoft.github.io/language-server-protocol/specification#initialize)
-- [x] [initialized](https://microsoft.github.io/language-server-protocol/specification#initialized)
-- [x] [shutdown](https://microsoft.github.io/language-server-protocol/specification#shutdown)
-- [ ] [exit](https://microsoft.github.io/language-server-protocol/specification#exit)
-- [x] [$/cancelRequest](https://microsoft.github.io/language-server-protocol/specification#cancelRequest)
-
-### Workspace
-- [ ] [workspace/workspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_workspaceFolders)
-- [ ] [workspace/didChangeWorkspaceFolders](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWorkspaceFolders)
-- [x] [workspace/didChangeConfiguration](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeConfiguration)
-- [ ] [workspace/configuration](https://microsoft.github.io/language-server-protocol/specification#workspace_configuration)
-- [x] [workspace/didChangeWatchedFiles](https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeWatchedFiles)
-- [x] [workspace/symbol](https://microsoft.github.io/language-server-protocol/specification#workspace_symbol)
-- [x] [workspace/executeCommand](https://microsoft.github.io/language-server-protocol/specification#workspace_executeCommand)
- - `apply_code_action`
-- [ ] [workspace/applyEdit](https://microsoft.github.io/language-server-protocol/specification#workspace_applyEdit)
-
-### Text Synchronization
-- [x] [textDocument/didOpen](https://microsoft.github.io/language-server-protocol/specification#textDocument_didOpen)
-- [x] [textDocument/didChange](https://microsoft.github.io/language-server-protocol/specification#textDocument_didChange)
-- [ ] [textDocument/willSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSave)
-- [ ] [textDocument/willSaveWaitUntil](https://microsoft.github.io/language-server-protocol/specification#textDocument_willSaveWaitUntil)
-- [x] [textDocument/didSave](https://microsoft.github.io/language-server-protocol/specification#textDocument_didSave)
-- [x] [textDocument/didClose](https://microsoft.github.io/language-server-protocol/specification#textDocument_didClose)
-
-### Diagnostics
-- [x] [textDocument/publishDiagnostics](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics)
-
-### Lanuguage Features
-- [x] [textDocument/completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
- - open close: false
- - change: Full
- - will save: false
- - will save wait until: false
- - save: false
-- [x] [completionItem/resolve](https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve)
- - resolve provider: none
- - trigger characters: `:`, `.`
-- [x] [textDocument/hover](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
-- [x] [textDocument/signatureHelp](https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp)
- - trigger characters: `(`, `,`, `)`
-- [ ] [textDocument/declaration](https://microsoft.github.io/language-server-protocol/specification#textDocument_declaration)
-- [x] [textDocument/definition](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition)
-- [ ] [textDocument/typeDefinition](https://microsoft.github.io/language-server-protocol/specification#textDocument_typeDefinition)
-- [x] [textDocument/implementation](https://microsoft.github.io/language-server-protocol/specification#textDocument_implementation)
-- [x] [textDocument/references](https://microsoft.github.io/language-server-protocol/specification#textDocument_references)
-- [x] [textDocument/documentHighlight](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight)
-- [x] [textDocument/documentSymbol](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol)
-- [x] [textDocument/codeAction](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction)
- - rust-analyzer.syntaxTree
- - rust-analyzer.extendSelection
- - rust-analyzer.matchingBrace
- - rust-analyzer.parentModule
- - rust-analyzer.joinLines
- - rust-analyzer.run
- - rust-analyzer.analyzerStatus
-- [x] [textDocument/codeLens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
-- [ ] [textDocument/documentLink](https://microsoft.github.io/language-server-protocol/specification#codeLens_resolve)
-- [ ] [documentLink/resolve](https://microsoft.github.io/language-server-protocol/specification#documentLink_resolve)
-- [ ] [textDocument/documentColor](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor)
-- [ ] [textDocument/colorPresentation](https://microsoft.github.io/language-server-protocol/specification#textDocument_colorPresentation)
-- [x] [textDocument/formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting)
-- [ ] [textDocument/rangeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting)
-- [x] [textDocument/onTypeFormatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting)
- - first trigger character: `=`
- - more trigger character `.`
-- [x] [textDocument/rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_rename)
-- [x] [textDocument/prepareRename](https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename)
-- [x] [textDocument/foldingRange](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)
-
## License
Rust analyzer is primarily distributed under the terms of both the MIT
diff --git a/ROADMAP.md b/ROADMAP.md
deleted file mode 100644
index 3856ebc5bb..0000000000
--- a/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.
diff --git a/docs/dev/README.md b/docs/dev/README.md
new file mode 100644
index 0000000000..ac7f4fd71b
--- /dev/null
+++ b/docs/dev/README.md
@@ -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 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/ARCHITECTURE.md b/docs/dev/architecture.md
similarity index 80%
rename from ARCHITECTURE.md
rename to docs/dev/architecture.md
index 57f76ebaec..f990d5bf0e 100644
--- a/ARCHITECTURE.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,32 @@ Run with `RUST_LOG=sync_lsp_server=debug` to see all the messages.
A CLI interface to rust-analyzer.
-### `crate/tools`
-Custom Cargo tasks used to develop rust-analyzer:
+## Testing Infrastructure
-- `cargo gen-syntax` -- generate `ast` and `syntax_kinds`
-- `cargo gen-tests` -- collect inline tests from grammar
-- `cargo install-code` -- build and install VS Code extension and server
+Rust Analyzer has three interesting [systems
+boundaries](https://www.tedinski.com/2018/04/10/making-tests-a-positive-influence-on-design.html)
+to concentrate tests on.
-### `editors/code`
+The outermost boundary is the `ra_lsp_server` crate, which defines an LSP
+interface in terms of stdio. We do integration testing of this component, by
+feeding it with a stream of LSP requests and checking responses. These tests are
+known as "heavy", because they interact with Cargo and read real files from
+disk. For this reason, we try to avoid writing too many tests on this boundary:
+in a statically typed language, it's hard to make an error in the protocol
+itself if messages are themselves typed.
-VS Code plugin
+The middle, and most important, boundary is `ra_ide_api`. Unlike
+`ra_lsp_server`, which exposes API, `ide_api` uses Rust API and is intended to
+use by various tools. Typical test creates an `AnalysisHost`, calls some
+`Analysis` functions and compares the results against expectation.
+The innermost and most elaborate boundary is `hir`. It has a much richer
+vocabulary of types than `ide_api`, but the basic testing setup is the same: we
+create a database, run some queries, assert result.
-## Common workflows
+For comparisons, we use [insta](https://github.com/mitsuhiko/insta/) library for
+snapshot testing.
-To try out VS Code extensions, run `cargo install-code`. This installs both the
-`ra_lsp_server` binary and the VS Code extension. To install only the binary, use
-`cargo install-lsp` (shorthand for `cargo install --path crates/ra_lsp_server --force`)
-
-To see logs from the language server, set `RUST_LOG=info` env variable. To see
-all communication between the server and the client, use
-`RUST_LOG=gen_lsp_server=debug` (this will print quite a bit of stuff).
-
-There's `rust-analyzer: status` command which prints common high-level debug
-info. In particular, it prints info about memory usage of various data
-structures, and, if compiled with jemalloc support (`cargo jinstall-lsp` or
-`cargo install --path crates/ra_lsp_server --force --features jemalloc`), includes
- statistic about the heap.
-
-To run tests, just `cargo test`.
-
-To work on the VS Code extension, launch code inside `editors/code` and use `F5` to
-launch/debug. To automatically apply formatter and linter suggestions, use `npm
-run fix`.
+To test various analysis corner cases and avoid forgetting about old tests, we
+use so-called marks. See the `marks` module in the `test_utils` crate for more.
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/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/docs/user/README.md b/docs/user/README.md
new file mode 100644
index 0000000000..439c4e6ae5
--- /dev/null
+++ b/docs/user/README.md
@@ -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 Ctrl+Shift+P 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
diff --git a/docs/user/features.md b/docs/user/features.md
new file mode 100644
index 0000000000..b9d2aa84f8
--- /dev/null
+++ b/docs/user/features.md
@@ -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 Ctrl+Shift+P to search for the corresponding action.
+
+### Workspace Symbol ctrl+t
+
+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 ctrl+shift+o
+
+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 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. `<|>` 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(){}`
+
diff --git a/editors/README.md b/editors/README.md
deleted file mode 100644
index ddc6ee0485..0000000000
--- a/editors/README.md
+++ /dev/null
@@ -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 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}};
-```
-
-## 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.