aboutsummaryrefslogtreecommitdiff
path: root/docs/dev/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/dev/README.md')
-rw-r--r--docs/dev/README.md117
1 files changed, 24 insertions, 93 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md
index dd2bfc493..b91013f13 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -9,8 +9,9 @@ $ cargo test
9 9
10should be enough to get you started! 10should be enough to get you started!
11 11
12To learn more about how rust-analyzer works, see 12To learn more about how rust-analyzer works, see [./architecture.md](./architecture.md) document.
13[./architecture.md](./architecture.md) document. 13It also explains the high-level layout of the source code.
14Do skim through that document.
14 15
15We also publish rustdoc docs to pages: 16We also publish rustdoc docs to pages:
16 17
@@ -43,6 +44,10 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0
43 while unactionable ones are effectively wont-fix. Each triaged issue should have one of these labels. 44 while unactionable ones are effectively wont-fix. Each triaged issue should have one of these labels.
44* [fun](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3Afun) 45* [fun](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3Afun)
45 is for cool, but probably hard stuff. 46 is for cool, but probably hard stuff.
47* [Design](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%Design)
48 is for moderate/large scale architecture discussion.
49 Also a kind of fun.
50 These issues should generally include a link to a Zulip discussion thread.
46 51
47# CI 52# CI
48 53
@@ -53,8 +58,6 @@ Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite.
53 58
54We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule. 59We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule.
55 60
56You can run `cargo xtask install-pre-commit-hook` to install git-hook to run rustfmt on commit.
57
58# Launching rust-analyzer 61# Launching rust-analyzer
59 62
60Debugging the language server can be tricky. 63Debugging the language server can be tricky.
@@ -95,25 +98,6 @@ I don't have a specific workflow for this case.
95Additionally, I use `cargo run --release -p rust-analyzer -- analysis-stats path/to/some/rust/crate` to run a batch analysis. 98Additionally, I use `cargo run --release -p rust-analyzer -- analysis-stats path/to/some/rust/crate` to run a batch analysis.
96This is primarily useful for performance optimizations, or for bug minimization. 99This is primarily useful for performance optimizations, or for bug minimization.
97 100
98## Parser Tests
99
100Tests for the parser (`parser`) live in the `syntax` crate (see `test_data` directory).
101There are two kinds of tests:
102
103* Manually written test cases in `parser/ok` and `parser/err`
104* "Inline" tests in `parser/inline` (these are generated) from comments in `parser` crate.
105
106The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for.
107If you are tempted to add a large inline test, it might be a good idea to leave only the simplest example in place, and move the test to a manual `parser/ok` test.
108
109To update test data, run with `UPDATE_EXPECT` variable:
110
111```bash
112env UPDATE_EXPECT=1 cargo qt
113```
114
115After adding a new inline test you need to run `cargo xtest codegen` and also update the test data as described above.
116
117## TypeScript Tests 101## TypeScript Tests
118 102
119If you change files under `editors/code` and would like to run the tests and linter, install npm and run: 103If you change files under `editors/code` and would like to run the tests and linter, install npm and run:
@@ -124,77 +108,18 @@ npm ci
124npm run lint 108npm run lint
125``` 109```
126 110
127# Code organization
128
129All Rust code lives in the `crates` top-level directory, and is organized as a single Cargo workspace.
130The `editors` top-level directory contains code for integrating with editors.
131Currently, it contains the plugin for VS Code (in TypeScript).
132The `docs` top-level directory contains both developer and user documentation.
133
134We have some automation infra in Rust in the `xtask` package.
135It contains stuff like formatting checking, code generation and powers `cargo xtask install`.
136The latter syntax is achieved with the help of cargo aliases (see `.cargo` directory).
137
138# Architecture Invariants
139
140This section tries to document high-level design constraints, which are not
141always obvious from the low-level code.
142
143## Incomplete syntax trees
144
145Syntax trees are by design incomplete and do not enforce well-formedness.
146If an AST method returns an `Option`, it *can* be `None` at runtime, even if this is forbidden by the grammar.
147
148## LSP independence
149
150rust-analyzer is independent from LSP.
151It provides features for a hypothetical perfect Rust-specific IDE client.
152Internal representations are lowered to LSP in the `rust-analyzer` crate (the only crate which is allowed to use LSP types).
153
154## IDE/Compiler split
155
156There's a semi-hard split between "compiler" and "IDE", at the `hir` crate.
157Compiler derives new facts about source code.
158It explicitly acknowledges that not all info is available (i.e. you can't look at types during name resolution).
159
160IDE assumes that all information is available at all times.
161
162IDE should use only types from `hir`, and should not depend on the underling compiler types.
163`hir` is a facade.
164
165## IDE API
166
167The main IDE crate (`ide`) uses "Plain Old Data" for the API.
168Rather than talking in definitions and references, it talks in Strings and textual offsets.
169In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath.
170The results are 100% Rust specific though.
171Shout outs to LSP developers for popularizing the idea that "UI" is a good place to draw a boundary at.
172
173## LSP is stateless
174
175The protocol is implemented in the mostly stateless way.
176A good mental model is HTTP, which doesn't store per-client state, and instead relies on devices like cookies to maintain an illusion of state.
177If some action requires multi-step protocol, each step should be self-contained.
178
179A good example here is code action resolving process.
180TO display the lightbulb, we compute the list of code actions without computing edits.
181Figuring out the edit is done in a separate `codeAction/resolve` call.
182Rather than storing some `lazy_edit: Box<dyn FnOnce() -> Edit>` somewhere, we use a string ID of action to re-compute the list of actions during the resolve process.
183(See [this post](https://rust-analyzer.github.io/blog/2020/09/28/how-to-make-a-light-bulb.html) for more details.)
184The benefit here is that, generally speaking, the state of the world might change between `codeAction` and `codeAction` resolve requests, so any closure we store might become invalid.
185
186While we don't currently implement any complicated refactors with complex GUI, I imagine we'd use the same techniques for refactors.
187After clicking each "Next" button during refactor, the client would send all the info which server needs to re-recreate the context from scratch.
188
189## CI
190
191CI does not test rust-analyzer, CI is a core part of rust-analyzer, and is maintained with above average standard of quality.
192CI is reproducible -- it can only be broken by changes to files in this repository, any dependence on externalities is a bug.
193
194# Code Style & Review Process 111# Code Style & Review Process
195 112
196Do see [./style.md](./style.md). 113Do see [./style.md](./style.md).
197 114
115# How to ...
116
117* ... add an assist? [#7535](https://github.com/rust-analyzer/rust-analyzer/pull/7535)
118* ... add a new protocol extension? [#4569](https://github.com/rust-analyzer/rust-analyzer/pull/4569)
119* ... add a new configuration option? [#7451](https://github.com/rust-analyzer/rust-analyzer/pull/7451)
120* ... add a new completion? [#6964](https://github.com/rust-analyzer/rust-analyzer/pull/6964)
121* ... allow new syntax in the parser? [#7338](https://github.com/rust-analyzer/rust-analyzer/pull/7338)
122
198# Logging 123# Logging
199 124
200Logging is done by both rust-analyzer and VS Code, so it might be tricky to 125Logging is done by both rust-analyzer and VS Code, so it might be tricky to
@@ -212,7 +137,7 @@ To log all communication between the server and the client, there are two choice
212 137
213* you can log on the server side, by running something like 138* you can log on the server side, by running something like
214 ``` 139 ```
215 env RA_LOG=gen_lsp_server=trace code . 140 env RA_LOG=lsp_server=debug code .
216 ``` 141 ```
217 142
218* you can log on the client side, by enabling `"rust-analyzer.trace.server": 143* you can log on the client side, by enabling `"rust-analyzer.trace.server":
@@ -251,6 +176,9 @@ RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more tha
251 176
252In particular, I have `export RA_PROFILE='*>10'` in my shell profile. 177In particular, I have `export RA_PROFILE='*>10'` in my shell profile.
253 178
179We also have a "counting" profiler which counts number of instances of popular structs.
180It is enabled by `RA_COUNT=1`.
181
254To measure time for from-scratch analysis, use something like this: 182To measure time for from-scratch analysis, use something like this:
255 183
256``` 184```
@@ -288,13 +216,16 @@ Release steps:
288 * makes a GitHub release 216 * makes a GitHub release
289 * pushes VS Code extension to the marketplace 217 * pushes VS Code extension to the marketplace
290 * create new changelog in `rust-analyzer.github.io` 218 * create new changelog in `rust-analyzer.github.io`
291 * create `rust-analyzer.github.io/git.log` file with the log of merge commits since last release 2192. While the release is in progress, fill in the changelog
2922. While the release is in progress, fill-in the changelog using `git.log`
2933. Commit & push the changelog 2203. Commit & push the changelog
2944. Tweet 2214. Tweet
2955. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's submodule. 2225. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's submodule.
296 Self-approve the PR. 223 Self-approve the PR.
297 224
225If the GitHub Actions release fails because of a transient problem like a timeout, you can re-run the job from the Actions console.
226If it fails because of something that needs to be fixed, remove the release tag (if needed), fix the problem, then start over.
227Make sure to remove the new changelog post created when running `cargo xtask release` a second time.
228
298# Permissions 229# Permissions
299 230
300There are three sets of people with extra permissions: 231There are three sets of people with extra permissions: