diff options
80 files changed, 1225 insertions, 1369 deletions
diff --git a/.travis.yml b/.travis.yml index acf1af028..8d420f618 100644 --- a/.travis.yml +++ b/.travis.yml | |||
@@ -1,7 +1,9 @@ | |||
1 | cache: cargo | ||
2 | |||
1 | matrix: | 3 | matrix: |
2 | include: | 4 | include: |
3 | - language: rust | 5 | - language: rust |
4 | rust: stable | 6 | rust: beta |
5 | script: | 7 | script: |
6 | - cargo gen-kinds --verify | 8 | - cargo gen-kinds --verify |
7 | - cargo gen-tests --verify | 9 | - cargo gen-tests --verify |
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 000000000..b497cc5d7 --- /dev/null +++ b/ARCHITECTURE.md | |||
@@ -0,0 +1,133 @@ | |||
1 | # Architecture | ||
2 | |||
3 | This document describes high-level architecture of rust-analyzer. | ||
4 | If you want to familiarize yourself with the code base, you are just | ||
5 | in the right place! | ||
6 | |||
7 | |||
8 | ## Code generation | ||
9 | |||
10 | Some of the components of this repository are generated through automatic | ||
11 | processes. These are outlined below: | ||
12 | |||
13 | - `gen-kinds`: The kinds of tokens are reused in several places, so a generator | ||
14 | is used. We use tera templates to generate the files listed below, based on | ||
15 | the grammar described in [grammar.ron]: | ||
16 | - [ast/generated.rs][ast generated] in `ra_syntax` based on | ||
17 | [ast/generated.tera.rs][ast source] | ||
18 | - [syntax_kinds/generated.rs][syntax_kinds generated] in `ra_syntax` based on | ||
19 | [syntax_kinds/generated.tera.rs][syntax_kinds source] | ||
20 | |||
21 | [tera]: https://tera.netlify.com/ | ||
22 | [grammar.ron]: ./crates/ra_syntax/src/grammar.ron | ||
23 | [ast generated]: ./crates/ra_syntax/src/ast/generated.rs | ||
24 | [ast source]: ./crates/ra_syntax/src/ast/generated.rs.tera | ||
25 | [syntax_kinds generated]: ./crates/ra_syntax/src/syntax_kinds/generated.rs | ||
26 | [syntax_kinds source]: ./crates/ra_syntax/src/syntax_kinds/generated.rs.tera | ||
27 | |||
28 | |||
29 | ## Code Walk-Through | ||
30 | |||
31 | ### `crates/ra_syntax` | ||
32 | |||
33 | Rust syntax tree structure and parser. See | ||
34 | [RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design | ||
35 | notes. | ||
36 | |||
37 | - [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees. | ||
38 | - `grammar` module is the actual parser. It is a hand-written recursive descent parsers, which | ||
39 | produces a sequence of events like "start node X", "finish not Y". It works similarly to [kotlin parser](https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java), | ||
40 | which is a good source for inspiration for dealing with syntax errors and incomplete input. Original [libsyntax parser](https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs) | ||
41 | is what we use for the definition of the Rust language. | ||
42 | - `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `rowan` trees. | ||
43 | This is the thing that turns a flat list of events into a tree (see `EventProcessor`) | ||
44 | - `ast` a type safe API on top of the raw `rowan` tree. | ||
45 | - `grammar.ron` RON description of the grammar, which is used to | ||
46 | generate `syntax_kinds` and `ast` modules, using `cargo gen-kinds` command. | ||
47 | - `algo`: generic tree algorithms, including `walk` for O(1) stack | ||
48 | space tree traversal (this is cool) and `visit` for type-driven | ||
49 | visiting the nodes (this is double plus cool, if you understand how | ||
50 | `Visitor` works, you understand rust-analyzer). | ||
51 | |||
52 | Test for ra_syntax are mostly data-driven: `tests/data/parser` contains a bunch of `.rs` | ||
53 | (test vectors) and `.txt` files with corresponding syntax trees. During testing, we check | ||
54 | `.rs` against `.txt`. If the `.txt` file is missing, it is created (this is how you update | ||
55 | tests). Additionally, running `cargo gen-tests` will walk the grammar module and collect | ||
56 | all `//test test_name` comments into files inside `tests/data` directory. | ||
57 | |||
58 | See [#93](https://github.com/rust-analyzer/rust-analyzer/pull/93) for an example PR which | ||
59 | fixes a bug in the grammar. | ||
60 | |||
61 | |||
62 | ### `crates/ra_editor` | ||
63 | |||
64 | All IDE features which can be implemented if you only have access to a | ||
65 | single file. `ra_editor` could be used to enhance editing of Rust code | ||
66 | without the need to fiddle with build-systems, file | ||
67 | synchronization and such. | ||
68 | |||
69 | In a sense, `ra_editor` is just a bunch of pure functions which take a | ||
70 | syntax tree as an input. | ||
71 | |||
72 | The tests for `ra_editor` are `#[cfg(test)] mod tests` unit-tests spread | ||
73 | throughout its modules. | ||
74 | |||
75 | ### `crates/salsa` | ||
76 | |||
77 | An implementation of red-green incremental compilation algorithm from | ||
78 | rust compiler. It makes all rust-analyzer features on-demand. To be replaced | ||
79 | with `salsa-rs/salsa` soon. | ||
80 | |||
81 | |||
82 | ### `crates/ra_analysis` | ||
83 | |||
84 | A stateful library for analyzing many Rust files as they change. | ||
85 | `AnalysisHost` is a mutable entity (clojure's atom) which holds | ||
86 | current state, incorporates changes and handles out `Analysis` --- an | ||
87 | immutable consistent snapshot of world state at a point in time, which | ||
88 | actually powers analysis. | ||
89 | |||
90 | |||
91 | ### `crates/ra_lsp_server` | ||
92 | |||
93 | An LSP implementation which uses `ra_analysis` for managing state and | ||
94 | `ra_editor` for actually doing useful stuff. | ||
95 | |||
96 | See [#79](https://github.com/rust-analyzer/rust-analyzer/pull/79/) as an | ||
97 | example of PR which adds a new feature to `ra_editor` and exposes it | ||
98 | to `ra_lsp_server`. | ||
99 | |||
100 | |||
101 | ### `crates/cli` | ||
102 | |||
103 | A CLI interface to rust-analyzer. | ||
104 | |||
105 | ### `crate/tools` | ||
106 | |||
107 | Custom Cargo tasks used to develop rust-analyzer: | ||
108 | |||
109 | - `cargo gen-kinds` -- generate `ast` and `syntax_kinds` | ||
110 | - `cargo gen-tests` -- collect inline tests from grammar | ||
111 | - `cargo install-code` -- build and install VS Code extension and server | ||
112 | |||
113 | ### `editors/code` | ||
114 | |||
115 | VS Code plugin | ||
116 | |||
117 | |||
118 | ## Common workflows | ||
119 | |||
120 | To try out VS Code extensions, run `cargo install-code`. This installs both the | ||
121 | `ra_lsp_server` binary and VS Code extension. To install only the binary, `use | ||
122 | cargo install --path crates/ra_lsp_server --force` | ||
123 | |||
124 | To see logs from the language server, set `RUST_LOG=info` env variable. To see | ||
125 | all communication between the server and the client, use | ||
126 | `RUST_LOG=gen_lsp_server=debug` (will print quite a bit of stuff). | ||
127 | |||
128 | To run tests, just `cargo test`. | ||
129 | |||
130 | To work on VS Code extension, launch code inside `editors/code` and use `F5` to | ||
131 | launch/debug. To automatically apply formatter and linter suggestions, use `npm | ||
132 | run fix`. | ||
133 | |||
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c952078cf..a2efc7afa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md | |||
@@ -1,58 +1,18 @@ | |||
1 | The project is in its early stages: contributions are welcome and would be | 1 | The project is in its early stages: contributions are welcome and would be |
2 | **very** helpful, but the project is not _yet_ optimized for contribution. | 2 | **very** helpful, but the project is not _yet_ optimized for contribution. |
3 | Moreover, it is doubly experimental, so there's no guarantee that any work here | 3 | Moreover, it is doubly experimental, so there's no guarantee that any work here |
4 | would reach production. That said, here are some areas where contributions would | 4 | would reach production. |
5 | be **especially** welcome: | ||
6 | 5 | ||
7 | - Designing internal data structures: RFC only outlines the constraints, it's an | 6 | To get an idea of how rust-analyzer works, take a look at the [ARCHITECTURE.md](./ARCHITECTURE.md) |
8 | open question how to satisfy them in the optimal way. See `ARCHITECTURE.md` | 7 | document. |
9 | for current design questions. | ||
10 | 8 | ||
11 | - Porting libsyntax parser to rust-analyzer: currently rust-analyzer parses only | 9 | Useful labels on the issue tracker: |
12 | a tiny subset of Rust. This should be fixed by porting parsing functions from | 10 | * [E-mentor](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-mentor) |
13 | libsyntax one by one. Take a look at the [libsyntax parser] for "what to port" | 11 | issues have links to the code in question and tests, |
14 | and at the [Kotlin parser] for "how to port". | 12 | * [E-easy](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy), |
13 | [E-medium](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-medium), | ||
14 | [E-hard](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-hard), | ||
15 | labels are *estimates* for how hard would be to write a fix. | ||
15 | 16 | ||
16 | - Writing validators: by design, rust-analyzer is very lax about the input. For | 17 | There's no formal PR check list: everything that passes CI (we use [bors](https://bors.tech/)) is valid, |
17 | example, the lexer happily accepts unclosed strings. The idea is that there | 18 | but it's a good idea to write nice commit messages, test code thoroughly, maintain consistent style, etc. |
18 | should be a higher level visitor, which walks the syntax tree after parsing | ||
19 | and produces all the warnings. Alas, there's no such visitor yet :( Would you | ||
20 | like to write one? :) | ||
21 | |||
22 | - Creating tests: it would be tremendously helpful to read each of libsyntax and | ||
23 | rust-analyzer parser functions and crate a small separate test cases to cover | ||
24 | each and every edge case. | ||
25 | |||
26 | - Building stuff with rust-analyzer: it would be really cool to compile | ||
27 | rust-analyzer to WASM and add _client side_ syntax validation to rust | ||
28 | playground! | ||
29 | |||
30 | Do take a look at the issue tracker. | ||
31 | |||
32 | If you don't know where to start, or have _any_ questions or suggestions, don't | ||
33 | hesitate to chat at [Gitter]! | ||
34 | |||
35 | # Code generation | ||
36 | |||
37 | Some of the components of this repository are generated through automatic | ||
38 | processes. These are outlined below: | ||
39 | |||
40 | - `gen-kinds`: The kinds of tokens are reused in several places, so a generator | ||
41 | is used. This process uses [tera] to generate, using data in [grammar.ron], | ||
42 | the files: | ||
43 | - [ast/generated.rs][ast generated] in `ra_syntax` based on | ||
44 | [ast/generated.tera.rs][ast source] | ||
45 | - [syntax_kinds/generated.rs][syntax_kinds generated] in `ra_syntax` based on | ||
46 | [syntax_kinds/generated.tera.rs][syntax_kinds source] | ||
47 | |||
48 | [libsyntax parser]: | ||
49 | https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs | ||
50 | [kotlin parser]: | ||
51 | https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java | ||
52 | [gitter]: https://gitter.im/libsyntax2/Lobby | ||
53 | [tera]: https://tera.netlify.com/ | ||
54 | [grammar.ron]: ./crates/ra_syntax/src/grammar.ron | ||
55 | [ast generated]: ./crates/ra_syntax/src/ast/generated.rs | ||
56 | [ast source]: ./crates/ra_syntax/src/ast/generated.tera.rs | ||
57 | [syntax_kinds generated]: ./crates/ra_syntax/src/syntax_kinds/generated.rs | ||
58 | [syntax_kinds source]: ./crates/ra_syntax/src/syntax_kinds/generated.tera.rs | ||
diff --git a/Cargo.lock b/Cargo.lock index 62feeb539..707257a31 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -15,6 +15,11 @@ dependencies = [ | |||
15 | ] | 15 | ] |
16 | 16 | ||
17 | [[package]] | 17 | [[package]] |
18 | name = "arrayref" | ||
19 | version = "0.3.5" | ||
20 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
21 | |||
22 | [[package]] | ||
18 | name = "arrayvec" | 23 | name = "arrayvec" |
19 | version = "0.4.7" | 24 | version = "0.4.7" |
20 | source = "registry+https://github.com/rust-lang/crates.io-index" | 25 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -68,6 +73,20 @@ version = "1.0.4" | |||
68 | source = "registry+https://github.com/rust-lang/crates.io-index" | 73 | source = "registry+https://github.com/rust-lang/crates.io-index" |
69 | 74 | ||
70 | [[package]] | 75 | [[package]] |
76 | name = "block-buffer" | ||
77 | version = "0.3.3" | ||
78 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
79 | dependencies = [ | ||
80 | "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||
81 | "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
82 | ] | ||
83 | |||
84 | [[package]] | ||
85 | name = "byte-tools" | ||
86 | version = "0.2.0" | ||
87 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
88 | |||
89 | [[package]] | ||
71 | name = "byteorder" | 90 | name = "byteorder" |
72 | version = "1.2.6" | 91 | version = "1.2.6" |
73 | source = "registry+https://github.com/rust-lang/crates.io-index" | 92 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -79,9 +98,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
79 | dependencies = [ | 98 | dependencies = [ |
80 | "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", | 99 | "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", |
81 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", | 100 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", |
82 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 101 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
83 | "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 102 | "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
84 | "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", | 103 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", |
85 | ] | 104 | ] |
86 | 105 | ||
87 | [[package]] | 106 | [[package]] |
@@ -188,6 +207,16 @@ version = "0.5.0" | |||
188 | source = "registry+https://github.com/rust-lang/crates.io-index" | 207 | source = "registry+https://github.com/rust-lang/crates.io-index" |
189 | 208 | ||
190 | [[package]] | 209 | [[package]] |
210 | name = "derive-new" | ||
211 | version = "0.5.5" | ||
212 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
213 | dependencies = [ | ||
214 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", | ||
215 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||
216 | "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||
217 | ] | ||
218 | |||
219 | [[package]] | ||
191 | name = "deunicode" | 220 | name = "deunicode" |
192 | version = "0.4.3" | 221 | version = "0.4.3" |
193 | source = "registry+https://github.com/rust-lang/crates.io-index" | 222 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -198,6 +227,14 @@ version = "2.0.0" | |||
198 | source = "registry+https://github.com/rust-lang/crates.io-index" | 227 | source = "registry+https://github.com/rust-lang/crates.io-index" |
199 | 228 | ||
200 | [[package]] | 229 | [[package]] |
230 | name = "digest" | ||
231 | version = "0.7.6" | ||
232 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
233 | dependencies = [ | ||
234 | "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
235 | ] | ||
236 | |||
237 | [[package]] | ||
201 | name = "drop_bomb" | 238 | name = "drop_bomb" |
202 | version = "0.1.4" | 239 | version = "0.1.4" |
203 | source = "registry+https://github.com/rust-lang/crates.io-index" | 240 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -229,13 +266,18 @@ name = "failure_derive" | |||
229 | version = "0.1.2" | 266 | version = "0.1.2" |
230 | source = "registry+https://github.com/rust-lang/crates.io-index" | 267 | source = "registry+https://github.com/rust-lang/crates.io-index" |
231 | dependencies = [ | 268 | dependencies = [ |
232 | "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | 269 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", |
233 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | 270 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", |
234 | "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", | 271 | "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", |
235 | "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", | 272 | "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", |
236 | ] | 273 | ] |
237 | 274 | ||
238 | [[package]] | 275 | [[package]] |
276 | name = "fake-simd" | ||
277 | version = "0.1.2" | ||
278 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
279 | |||
280 | [[package]] | ||
239 | name = "flexi_logger" | 281 | name = "flexi_logger" |
240 | version = "0.9.2" | 282 | version = "0.9.2" |
241 | source = "registry+https://github.com/rust-lang/crates.io-index" | 283 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -277,9 +319,17 @@ dependencies = [ | |||
277 | "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | 319 | "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", |
278 | "languageserver-types 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)", | 320 | "languageserver-types 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)", |
279 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", | 321 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", |
280 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 322 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
281 | "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 323 | "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
282 | "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", | 324 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", |
325 | ] | ||
326 | |||
327 | [[package]] | ||
328 | name = "generic-array" | ||
329 | version = "0.9.0" | ||
330 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
331 | dependencies = [ | ||
332 | "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
283 | ] | 333 | ] |
284 | 334 | ||
285 | [[package]] | 335 | [[package]] |
@@ -312,7 +362,7 @@ dependencies = [ | |||
312 | 362 | ||
313 | [[package]] | 363 | [[package]] |
314 | name = "im" | 364 | name = "im" |
315 | version = "12.1.0" | 365 | version = "12.2.0" |
316 | source = "registry+https://github.com/rust-lang/crates.io-index" | 366 | source = "registry+https://github.com/rust-lang/crates.io-index" |
317 | dependencies = [ | 367 | dependencies = [ |
318 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | 368 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -320,6 +370,11 @@ dependencies = [ | |||
320 | ] | 370 | ] |
321 | 371 | ||
322 | [[package]] | 372 | [[package]] |
373 | name = "indexmap" | ||
374 | version = "1.0.1" | ||
375 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
376 | |||
377 | [[package]] | ||
323 | name = "itertools" | 378 | name = "itertools" |
324 | version = "0.7.8" | 379 | version = "0.7.8" |
325 | source = "registry+https://github.com/rust-lang/crates.io-index" | 380 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -343,11 +398,11 @@ version = "0.51.0" | |||
343 | source = "registry+https://github.com/rust-lang/crates.io-index" | 398 | source = "registry+https://github.com/rust-lang/crates.io-index" |
344 | dependencies = [ | 399 | dependencies = [ |
345 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", | 400 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", |
346 | "num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", | 401 | "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", |
347 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | 402 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", |
348 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 403 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
349 | "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 404 | "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
350 | "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", | 405 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", |
351 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | 406 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", |
352 | "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | 407 | "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
353 | ] | 408 | ] |
@@ -383,6 +438,11 @@ dependencies = [ | |||
383 | ] | 438 | ] |
384 | 439 | ||
385 | [[package]] | 440 | [[package]] |
441 | name = "maplit" | ||
442 | version = "1.0.1" | ||
443 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
444 | |||
445 | [[package]] | ||
386 | name = "matches" | 446 | name = "matches" |
387 | version = "0.1.8" | 447 | version = "0.1.8" |
388 | source = "registry+https://github.com/rust-lang/crates.io-index" | 448 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -418,13 +478,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
418 | 478 | ||
419 | [[package]] | 479 | [[package]] |
420 | name = "num-derive" | 480 | name = "num-derive" |
421 | version = "0.2.2" | 481 | version = "0.2.3" |
422 | source = "registry+https://github.com/rust-lang/crates.io-index" | 482 | source = "registry+https://github.com/rust-lang/crates.io-index" |
423 | dependencies = [ | 483 | dependencies = [ |
424 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | 484 | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", |
425 | "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | 485 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", |
426 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | 486 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", |
427 | "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", | 487 | "syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)", |
428 | ] | 488 | ] |
429 | 489 | ||
430 | [[package]] | 490 | [[package]] |
@@ -492,38 +552,57 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
492 | 552 | ||
493 | [[package]] | 553 | [[package]] |
494 | name = "pest" | 554 | name = "pest" |
495 | version = "1.0.6" | 555 | version = "2.0.1" |
496 | source = "registry+https://github.com/rust-lang/crates.io-index" | 556 | source = "registry+https://github.com/rust-lang/crates.io-index" |
557 | dependencies = [ | ||
558 | "ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||
559 | ] | ||
497 | 560 | ||
498 | [[package]] | 561 | [[package]] |
499 | name = "pest_derive" | 562 | name = "pest_derive" |
500 | version = "1.0.8" | 563 | version = "2.0.1" |
501 | source = "registry+https://github.com/rust-lang/crates.io-index" | 564 | source = "registry+https://github.com/rust-lang/crates.io-index" |
502 | dependencies = [ | 565 | dependencies = [ |
503 | "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", | 566 | "pest 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
504 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", | 567 | "pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", |
505 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||
506 | ] | 568 | ] |
507 | 569 | ||
508 | [[package]] | 570 | [[package]] |
509 | name = "proc-macro2" | 571 | name = "pest_generator" |
510 | version = "0.4.19" | 572 | version = "2.0.0" |
511 | source = "registry+https://github.com/rust-lang/crates.io-index" | 573 | source = "registry+https://github.com/rust-lang/crates.io-index" |
512 | dependencies = [ | 574 | dependencies = [ |
513 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 575 | "pest 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
576 | "pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||
577 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", | ||
578 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||
579 | "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||
514 | ] | 580 | ] |
515 | 581 | ||
516 | [[package]] | 582 | [[package]] |
517 | name = "quote" | 583 | name = "pest_meta" |
518 | version = "0.3.15" | 584 | version = "2.0.3" |
585 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
586 | dependencies = [ | ||
587 | "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||
588 | "pest 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||
589 | "sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
590 | ] | ||
591 | |||
592 | [[package]] | ||
593 | name = "proc-macro2" | ||
594 | version = "0.4.20" | ||
519 | source = "registry+https://github.com/rust-lang/crates.io-index" | 595 | source = "registry+https://github.com/rust-lang/crates.io-index" |
596 | dependencies = [ | ||
597 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
598 | ] | ||
520 | 599 | ||
521 | [[package]] | 600 | [[package]] |
522 | name = "quote" | 601 | name = "quote" |
523 | version = "0.6.8" | 602 | version = "0.6.8" |
524 | source = "registry+https://github.com/rust-lang/crates.io-index" | 603 | source = "registry+https://github.com/rust-lang/crates.io-index" |
525 | dependencies = [ | 604 | dependencies = [ |
526 | "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | 605 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", |
527 | ] | 606 | ] |
528 | 607 | ||
529 | [[package]] | 608 | [[package]] |
@@ -532,7 +611,7 @@ version = "0.1.0" | |||
532 | dependencies = [ | 611 | dependencies = [ |
533 | "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | 612 | "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", |
534 | "fst 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", | 613 | "fst 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", |
535 | "im 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 614 | "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
536 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", | 615 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", |
537 | "once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | 616 | "once_cell 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", |
538 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", | 617 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -541,7 +620,7 @@ dependencies = [ | |||
541 | "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | 620 | "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", |
542 | "relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | 621 | "relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", |
543 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 622 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
544 | "salsa 0.1.0", | 623 | "salsa 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", |
545 | "test_utils 0.1.0", | 624 | "test_utils 0.1.0", |
546 | ] | 625 | ] |
547 | 626 | ||
@@ -579,7 +658,7 @@ dependencies = [ | |||
579 | "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | 658 | "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", |
580 | "flexi_logger 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", | 659 | "flexi_logger 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", |
581 | "gen_lsp_server 0.1.0", | 660 | "gen_lsp_server 0.1.0", |
582 | "im 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 661 | "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
583 | "languageserver-types 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)", | 662 | "languageserver-types 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)", |
584 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", | 663 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", |
585 | "ra_analysis 0.1.0", | 664 | "ra_analysis 0.1.0", |
@@ -588,10 +667,10 @@ dependencies = [ | |||
588 | "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | 667 | "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", |
589 | "relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | 668 | "relative-path 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", |
590 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 669 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
591 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 670 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
592 | "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 671 | "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
593 | "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", | 672 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", |
594 | "smol_str 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | 673 | "smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", |
595 | "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | 674 | "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", |
596 | "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | 675 | "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", |
597 | "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | 676 | "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -629,13 +708,21 @@ dependencies = [ | |||
629 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | 708 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", |
630 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", | 709 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", |
631 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", | 710 | "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", |
632 | "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | 711 | "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", |
633 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | 712 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", |
634 | ] | 713 | ] |
635 | 714 | ||
636 | [[package]] | 715 | [[package]] |
637 | name = "rand_core" | 716 | name = "rand_core" |
638 | version = "0.2.1" | 717 | version = "0.2.2" |
718 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
719 | dependencies = [ | ||
720 | "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
721 | ] | ||
722 | |||
723 | [[package]] | ||
724 | name = "rand_core" | ||
725 | version = "0.3.0" | ||
639 | source = "registry+https://github.com/rust-lang/crates.io-index" | 726 | source = "registry+https://github.com/rust-lang/crates.io-index" |
640 | 727 | ||
641 | [[package]] | 728 | [[package]] |
@@ -712,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
712 | dependencies = [ | 799 | dependencies = [ |
713 | "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", | 800 | "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", |
714 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", | 801 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", |
715 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 802 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
716 | ] | 803 | ] |
717 | 804 | ||
718 | [[package]] | 805 | [[package]] |
@@ -721,7 +808,7 @@ version = "0.1.0" | |||
721 | source = "registry+https://github.com/rust-lang/crates.io-index" | 808 | source = "registry+https://github.com/rust-lang/crates.io-index" |
722 | dependencies = [ | 809 | dependencies = [ |
723 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", | 810 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", |
724 | "smol_str 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", | 811 | "smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", |
725 | "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | 812 | "text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", |
726 | ] | 813 | ] |
727 | 814 | ||
@@ -758,10 +845,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
758 | 845 | ||
759 | [[package]] | 846 | [[package]] |
760 | name = "salsa" | 847 | name = "salsa" |
761 | version = "0.1.0" | 848 | version = "0.5.0" |
849 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
762 | dependencies = [ | 850 | dependencies = [ |
763 | "im 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 851 | "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", |
852 | "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||
853 | "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||
764 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", | 854 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", |
855 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||
856 | "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||
765 | ] | 857 | ] |
766 | 858 | ||
767 | [[package]] | 859 | [[package]] |
@@ -783,7 +875,7 @@ version = "0.9.0" | |||
783 | source = "registry+https://github.com/rust-lang/crates.io-index" | 875 | source = "registry+https://github.com/rust-lang/crates.io-index" |
784 | dependencies = [ | 876 | dependencies = [ |
785 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | 877 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", |
786 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 878 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
787 | ] | 879 | ] |
788 | 880 | ||
789 | [[package]] | 881 | [[package]] |
@@ -793,30 +885,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
793 | 885 | ||
794 | [[package]] | 886 | [[package]] |
795 | name = "serde" | 887 | name = "serde" |
796 | version = "1.0.79" | 888 | version = "1.0.80" |
797 | source = "registry+https://github.com/rust-lang/crates.io-index" | 889 | source = "registry+https://github.com/rust-lang/crates.io-index" |
798 | dependencies = [ | 890 | dependencies = [ |
799 | "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 891 | "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
800 | ] | 892 | ] |
801 | 893 | ||
802 | [[package]] | 894 | [[package]] |
803 | name = "serde_derive" | 895 | name = "serde_derive" |
804 | version = "1.0.79" | 896 | version = "1.0.80" |
805 | source = "registry+https://github.com/rust-lang/crates.io-index" | 897 | source = "registry+https://github.com/rust-lang/crates.io-index" |
806 | dependencies = [ | 898 | dependencies = [ |
807 | "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | 899 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", |
808 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | 900 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", |
809 | "syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", | 901 | "syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)", |
810 | ] | 902 | ] |
811 | 903 | ||
812 | [[package]] | 904 | [[package]] |
813 | name = "serde_json" | 905 | name = "serde_json" |
814 | version = "1.0.31" | 906 | version = "1.0.32" |
815 | source = "registry+https://github.com/rust-lang/crates.io-index" | 907 | source = "registry+https://github.com/rust-lang/crates.io-index" |
816 | dependencies = [ | 908 | dependencies = [ |
817 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", | 909 | "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", |
818 | "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | 910 | "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", |
819 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 911 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
912 | ] | ||
913 | |||
914 | [[package]] | ||
915 | name = "sha-1" | ||
916 | version = "0.7.0" | ||
917 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
918 | dependencies = [ | ||
919 | "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||
920 | "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
921 | "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||
922 | "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||
820 | ] | 923 | ] |
821 | 924 | ||
822 | [[package]] | 925 | [[package]] |
@@ -837,10 +940,10 @@ dependencies = [ | |||
837 | 940 | ||
838 | [[package]] | 941 | [[package]] |
839 | name = "smol_str" | 942 | name = "smol_str" |
840 | version = "0.1.6" | 943 | version = "0.1.7" |
841 | source = "registry+https://github.com/rust-lang/crates.io-index" | 944 | source = "registry+https://github.com/rust-lang/crates.io-index" |
842 | dependencies = [ | 945 | dependencies = [ |
843 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 946 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
844 | ] | 947 | ] |
845 | 948 | ||
846 | [[package]] | 949 | [[package]] |
@@ -860,48 +963,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
860 | 963 | ||
861 | [[package]] | 964 | [[package]] |
862 | name = "syn" | 965 | name = "syn" |
863 | version = "0.11.11" | ||
864 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
865 | dependencies = [ | ||
866 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", | ||
867 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||
868 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||
869 | ] | ||
870 | |||
871 | [[package]] | ||
872 | name = "syn" | ||
873 | version = "0.14.9" | 966 | version = "0.14.9" |
874 | source = "registry+https://github.com/rust-lang/crates.io-index" | 967 | source = "registry+https://github.com/rust-lang/crates.io-index" |
875 | dependencies = [ | 968 | dependencies = [ |
876 | "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | 969 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", |
877 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | 970 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", |
878 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 971 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
879 | ] | 972 | ] |
880 | 973 | ||
881 | [[package]] | 974 | [[package]] |
882 | name = "syn" | 975 | name = "syn" |
883 | version = "0.15.7" | 976 | version = "0.15.11" |
884 | source = "registry+https://github.com/rust-lang/crates.io-index" | 977 | source = "registry+https://github.com/rust-lang/crates.io-index" |
885 | dependencies = [ | 978 | dependencies = [ |
886 | "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | 979 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", |
887 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | 980 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", |
888 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 981 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
889 | ] | 982 | ] |
890 | 983 | ||
891 | [[package]] | 984 | [[package]] |
892 | name = "synom" | ||
893 | version = "0.11.3" | ||
894 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
895 | dependencies = [ | ||
896 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||
897 | ] | ||
898 | |||
899 | [[package]] | ||
900 | name = "synstructure" | 985 | name = "synstructure" |
901 | version = "0.9.0" | 986 | version = "0.9.0" |
902 | source = "registry+https://github.com/rust-lang/crates.io-index" | 987 | source = "registry+https://github.com/rust-lang/crates.io-index" |
903 | dependencies = [ | 988 | dependencies = [ |
904 | "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | 989 | "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", |
905 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", | 990 | "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", |
906 | "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", | 991 | "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", |
907 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 992 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -918,7 +1003,7 @@ dependencies = [ | |||
918 | 1003 | ||
919 | [[package]] | 1004 | [[package]] |
920 | name = "tera" | 1005 | name = "tera" |
921 | version = "0.11.16" | 1006 | version = "0.11.17" |
922 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" |
923 | dependencies = [ | 1008 | dependencies = [ |
924 | "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | 1009 | "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -926,11 +1011,11 @@ dependencies = [ | |||
926 | "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", | 1011 | "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", |
927 | "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1012 | "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
928 | "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1013 | "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
929 | "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", | 1014 | "pest 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
930 | "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", | 1015 | "pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
931 | "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | 1016 | "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", |
932 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 1017 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
933 | "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", | 1018 | "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", |
934 | "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | 1019 | "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", |
935 | "unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1020 | "unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", |
936 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1021 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -960,7 +1045,7 @@ name = "text_unit" | |||
960 | version = "0.1.4" | 1045 | version = "0.1.4" |
961 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" |
962 | dependencies = [ | 1047 | dependencies = [ |
963 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 1048 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
964 | ] | 1049 | ] |
965 | 1050 | ||
966 | [[package]] | 1051 | [[package]] |
@@ -998,7 +1083,7 @@ dependencies = [ | |||
998 | "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1083 | "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", |
999 | "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", | 1084 | "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", |
1000 | "ron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | 1085 | "ron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", |
1001 | "tera 0.11.16 (registry+https://github.com/rust-lang/crates.io-index)", | 1086 | "tera 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)", |
1002 | "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", | 1087 | "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", |
1003 | ] | 1088 | ] |
1004 | 1089 | ||
@@ -1008,6 +1093,11 @@ version = "1.10.0" | |||
1008 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1009 | 1094 | ||
1010 | [[package]] | 1095 | [[package]] |
1096 | name = "ucd-trie" | ||
1097 | version = "0.1.1" | ||
1098 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1099 | |||
1100 | [[package]] | ||
1011 | name = "ucd-util" | 1101 | name = "ucd-util" |
1012 | version = "0.1.1" | 1102 | version = "0.1.1" |
1013 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1081,11 +1171,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1081 | 1171 | ||
1082 | [[package]] | 1172 | [[package]] |
1083 | name = "unicode-xid" | 1173 | name = "unicode-xid" |
1084 | version = "0.0.4" | ||
1085 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1086 | |||
1087 | [[package]] | ||
1088 | name = "unicode-xid" | ||
1089 | version = "0.1.0" | 1174 | version = "0.1.0" |
1090 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1091 | 1176 | ||
@@ -1112,7 +1197,7 @@ name = "url_serde" | |||
1112 | version = "0.2.0" | 1197 | version = "0.2.0" |
1113 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1114 | dependencies = [ | 1199 | dependencies = [ |
1115 | "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | 1200 | "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", |
1116 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | 1201 | "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", |
1117 | ] | 1202 | ] |
1118 | 1203 | ||
@@ -1176,12 +1261,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1176 | [metadata] | 1261 | [metadata] |
1177 | "checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" | 1262 | "checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" |
1178 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" | 1263 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" |
1264 | "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" | ||
1179 | "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" | 1265 | "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" |
1180 | "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" | 1266 | "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" |
1181 | "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" | 1267 | "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" |
1182 | "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" | 1268 | "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" |
1183 | "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" | 1269 | "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" |
1184 | "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" | 1270 | "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" |
1271 | "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" | ||
1272 | "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" | ||
1185 | "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" | 1273 | "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" |
1186 | "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" | 1274 | "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" |
1187 | "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" | 1275 | "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" |
@@ -1195,22 +1283,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1195 | "checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416" | 1283 | "checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416" |
1196 | "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" | 1284 | "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" |
1197 | "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" | 1285 | "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" |
1286 | "checksum derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "899ec79626c14e00ccc9729b4d750bbe67fe76a8f436824c16e0233bbd9d7daa" | ||
1198 | "checksum deunicode 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" | 1287 | "checksum deunicode 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" |
1199 | "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" | 1288 | "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" |
1289 | "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" | ||
1200 | "checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" | 1290 | "checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" |
1201 | "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" | 1291 | "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" |
1202 | "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" | 1292 | "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" |
1203 | "checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" | 1293 | "checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" |
1204 | "checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" | 1294 | "checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" |
1295 | "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" | ||
1205 | "checksum flexi_logger 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2103a4bd3f67bf8b3e89fe0695cd13ac23c9968a2a81f2ccf2d95f1bb4e5a520" | 1296 | "checksum flexi_logger 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2103a4bd3f67bf8b3e89fe0695cd13ac23c9968a2a81f2ccf2d95f1bb4e5a520" |
1206 | "checksum fst 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9b0408ab57c1bf7c634b2ac6a165d14f642dc3335a43203090a7f8c78b54577b" | 1297 | "checksum fst 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9b0408ab57c1bf7c634b2ac6a165d14f642dc3335a43203090a7f8c78b54577b" |
1207 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" | 1298 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" |
1208 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" | 1299 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" |
1300 | "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" | ||
1209 | "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" | 1301 | "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" |
1210 | "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" | 1302 | "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" |
1211 | "checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" | 1303 | "checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" |
1212 | "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" | 1304 | "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" |
1213 | "checksum im 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90742b94a13db9b161eeab35f89bc9723634eb72bfd124f3ebb025734fdfef18" | 1305 | "checksum im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9c7f9bb8aee47fc16d535a705f7867a9fc83bb822e5e1043bb98e77ffeed3c" |
1306 | "checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" | ||
1214 | "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" | 1307 | "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" |
1215 | "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" | 1308 | "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" |
1216 | "checksum join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7bddc885f3fd69dd4b5d747c2efe6dd2c36d795ea9938281ed50910e32c95e31" | 1309 | "checksum join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7bddc885f3fd69dd4b5d747c2efe6dd2c36d795ea9938281ed50910e32c95e31" |
@@ -1219,12 +1312,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1219 | "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" | 1312 | "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" |
1220 | "checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" | 1313 | "checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" |
1221 | "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" | 1314 | "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" |
1315 | "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" | ||
1222 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" | 1316 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" |
1223 | "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" | 1317 | "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" |
1224 | "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" | 1318 | "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" |
1225 | "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" | 1319 | "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" |
1226 | "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" | 1320 | "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" |
1227 | "checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7" | 1321 | "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d" |
1228 | "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" | 1322 | "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" |
1229 | "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" | 1323 | "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" |
1230 | "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" | 1324 | "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" |
@@ -1233,14 +1327,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1233 | "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" | 1327 | "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" |
1234 | "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" | 1328 | "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" |
1235 | "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" | 1329 | "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" |
1236 | "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" | 1330 | "checksum pest 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c3abb0d36ede865dcc689fd3bee2ff39094eff6e57a814f4a53c3c6108088353" |
1237 | "checksum pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3294f437119209b084c797604295f40227cffa35c57220b1e99a6ff3bf8ee4" | 1331 | "checksum pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b76f477146419bc539a63f4ef40e902166cb43b3e51cecc71d9136fd12c567e7" |
1238 | "checksum proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe022fb8c8bd254524b0b3305906c1921fa37a84a644e29079a9e62200c3901" | 1332 | "checksum pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebee4e9680be4fd162e6f3394ae4192a6b60b1e4d17d845e631f0c68d1a3386" |
1239 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" | 1333 | "checksum pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f6d5f6f0e6082578c86af197d780dc38328e3f768cec06aac9bc46d714e8221" |
1334 | "checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" | ||
1240 | "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" | 1335 | "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" |
1241 | "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" | 1336 | "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" |
1242 | "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" | 1337 | "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" |
1243 | "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" | 1338 | "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" |
1339 | "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" | ||
1244 | "checksum rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df7a791f788cb4c516f0e091301a29c2b71ef680db5e644a7d68835c8ae6dbfa" | 1340 | "checksum rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df7a791f788cb4c516f0e091301a29c2b71ef680db5e644a7d68835c8ae6dbfa" |
1245 | "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" | 1341 | "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" |
1246 | "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" | 1342 | "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" |
@@ -1256,32 +1352,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1256 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" | 1352 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" |
1257 | "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" | 1353 | "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" |
1258 | "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" | 1354 | "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" |
1355 | "checksum salsa 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8301c563959d6d50fe0a34817f0d9ff08fe12eda7456e01e2bbde1588ea30602" | ||
1259 | "checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" | 1356 | "checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" |
1260 | "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" | 1357 | "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" |
1261 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" | 1358 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" |
1262 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | 1359 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" |
1263 | "checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" | 1360 | "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" |
1264 | "checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" | 1361 | "checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" |
1265 | "checksum serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "bb47a3d5c84320222f66d7db21157c4a7407755de41798f9b4c1c40593397b1a" | 1362 | "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" |
1363 | "checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" | ||
1266 | "checksum slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" | 1364 | "checksum slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" |
1267 | "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" | 1365 | "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" |
1268 | "checksum smol_str 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "248055d41f4c53f8ee7048e8a578a5190d0cca306630718091e4d481735e44b9" | 1366 | "checksum smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ed6f19b800d76574926e458d5f8e2dbea86c2b58c08d33a982448f09ac8d0c" |
1269 | "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" | 1367 | "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" |
1270 | "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" | 1368 | "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" |
1271 | "checksum superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50b13d42370e0f5fc62eafdd5c2d20065eaf5458dab215ff3e20e63eea96b30" | 1369 | "checksum superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50b13d42370e0f5fc62eafdd5c2d20065eaf5458dab215ff3e20e63eea96b30" |
1272 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" | ||
1273 | "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" | 1370 | "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" |
1274 | "checksum syn 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)" = "455a6ec9b368f8c479b0ae5494d13b22dc00990d2f00d68c9dc6a2dc4f17f210" | 1371 | "checksum syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b036b7b35e846707c0e55c2c9441fa47867c0f87fca416921db3261b1d8c741a" |
1275 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" | ||
1276 | "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" | 1372 | "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" |
1277 | "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" | 1373 | "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" |
1278 | "checksum tera 0.11.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4f79f17fe555fffe4838a082a63636883ee13022888dc7bdc99edad8e0a411cd" | 1374 | "checksum tera 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)" = "2829d259c4699fbbe8acb353d231e6da31ff4301c52244413ed29ff6093da412" |
1279 | "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" | 1375 | "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" |
1280 | "checksum text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc86da66d0b9aa8d359b0ec31b4342c6bc52637eadef05b91b098551a9f8e9" | 1376 | "checksum text_unit 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc86da66d0b9aa8d359b0ec31b4342c6bc52637eadef05b91b098551a9f8e9" |
1281 | "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" | 1377 | "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" |
1282 | "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" | 1378 | "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" |
1283 | "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" | 1379 | "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" |
1284 | "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" | 1380 | "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" |
1381 | "checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77" | ||
1285 | "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" | 1382 | "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" |
1286 | "checksum unic-char-property 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce36d3f7ce754afdbccccf8ff0dd0134e50fb44aaae579f96218856e9e5dbd1e" | 1383 | "checksum unic-char-property 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce36d3f7ce754afdbccccf8ff0dd0134e50fb44aaae579f96218856e9e5dbd1e" |
1287 | "checksum unic-char-range 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab85fab42ad1b26cafc03bf891f69cb4d6e15f491030e89a0122197baa8ae8" | 1384 | "checksum unic-char-range 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab85fab42ad1b26cafc03bf891f69cb4d6e15f491030e89a0122197baa8ae8" |
@@ -1293,7 +1390,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1293 | "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" | 1390 | "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" |
1294 | "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" | 1391 | "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" |
1295 | "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" | 1392 | "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" |
1296 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" | ||
1297 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" | 1393 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" |
1298 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" | 1394 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" |
1299 | "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" | 1395 | "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" |
@@ -16,7 +16,8 @@ functionality is provided via a language server. | |||
16 | 16 | ||
17 | ## Quick Start | 17 | ## Quick Start |
18 | 18 | ||
19 | Rust analyzer builds on stable Rust >= 1.29.0. | 19 | Rust analyzer builds on Rust >= 1.30.0 (currently in beta) and uses |
20 | the 2018 edition. | ||
20 | 21 | ||
21 | ``` | 22 | ``` |
22 | # run tests | 23 | # run tests |
@@ -61,99 +62,20 @@ fold: | |||
61 | * to quickly bootstrap usable and useful language server: solution | 62 | * to quickly bootstrap usable and useful language server: solution |
62 | that covers 80% of Rust code will be useful for IDEs, and will be | 63 | that covers 80% of Rust code will be useful for IDEs, and will be |
63 | vastly simpler than 100% solution. | 64 | vastly simpler than 100% solution. |
64 | 65 | ||
65 | * to understand how the consumer-side of compiler API should look like | 66 | * to understand how the consumer-side of compiler API should look like |
66 | (especially it's on-demand aspects). If you have | 67 | (especially it's on-demand aspects). If you have |
67 | `get_expression_type` function, you can write a ton of purely-IDE | 68 | `get_expression_type` function, you can write a ton of purely-IDE |
68 | features on top of it, even if the function is only partially | 69 | features on top of it, even if the function is only partially |
69 | correct. Plugin in the precise function afterwards should just make | 70 | correct. Plugin in the precise function afterwards should just make |
70 | IDE features more reliable. | 71 | IDE features more reliable. |
71 | 72 | ||
72 | The long term plan is to merge with the mainline rustc compiler, | 73 | The long term plan is to merge with the mainline rustc compiler, |
73 | probably around the HIR boundary? That is, use rust analyzer for | 74 | probably around the HIR boundary? That is, use rust analyzer for |
74 | parsing, macro expansion and related bits of name resolution, but | 75 | parsing, macro expansion and related bits of name resolution, but |
75 | leave the rest (including type inference and trait selection) to the | 76 | leave the rest (including type inference and trait selection) to the |
76 | existing rustc. | 77 | existing rustc. |
77 | 78 | ||
78 | ## Code Walk-Through | ||
79 | |||
80 | ### `crates/ra_syntax` | ||
81 | |||
82 | Rust syntax tree structure and parser. See | ||
83 | [RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design | ||
84 | notes. | ||
85 | |||
86 | - `yellow`, red/green syntax tree, heavily inspired [by this](https://github.com/apple/swift/tree/ab68f0d4cbf99cdfa672f8ffe18e433fddc8b371/lib/Syntax) | ||
87 | - `grammar`, the actual parser | ||
88 | - `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `yellow` trees | ||
89 | - `grammar.ron` RON description of the grammar, which is used to | ||
90 | generate `syntax_kinds` and `ast` modules. | ||
91 | - `algo`: generic tree algorithms, including `walk` for O(1) stack | ||
92 | space tree traversal (this is cool) and `visit` for type-driven | ||
93 | visiting the nodes (this is double plus cool, if you understand how | ||
94 | `Visitor` works, you understand rust-analyzer). | ||
95 | |||
96 | |||
97 | ### `crates/ra_editor` | ||
98 | |||
99 | All IDE features which can be implemented if you only have access to a | ||
100 | single file. `ra_editor` could be used to enhance editing of Rust code | ||
101 | without the need to fiddle with build-systems, file | ||
102 | synchronization and such. | ||
103 | |||
104 | In a sense, `ra_editor` is just a bunch of pure functions which take a | ||
105 | syntax tree as an input. | ||
106 | |||
107 | ### `crates/salsa` | ||
108 | |||
109 | An implementation of red-green incremental compilation algorithm from | ||
110 | rust compiler. It makes all rust-analyzer features on-demand. | ||
111 | |||
112 | |||
113 | ### `crates/ra_analysis` | ||
114 | |||
115 | A stateful library for analyzing many Rust files as they change. | ||
116 | `AnalysisHost` is a mutable entity (clojure's atom) which holds | ||
117 | current state, incorporates changes and handles out `Analysis` --- an | ||
118 | immutable consistent snapshot of world state at a point in time, which | ||
119 | actually powers analysis. | ||
120 | |||
121 | |||
122 | ### `crates/ra_lsp_server` | ||
123 | |||
124 | An LSP implementation which uses `ra_analysis` for managing state and | ||
125 | `ra_editor` for actually doing useful stuff. | ||
126 | |||
127 | |||
128 | ### `crates/cli` | ||
129 | |||
130 | A CLI interface to libsyntax | ||
131 | |||
132 | ### `crate/tools` | ||
133 | |||
134 | Code-gen tasks, used to develop rust-analyzer: | ||
135 | |||
136 | - `cargo gen-kinds` -- generate `ast` and `syntax_kinds` | ||
137 | - `cargo gen-tests` -- collect inline tests from grammar | ||
138 | - `cargo install-code` -- build and install VS Code extension and server | ||
139 | |||
140 | ### `editors/code` | ||
141 | |||
142 | VS Code plugin | ||
143 | |||
144 | |||
145 | ## Performance | ||
146 | |||
147 | Non-incremental, but seems pretty fast: | ||
148 | |||
149 | ``` | ||
150 | $ cargo build --release --package ra_cli | ||
151 | $ wc -l ~/projects/rust/src/libsyntax/parse/parser.rs | ||
152 | 7546 /home/matklad/projects/rust/src/libsyntax/parse/parser.rs | ||
153 | $ ./target/release/ra_cli parse < ~/projects/rust/src/libsyntax/parse/parser.rs --no-dump > /dev/null | ||
154 | parsing: 21.067065ms | ||
155 | ``` | ||
156 | |||
157 | ## Getting in touch | 79 | ## Getting in touch |
158 | 80 | ||
159 | @matklad can be found at Rust | 81 | @matklad can be found at Rust |
@@ -161,6 +83,11 @@ parsing: 21.067065ms | |||
161 | #ides-and-editors. | 83 | #ides-and-editors. |
162 | 84 | ||
163 | 85 | ||
86 | ## Contributing | ||
87 | |||
88 | See [CONTRIBUTING.md](./CONTRIBUTING.md) and [ARCHITECTURE.md](./ARCHITECTURE.md) | ||
89 | |||
90 | |||
164 | ## License | 91 | ## License |
165 | 92 | ||
166 | Rust analyzer is primarily distributed under the terms of both the MIT | 93 | Rust analyzer is primarily distributed under the terms of both the MIT |
diff --git a/appveyor.yml b/appveyor.yml index a6ba3b0e1..a32a1e7b8 100644 --- a/appveyor.yml +++ b/appveyor.yml | |||
@@ -2,7 +2,7 @@ os: Visual Studio 2015 | |||
2 | 2 | ||
3 | install: | 3 | install: |
4 | - curl https://win.rustup.rs/ --output rustup-init.exe | 4 | - curl https://win.rustup.rs/ --output rustup-init.exe |
5 | - rustup-init -yv --default-toolchain stable --default-host x86_64-pc-windows-msvc | 5 | - rustup-init -yv --default-toolchain beta --default-host x86_64-pc-windows-msvc |
6 | - set PATH=%PATH%;%USERPROFILE%\.cargo\bin | 6 | - set PATH=%PATH%;%USERPROFILE%\.cargo\bin |
7 | - rustc -vV | 7 | - rustc -vV |
8 | - cargo -vV | 8 | - cargo -vV |
diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml index a82e1761c..17b04182f 100644 --- a/crates/ra_analysis/Cargo.toml +++ b/crates/ra_analysis/Cargo.toml | |||
@@ -1,4 +1,5 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | ||
2 | name = "ra_analysis" | 3 | name = "ra_analysis" |
3 | version = "0.1.0" | 4 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
@@ -14,7 +15,7 @@ fst = "0.3.1" | |||
14 | im = "12.0.0" | 15 | im = "12.0.0" |
15 | ra_syntax = { path = "../ra_syntax" } | 16 | ra_syntax = { path = "../ra_syntax" } |
16 | ra_editor = { path = "../ra_editor" } | 17 | ra_editor = { path = "../ra_editor" } |
17 | salsa = { path = "../salsa" } | 18 | salsa = "0.5.0" |
18 | rustc-hash = "1.0" | 19 | rustc-hash = "1.0" |
19 | 20 | ||
20 | [dev-dependencies] | 21 | [dev-dependencies] |
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs new file mode 100644 index 000000000..c69577233 --- /dev/null +++ b/crates/ra_analysis/src/db.rs | |||
@@ -0,0 +1,117 @@ | |||
1 | use std::{ | ||
2 | fmt, | ||
3 | sync::Arc, | ||
4 | hash::{Hash, Hasher}, | ||
5 | }; | ||
6 | use salsa; | ||
7 | use rustc_hash::FxHashSet; | ||
8 | use ra_syntax::File; | ||
9 | use ra_editor::{LineIndex}; | ||
10 | use crate::{ | ||
11 | symbol_index::SymbolIndex, | ||
12 | module_map::{ModulesDatabase, ModuleTreeQuery, ModuleDescriptorQuery}, | ||
13 | FileId, FileResolverImp, | ||
14 | }; | ||
15 | |||
16 | #[derive(Default)] | ||
17 | pub(crate) struct RootDatabase { | ||
18 | runtime: salsa::runtime::Runtime<RootDatabase>, | ||
19 | } | ||
20 | |||
21 | impl fmt::Debug for RootDatabase { | ||
22 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
23 | fmt.write_str("RootDatabase { ... }") | ||
24 | } | ||
25 | } | ||
26 | |||
27 | impl salsa::Database for RootDatabase { | ||
28 | fn salsa_runtime(&self) -> &salsa::runtime::Runtime<RootDatabase> { | ||
29 | &self.runtime | ||
30 | } | ||
31 | } | ||
32 | |||
33 | impl salsa::ParallelDatabase for RootDatabase { | ||
34 | fn fork(&self) -> Self { | ||
35 | RootDatabase { | ||
36 | runtime: self.runtime.fork(), | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | |||
41 | impl Clone for RootDatabase { | ||
42 | fn clone(&self) -> RootDatabase { | ||
43 | salsa::ParallelDatabase::fork(self) | ||
44 | } | ||
45 | } | ||
46 | |||
47 | salsa::database_storage! { | ||
48 | pub(crate) struct RootDatabaseStorage for RootDatabase { | ||
49 | impl FilesDatabase { | ||
50 | fn file_text() for FileTextQuery; | ||
51 | fn file_set() for FileSetQuery; | ||
52 | } | ||
53 | impl SyntaxDatabase { | ||
54 | fn file_syntax() for FileSyntaxQuery; | ||
55 | fn file_lines() for FileLinesQuery; | ||
56 | fn file_symbols() for FileSymbolsQuery; | ||
57 | } | ||
58 | impl ModulesDatabase { | ||
59 | fn module_tree() for ModuleTreeQuery; | ||
60 | fn module_descriptor() for ModuleDescriptorQuery; | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | salsa::query_group! { | ||
66 | pub(crate) trait FilesDatabase: salsa::Database { | ||
67 | fn file_text(file_id: FileId) -> Arc<String> { | ||
68 | type FileTextQuery; | ||
69 | storage input; | ||
70 | } | ||
71 | fn file_set(key: ()) -> Arc<FileSet> { | ||
72 | type FileSetQuery; | ||
73 | storage input; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | |||
78 | #[derive(Default, Debug, PartialEq, Eq)] | ||
79 | pub(crate) struct FileSet { | ||
80 | pub(crate) files: FxHashSet<FileId>, | ||
81 | pub(crate) resolver: FileResolverImp, | ||
82 | } | ||
83 | |||
84 | impl Hash for FileSet { | ||
85 | fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
86 | let mut files = self.files.iter().cloned().collect::<Vec<_>>(); | ||
87 | files.sort(); | ||
88 | files.hash(hasher); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | salsa::query_group! { | ||
93 | pub(crate) trait SyntaxDatabase: FilesDatabase { | ||
94 | fn file_syntax(file_id: FileId) -> File { | ||
95 | type FileSyntaxQuery; | ||
96 | } | ||
97 | fn file_lines(file_id: FileId) -> Arc<LineIndex> { | ||
98 | type FileLinesQuery; | ||
99 | } | ||
100 | fn file_symbols(file_id: FileId) -> Arc<SymbolIndex> { | ||
101 | type FileSymbolsQuery; | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | |||
106 | fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> File { | ||
107 | let text = db.file_text(file_id); | ||
108 | File::parse(&*text) | ||
109 | } | ||
110 | fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> { | ||
111 | let text = db.file_text(file_id); | ||
112 | Arc::new(LineIndex::new(&*text)) | ||
113 | } | ||
114 | fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<SymbolIndex> { | ||
115 | let syntax = db.file_syntax(file_id); | ||
116 | Arc::new(SymbolIndex::for_file(file_id, syntax)) | ||
117 | } | ||
diff --git a/crates/ra_analysis/src/db/imp.rs b/crates/ra_analysis/src/db/imp.rs deleted file mode 100644 index 36f6cf290..000000000 --- a/crates/ra_analysis/src/db/imp.rs +++ /dev/null | |||
@@ -1,153 +0,0 @@ | |||
1 | use std::{ | ||
2 | sync::Arc, | ||
3 | any::Any, | ||
4 | hash::{Hash, Hasher}, | ||
5 | collections::hash_map::{DefaultHasher}, | ||
6 | iter, | ||
7 | }; | ||
8 | use rustc_hash::FxHashMap; | ||
9 | use salsa; | ||
10 | use {FileId, imp::FileResolverImp}; | ||
11 | use super::{State, Query, QueryCtx}; | ||
12 | |||
13 | pub(super) type Data = Arc<Any + Send + Sync + 'static>; | ||
14 | |||
15 | #[derive(Debug)] | ||
16 | pub(super) struct Db { | ||
17 | names: Arc<FxHashMap<salsa::QueryTypeId, &'static str>>, | ||
18 | pub(super) imp: salsa::Db<State, Data>, | ||
19 | } | ||
20 | |||
21 | impl Db { | ||
22 | pub(super) fn new(mut reg: QueryRegistry) -> Db { | ||
23 | let config = reg.config.take().unwrap(); | ||
24 | Db { | ||
25 | names: Arc::new(reg.names), | ||
26 | imp: salsa::Db::new(config, State::default()) | ||
27 | } | ||
28 | } | ||
29 | pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db { | ||
30 | let names = self.names.clone(); | ||
31 | let mut invalidations = salsa::Invalidations::new(); | ||
32 | invalidations.invalidate(FILE_TEXT, changed_files.iter().map(hash).map(salsa::InputFingerprint)); | ||
33 | if resolver_changed { | ||
34 | invalidations.invalidate(FILE_SET, iter::once(salsa::InputFingerprint(hash(&())))); | ||
35 | } else { | ||
36 | invalidations.invalidate(FILE_SET, iter::empty()); | ||
37 | } | ||
38 | let imp = self.imp.with_ground_data( | ||
39 | new_state, | ||
40 | invalidations, | ||
41 | ); | ||
42 | Db { names, imp } | ||
43 | } | ||
44 | pub(super) fn extract_trace(&self, ctx: &salsa::QueryCtx<State, Data>) -> Vec<&'static str> { | ||
45 | ctx.trace().into_iter().map(|it| self.names[&it]).collect() | ||
46 | } | ||
47 | } | ||
48 | |||
49 | pub(crate) trait EvalQuery { | ||
50 | type Params; | ||
51 | type Output; | ||
52 | fn query_type(&self) -> salsa::QueryTypeId; | ||
53 | fn f(&self) -> salsa::QueryFn<State, Data>; | ||
54 | fn get(&self, &QueryCtx, Self::Params) -> Arc<Self::Output>; | ||
55 | } | ||
56 | |||
57 | impl<T, R> EvalQuery for Query<T, R> | ||
58 | where | ||
59 | T: Hash + Send + Sync + 'static, | ||
60 | R: Hash + Send + Sync + 'static, | ||
61 | { | ||
62 | type Params = T; | ||
63 | type Output = R; | ||
64 | fn query_type(&self) -> salsa::QueryTypeId { | ||
65 | salsa::QueryTypeId(self.0) | ||
66 | } | ||
67 | fn f(&self) -> salsa::QueryFn<State, Data> { | ||
68 | let f = self.1; | ||
69 | Box::new(move |ctx, data| { | ||
70 | let ctx = QueryCtx { imp: ctx }; | ||
71 | let data: &T = data.downcast_ref().unwrap(); | ||
72 | let res = f(ctx, data); | ||
73 | let h = hash(&res); | ||
74 | (Arc::new(res), salsa::OutputFingerprint(h)) | ||
75 | }) | ||
76 | } | ||
77 | fn get(&self, ctx: &QueryCtx, params: Self::Params) -> Arc<Self::Output> { | ||
78 | let query_id = salsa::QueryId( | ||
79 | self.query_type(), | ||
80 | salsa::InputFingerprint(hash(¶ms)), | ||
81 | ); | ||
82 | let res = ctx.imp.get(query_id, Arc::new(params)); | ||
83 | res.downcast().unwrap() | ||
84 | } | ||
85 | } | ||
86 | |||
87 | pub(super) struct QueryRegistry { | ||
88 | config: Option<salsa::QueryConfig<State, Data>>, | ||
89 | names: FxHashMap<salsa::QueryTypeId, &'static str>, | ||
90 | } | ||
91 | |||
92 | impl QueryRegistry { | ||
93 | pub(super) fn new() -> QueryRegistry { | ||
94 | let mut config = salsa::QueryConfig::<State, Data>::new(); | ||
95 | config = config.with_ground_query( | ||
96 | FILE_TEXT, Box::new(|state, params| { | ||
97 | let file_id: &FileId = params.downcast_ref().unwrap(); | ||
98 | let res = state.file_map[file_id].clone(); | ||
99 | let fingerprint = salsa::OutputFingerprint(hash(&res)); | ||
100 | (res, fingerprint) | ||
101 | }) | ||
102 | ); | ||
103 | config = config.with_ground_query( | ||
104 | FILE_SET, Box::new(|state, _params| { | ||
105 | let file_ids: Vec<FileId> = state.file_map.keys().cloned().collect(); | ||
106 | let hash = hash(&file_ids); | ||
107 | let file_resolver = state.file_resolver.clone(); | ||
108 | let res = (file_ids, file_resolver); | ||
109 | let fingerprint = salsa::OutputFingerprint(hash); | ||
110 | (Arc::new(res), fingerprint) | ||
111 | }) | ||
112 | ); | ||
113 | let mut names = FxHashMap::default(); | ||
114 | names.insert(FILE_TEXT, "FILE_TEXT"); | ||
115 | names.insert(FILE_SET, "FILE_SET"); | ||
116 | QueryRegistry { config: Some(config), names } | ||
117 | } | ||
118 | pub(super) fn add<Q: EvalQuery>(&mut self, q: Q, name: &'static str) { | ||
119 | let id = q.query_type(); | ||
120 | let prev = self.names.insert(id, name); | ||
121 | assert!(prev.is_none(), "duplicate query: {:?}", id); | ||
122 | let config = self.config.take().unwrap(); | ||
123 | let config = config.with_query(id, q.f()); | ||
124 | self.config= Some(config); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | fn hash<T: Hash>(x: &T) -> u64 { | ||
129 | let mut hasher = DefaultHasher::new(); | ||
130 | x.hash(&mut hasher); | ||
131 | hasher.finish() | ||
132 | } | ||
133 | |||
134 | const FILE_TEXT: salsa::QueryTypeId = salsa::QueryTypeId(0); | ||
135 | pub(super) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc<String> { | ||
136 | let query_id = salsa::QueryId( | ||
137 | FILE_TEXT, | ||
138 | salsa::InputFingerprint(hash(&file_id)), | ||
139 | ); | ||
140 | let res = ctx.imp.get(query_id, Arc::new(file_id)); | ||
141 | res.downcast().unwrap() | ||
142 | } | ||
143 | |||
144 | const FILE_SET: salsa::QueryTypeId = salsa::QueryTypeId(1); | ||
145 | pub(super) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> { | ||
146 | let query_id = salsa::QueryId( | ||
147 | FILE_SET, | ||
148 | salsa::InputFingerprint(hash(&())), | ||
149 | ); | ||
150 | let res = ctx.imp.get(query_id, Arc::new(())); | ||
151 | res.downcast().unwrap() | ||
152 | } | ||
153 | |||
diff --git a/crates/ra_analysis/src/db/mod.rs b/crates/ra_analysis/src/db/mod.rs deleted file mode 100644 index 22769d112..000000000 --- a/crates/ra_analysis/src/db/mod.rs +++ /dev/null | |||
@@ -1,85 +0,0 @@ | |||
1 | mod imp; | ||
2 | |||
3 | use std::{ | ||
4 | sync::Arc, | ||
5 | }; | ||
6 | use im; | ||
7 | use salsa; | ||
8 | use {FileId, imp::FileResolverImp}; | ||
9 | |||
10 | #[derive(Debug, Default, Clone)] | ||
11 | pub(crate) struct State { | ||
12 | pub(crate) file_map: im::HashMap<FileId, Arc<String>>, | ||
13 | pub(crate) file_resolver: FileResolverImp | ||
14 | } | ||
15 | |||
16 | #[derive(Debug)] | ||
17 | pub(crate) struct Db { | ||
18 | imp: imp::Db, | ||
19 | } | ||
20 | |||
21 | #[derive(Clone, Copy)] | ||
22 | pub(crate) struct QueryCtx<'a> { | ||
23 | imp: &'a salsa::QueryCtx<State, imp::Data>, | ||
24 | } | ||
25 | |||
26 | pub(crate) struct Query<T, R>(pub(crate) u16, pub(crate) fn(QueryCtx, &T) -> R); | ||
27 | |||
28 | pub(crate) struct QueryRegistry { | ||
29 | imp: imp::QueryRegistry, | ||
30 | } | ||
31 | |||
32 | impl Default for Db { | ||
33 | fn default() -> Db { | ||
34 | Db::new() | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl Db { | ||
39 | pub(crate) fn new() -> Db { | ||
40 | let reg = QueryRegistry::new(); | ||
41 | Db { imp: imp::Db::new(reg.imp) } | ||
42 | } | ||
43 | pub(crate) fn state(&self) -> &State { | ||
44 | self.imp.imp.ground_data() | ||
45 | } | ||
46 | pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db { | ||
47 | Db { imp: self.imp.with_changes(new_state, changed_files, resolver_changed) } | ||
48 | } | ||
49 | pub(crate) fn make_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> R { | ||
50 | let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; | ||
51 | f(ctx) | ||
52 | } | ||
53 | #[allow(unused)] | ||
54 | pub(crate) fn trace_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> (R, Vec<&'static str>) { | ||
55 | let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; | ||
56 | let res = f(ctx); | ||
57 | let trace = self.imp.extract_trace(ctx.imp); | ||
58 | (res, trace) | ||
59 | } | ||
60 | } | ||
61 | |||
62 | impl<'a> QueryCtx<'a> { | ||
63 | pub(crate) fn get<Q: imp::EvalQuery>(&self, q: Q, params: Q::Params) -> Arc<Q::Output> { | ||
64 | q.get(self, params) | ||
65 | } | ||
66 | } | ||
67 | |||
68 | pub(crate) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc<String> { | ||
69 | imp::file_text(ctx, file_id) | ||
70 | } | ||
71 | |||
72 | pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> { | ||
73 | imp::file_set(ctx) | ||
74 | } | ||
75 | impl QueryRegistry { | ||
76 | fn new() -> QueryRegistry { | ||
77 | let mut reg = QueryRegistry { imp: imp::QueryRegistry::new() }; | ||
78 | ::queries::register_queries(&mut reg); | ||
79 | ::module_map::register_queries(&mut reg); | ||
80 | reg | ||
81 | } | ||
82 | pub(crate) fn add<Q: imp::EvalQuery>(&mut self, q: Q, name: &'static str) { | ||
83 | self.imp.add(q, name) | ||
84 | } | ||
85 | } | ||
diff --git a/crates/ra_analysis/src/descriptors.rs b/crates/ra_analysis/src/descriptors.rs index 0731b5572..8d9f38ca5 100644 --- a/crates/ra_analysis/src/descriptors.rs +++ b/crates/ra_analysis/src/descriptors.rs | |||
@@ -4,14 +4,15 @@ use std::{ | |||
4 | use relative_path::RelativePathBuf; | 4 | use relative_path::RelativePathBuf; |
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | SmolStr, | 6 | SmolStr, |
7 | ast::{self, NameOwner}, | 7 | ast::{self, NameOwner, AstNode}, |
8 | text_utils::is_subrange | ||
8 | }; | 9 | }; |
9 | use { | 10 | use crate::{ |
10 | FileId, | 11 | FileId, |
11 | imp::FileResolverImp, | 12 | imp::FileResolverImp, |
12 | }; | 13 | }; |
13 | 14 | ||
14 | #[derive(Debug, Hash)] | 15 | #[derive(Debug, PartialEq, Eq, Hash)] |
15 | pub struct ModuleDescriptor { | 16 | pub struct ModuleDescriptor { |
16 | pub submodules: Vec<Submodule> | 17 | pub submodules: Vec<Submodule> |
17 | } | 18 | } |
@@ -42,7 +43,7 @@ pub struct Submodule { | |||
42 | pub name: SmolStr, | 43 | pub name: SmolStr, |
43 | } | 44 | } |
44 | 45 | ||
45 | #[derive(Hash, Debug)] | 46 | #[derive(Debug, PartialEq, Eq, Hash)] |
46 | pub(crate) struct ModuleTreeDescriptor { | 47 | pub(crate) struct ModuleTreeDescriptor { |
47 | nodes: Vec<NodeData>, | 48 | nodes: Vec<NodeData>, |
48 | links: Vec<LinkData>, | 49 | links: Vec<LinkData>, |
@@ -51,7 +52,7 @@ pub(crate) struct ModuleTreeDescriptor { | |||
51 | 52 | ||
52 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 53 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
53 | struct Node(usize); | 54 | struct Node(usize); |
54 | #[derive(Hash, Debug)] | 55 | #[derive(Hash, Debug, PartialEq, Eq)] |
55 | struct NodeData { | 56 | struct NodeData { |
56 | file_id: FileId, | 57 | file_id: FileId, |
57 | links: Vec<Link>, | 58 | links: Vec<Link>, |
@@ -60,7 +61,7 @@ struct NodeData { | |||
60 | 61 | ||
61 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 62 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
62 | pub(crate) struct Link(usize); | 63 | pub(crate) struct Link(usize); |
63 | #[derive(Hash, Debug)] | 64 | #[derive(Hash, Debug, PartialEq, Eq)] |
64 | struct LinkData { | 65 | struct LinkData { |
65 | owner: Node, | 66 | owner: Node, |
66 | name: SmolStr, | 67 | name: SmolStr, |
@@ -69,7 +70,7 @@ struct LinkData { | |||
69 | } | 70 | } |
70 | 71 | ||
71 | 72 | ||
72 | #[derive(Clone, Debug, Hash)] | 73 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
73 | pub enum Problem { | 74 | pub enum Problem { |
74 | UnresolvedModule { | 75 | UnresolvedModule { |
75 | candidate: RelativePathBuf, | 76 | candidate: RelativePathBuf, |
@@ -218,3 +219,56 @@ fn resolve_submodule( | |||
218 | } | 219 | } |
219 | (points_to, problem) | 220 | (points_to, problem) |
220 | } | 221 | } |
222 | |||
223 | #[derive(Debug, Clone)] | ||
224 | pub struct FnDescriptor { | ||
225 | pub name: String, | ||
226 | pub label : String, | ||
227 | pub ret_type: Option<String>, | ||
228 | pub params: Vec<String>, | ||
229 | } | ||
230 | |||
231 | impl FnDescriptor { | ||
232 | pub fn new(node: ast::FnDef) -> Option<Self> { | ||
233 | let name = node.name()?.text().to_string(); | ||
234 | |||
235 | // Strip the body out for the label. | ||
236 | let label : String = if let Some(body) = node.body() { | ||
237 | let body_range = body.syntax().range(); | ||
238 | let label : String = node.syntax().children() | ||
239 | .filter(|child| !is_subrange(body_range, child.range())) | ||
240 | .map(|node| node.text().to_string()) | ||
241 | .collect(); | ||
242 | label | ||
243 | } else { | ||
244 | node.syntax().text().to_string() | ||
245 | }; | ||
246 | |||
247 | let params = FnDescriptor::param_list(node); | ||
248 | let ret_type = node.ret_type().map(|r| r.syntax().text().to_string()); | ||
249 | |||
250 | Some(FnDescriptor { | ||
251 | name, | ||
252 | ret_type, | ||
253 | params, | ||
254 | label | ||
255 | }) | ||
256 | } | ||
257 | |||
258 | fn param_list(node: ast::FnDef) -> Vec<String> { | ||
259 | let mut res = vec![]; | ||
260 | if let Some(param_list) = node.param_list() { | ||
261 | if let Some(self_param) = param_list.self_param() { | ||
262 | res.push(self_param.syntax().text().to_string()) | ||
263 | } | ||
264 | |||
265 | // Maybe use param.pat here? See if we can just extract the name? | ||
266 | //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); | ||
267 | res.extend(param_list.params() | ||
268 | .filter_map(|p| p.pat()) | ||
269 | .map(|pat| pat.syntax().text().to_string()) | ||
270 | ); | ||
271 | } | ||
272 | res | ||
273 | } | ||
274 | } | ||
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 47bc0032b..5efcaeca0 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | sync::{ | 2 | sync::{ |
3 | Arc, | 3 | Arc, |
4 | atomic::{AtomicBool, Ordering::SeqCst}, | ||
5 | }, | 4 | }, |
5 | hash::{Hash, Hasher}, | ||
6 | fmt, | 6 | fmt, |
7 | collections::VecDeque, | 7 | collections::VecDeque, |
8 | iter, | 8 | iter, |
@@ -12,24 +12,38 @@ use relative_path::RelativePath; | |||
12 | use rustc_hash::FxHashSet; | 12 | use rustc_hash::FxHashSet; |
13 | use ra_editor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit, resolve_local_name}; | 13 | use ra_editor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit, resolve_local_name}; |
14 | use ra_syntax::{ | 14 | use ra_syntax::{ |
15 | TextUnit, TextRange, SmolStr, File, AstNode, | 15 | TextUnit, TextRange, SmolStr, File, AstNode, SyntaxNodeRef, |
16 | SyntaxKind::*, | 16 | SyntaxKind::*, |
17 | ast::{self, NameOwner}, | 17 | ast::{self, NameOwner, ArgListOwner, Expr}, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | use { | 20 | use crate::{ |
21 | FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, | 21 | FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, |
22 | JobToken, CrateGraph, CrateId, | 22 | JobToken, CrateGraph, CrateId, |
23 | roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot}, | 23 | roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot}, |
24 | descriptors::{ModuleTreeDescriptor, Problem}, | 24 | descriptors::{FnDescriptor, ModuleTreeDescriptor, Problem}, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | |||
28 | #[derive(Clone, Debug)] | 27 | #[derive(Clone, Debug)] |
29 | pub(crate) struct FileResolverImp { | 28 | pub(crate) struct FileResolverImp { |
30 | inner: Arc<FileResolver> | 29 | inner: Arc<FileResolver> |
31 | } | 30 | } |
32 | 31 | ||
32 | impl PartialEq for FileResolverImp { | ||
33 | fn eq(&self, other: &FileResolverImp) -> bool { | ||
34 | self.inner() == other.inner() | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl Eq for FileResolverImp { | ||
39 | } | ||
40 | |||
41 | impl Hash for FileResolverImp { | ||
42 | fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
43 | self.inner().hash(hasher); | ||
44 | } | ||
45 | } | ||
46 | |||
33 | impl FileResolverImp { | 47 | impl FileResolverImp { |
34 | pub(crate) fn new(inner: Arc<FileResolver>) -> FileResolverImp { | 48 | pub(crate) fn new(inner: Arc<FileResolver>) -> FileResolverImp { |
35 | FileResolverImp { inner } | 49 | FileResolverImp { inner } |
@@ -40,6 +54,9 @@ impl FileResolverImp { | |||
40 | pub(crate) fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> { | 54 | pub(crate) fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> { |
41 | self.inner.resolve(file_id, path) | 55 | self.inner.resolve(file_id, path) |
42 | } | 56 | } |
57 | fn inner(&self) -> *const FileResolver { | ||
58 | &*self.inner | ||
59 | } | ||
43 | } | 60 | } |
44 | 61 | ||
45 | impl Default for FileResolverImp { | 62 | impl Default for FileResolverImp { |
@@ -60,29 +77,27 @@ impl Default for FileResolverImp { | |||
60 | 77 | ||
61 | #[derive(Debug)] | 78 | #[derive(Debug)] |
62 | pub(crate) struct AnalysisHostImpl { | 79 | pub(crate) struct AnalysisHostImpl { |
63 | data: Arc<WorldData> | 80 | data: WorldData |
64 | } | 81 | } |
65 | 82 | ||
66 | impl AnalysisHostImpl { | 83 | impl AnalysisHostImpl { |
67 | pub fn new() -> AnalysisHostImpl { | 84 | pub fn new() -> AnalysisHostImpl { |
68 | AnalysisHostImpl { | 85 | AnalysisHostImpl { |
69 | data: Arc::new(WorldData::default()), | 86 | data: WorldData::default(), |
70 | } | 87 | } |
71 | } | 88 | } |
72 | pub fn analysis(&self) -> AnalysisImpl { | 89 | pub fn analysis(&self) -> AnalysisImpl { |
73 | AnalysisImpl { | 90 | AnalysisImpl { |
74 | needs_reindex: AtomicBool::new(false), | ||
75 | data: self.data.clone(), | 91 | data: self.data.clone(), |
76 | } | 92 | } |
77 | } | 93 | } |
78 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { | 94 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { |
79 | let data = self.data_mut(); | 95 | self.data_mut() |
80 | data.root = Arc::new(data.root.apply_changes(changes, None)); | 96 | .root.apply_changes(changes, None); |
81 | } | 97 | } |
82 | pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { | 98 | pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { |
83 | let data = self.data_mut(); | 99 | self.data_mut() |
84 | data.file_resolver = resolver.clone(); | 100 | .root.apply_changes(&mut iter::empty(), Some(resolver)); |
85 | data.root = Arc::new(data.root.apply_changes(&mut iter::empty(), Some(resolver))); | ||
86 | } | 101 | } |
87 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | 102 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { |
88 | let mut visited = FxHashSet::default(); | 103 | let mut visited = FxHashSet::default(); |
@@ -97,34 +112,24 @@ impl AnalysisHostImpl { | |||
97 | self.data_mut().libs.push(Arc::new(root)); | 112 | self.data_mut().libs.push(Arc::new(root)); |
98 | } | 113 | } |
99 | fn data_mut(&mut self) -> &mut WorldData { | 114 | fn data_mut(&mut self) -> &mut WorldData { |
100 | Arc::make_mut(&mut self.data) | 115 | &mut self.data |
101 | } | 116 | } |
102 | } | 117 | } |
103 | 118 | ||
104 | pub(crate) struct AnalysisImpl { | 119 | pub(crate) struct AnalysisImpl { |
105 | needs_reindex: AtomicBool, | 120 | data: WorldData, |
106 | data: Arc<WorldData>, | ||
107 | } | 121 | } |
108 | 122 | ||
109 | impl fmt::Debug for AnalysisImpl { | 123 | impl fmt::Debug for AnalysisImpl { |
110 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 124 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
111 | (&*self.data).fmt(f) | 125 | self.data.fmt(f) |
112 | } | ||
113 | } | ||
114 | |||
115 | impl Clone for AnalysisImpl { | ||
116 | fn clone(&self) -> AnalysisImpl { | ||
117 | AnalysisImpl { | ||
118 | needs_reindex: AtomicBool::new(self.needs_reindex.load(SeqCst)), | ||
119 | data: Arc::clone(&self.data), | ||
120 | } | ||
121 | } | 126 | } |
122 | } | 127 | } |
123 | 128 | ||
124 | impl AnalysisImpl { | 129 | impl AnalysisImpl { |
125 | fn root(&self, file_id: FileId) -> &SourceRoot { | 130 | fn root(&self, file_id: FileId) -> &SourceRoot { |
126 | if self.data.root.contains(file_id) { | 131 | if self.data.root.contains(file_id) { |
127 | return &*self.data.root; | 132 | return &self.data.root; |
128 | } | 133 | } |
129 | &**self.data.libs.iter().find(|it| it.contains(file_id)).unwrap() | 134 | &**self.data.libs.iter().find(|it| it.contains(file_id)).unwrap() |
130 | } | 135 | } |
@@ -306,6 +311,68 @@ impl AnalysisImpl { | |||
306 | .collect() | 311 | .collect() |
307 | } | 312 | } |
308 | 313 | ||
314 | pub fn resolve_callable(&self, file_id: FileId, offset: TextUnit, token: &JobToken) | ||
315 | -> Option<(FnDescriptor, Option<usize>)> { | ||
316 | |||
317 | let root = self.root(file_id); | ||
318 | let file = root.syntax(file_id); | ||
319 | let syntax = file.syntax(); | ||
320 | |||
321 | // Find the calling expression and it's NameRef | ||
322 | let calling_node = FnCallNode::with_node(syntax, offset)?; | ||
323 | let name_ref = calling_node.name_ref()?; | ||
324 | |||
325 | // Resolve the function's NameRef (NOTE: this isn't entirely accurate). | ||
326 | let file_symbols = self.index_resolve(name_ref, token); | ||
327 | for (_, fs) in file_symbols { | ||
328 | if fs.kind == FN_DEF { | ||
329 | if let Some(fn_def) = find_node_at_offset(syntax, fs.node_range.start()) { | ||
330 | if let Some(descriptor) = FnDescriptor::new(fn_def) { | ||
331 | // If we have a calling expression let's find which argument we are on | ||
332 | let mut current_parameter = None; | ||
333 | |||
334 | let num_params = descriptor.params.len(); | ||
335 | let has_self = fn_def.param_list() | ||
336 | .and_then(|l| l.self_param()) | ||
337 | .is_some(); | ||
338 | |||
339 | if num_params == 1 { | ||
340 | if !has_self { | ||
341 | current_parameter = Some(1); | ||
342 | } | ||
343 | } else if num_params > 1 { | ||
344 | // Count how many parameters into the call we are. | ||
345 | // TODO: This is best effort for now and should be fixed at some point. | ||
346 | // It may be better to see where we are in the arg_list and then check | ||
347 | // where offset is in that list (or beyond). | ||
348 | // Revisit this after we get documentation comments in. | ||
349 | if let Some(ref arg_list) = calling_node.arg_list() { | ||
350 | let start = arg_list.syntax().range().start(); | ||
351 | |||
352 | let range_search = TextRange::from_to(start, offset); | ||
353 | let mut commas: usize = arg_list.syntax().text() | ||
354 | .slice(range_search).to_string() | ||
355 | .matches(",") | ||
356 | .count(); | ||
357 | |||
358 | // If we have a method call eat the first param since it's just self. | ||
359 | if has_self { | ||
360 | commas = commas + 1; | ||
361 | } | ||
362 | |||
363 | current_parameter = Some(commas); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | return Some((descriptor, current_parameter)); | ||
368 | } | ||
369 | } | ||
370 | } | ||
371 | } | ||
372 | |||
373 | None | ||
374 | } | ||
375 | |||
309 | fn index_resolve(&self, name_ref: ast::NameRef, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | 376 | fn index_resolve(&self, name_ref: ast::NameRef, token: &JobToken) -> Vec<(FileId, FileSymbol)> { |
310 | let name = name_ref.text(); | 377 | let name = name_ref.text(); |
311 | let mut query = Query::new(name.to_string()); | 378 | let mut query = Query::new(name.to_string()); |
@@ -325,9 +392,8 @@ impl AnalysisImpl { | |||
325 | 392 | ||
326 | #[derive(Default, Clone, Debug)] | 393 | #[derive(Default, Clone, Debug)] |
327 | struct WorldData { | 394 | struct WorldData { |
328 | file_resolver: FileResolverImp, | ||
329 | crate_graph: CrateGraph, | 395 | crate_graph: CrateGraph, |
330 | root: Arc<WritableSourceRoot>, | 396 | root: WritableSourceRoot, |
331 | libs: Vec<Arc<ReadonlySourceRoot>>, | 397 | libs: Vec<Arc<ReadonlySourceRoot>>, |
332 | } | 398 | } |
333 | 399 | ||
@@ -355,3 +421,46 @@ impl CrateGraph { | |||
355 | Some(crate_id) | 421 | Some(crate_id) |
356 | } | 422 | } |
357 | } | 423 | } |
424 | |||
425 | enum FnCallNode<'a> { | ||
426 | CallExpr(ast::CallExpr<'a>), | ||
427 | MethodCallExpr(ast::MethodCallExpr<'a>) | ||
428 | } | ||
429 | |||
430 | impl<'a> FnCallNode<'a> { | ||
431 | pub fn with_node(syntax: SyntaxNodeRef, offset: TextUnit) -> Option<FnCallNode> { | ||
432 | if let Some(expr) = find_node_at_offset::<ast::CallExpr>(syntax, offset) { | ||
433 | return Some(FnCallNode::CallExpr(expr)); | ||
434 | } | ||
435 | if let Some(expr) = find_node_at_offset::<ast::MethodCallExpr>(syntax, offset) { | ||
436 | return Some(FnCallNode::MethodCallExpr(expr)); | ||
437 | } | ||
438 | None | ||
439 | } | ||
440 | |||
441 | pub fn name_ref(&self) -> Option<ast::NameRef> { | ||
442 | match *self { | ||
443 | FnCallNode::CallExpr(call_expr) => { | ||
444 | Some(match call_expr.expr()? { | ||
445 | Expr::PathExpr(path_expr) => { | ||
446 | path_expr.path()?.segment()?.name_ref()? | ||
447 | }, | ||
448 | _ => return None | ||
449 | }) | ||
450 | }, | ||
451 | |||
452 | FnCallNode::MethodCallExpr(call_expr) => { | ||
453 | call_expr.syntax().children() | ||
454 | .filter_map(ast::NameRef::cast) | ||
455 | .nth(0) | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | |||
460 | pub fn arg_list(&self) -> Option<ast::ArgList> { | ||
461 | match *self { | ||
462 | FnCallNode::CallExpr(expr) => expr.arg_list(), | ||
463 | FnCallNode::MethodCallExpr(expr) => expr.arg_list() | ||
464 | } | ||
465 | } | ||
466 | } | ||
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 849fd93e4..d8b355a81 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -19,7 +19,6 @@ mod imp; | |||
19 | mod job; | 19 | mod job; |
20 | mod roots; | 20 | mod roots; |
21 | mod db; | 21 | mod db; |
22 | mod queries; | ||
23 | mod descriptors; | 22 | mod descriptors; |
24 | 23 | ||
25 | use std::{ | 24 | use std::{ |
@@ -29,15 +28,18 @@ use std::{ | |||
29 | 28 | ||
30 | use relative_path::{RelativePath, RelativePathBuf}; | 29 | use relative_path::{RelativePath, RelativePathBuf}; |
31 | use ra_syntax::{File, TextRange, TextUnit, AtomEdit}; | 30 | use ra_syntax::{File, TextRange, TextUnit, AtomEdit}; |
32 | use imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp}; | ||
33 | use rustc_hash::FxHashMap; | 31 | use rustc_hash::FxHashMap; |
32 | use crate::imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp}; | ||
34 | 33 | ||
35 | pub use ra_editor::{ | 34 | pub use ra_editor::{ |
36 | StructureNode, LineIndex, FileSymbol, | 35 | StructureNode, LineIndex, FileSymbol, |
37 | Runnable, RunnableKind, HighlightedRange, CompletionItem, | 36 | Runnable, RunnableKind, HighlightedRange, CompletionItem, |
38 | Fold, FoldKind | 37 | Fold, FoldKind |
39 | }; | 38 | }; |
40 | pub use job::{JobToken, JobHandle}; | 39 | pub use crate::{ |
40 | job::{JobToken, JobHandle}, | ||
41 | descriptors::FnDescriptor, | ||
42 | }; | ||
41 | 43 | ||
42 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 44 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
43 | pub struct FileId(pub u32); | 45 | pub struct FileId(pub u32); |
@@ -159,7 +161,7 @@ impl Query { | |||
159 | } | 161 | } |
160 | } | 162 | } |
161 | 163 | ||
162 | #[derive(Clone, Debug)] | 164 | #[derive(Debug)] |
163 | pub struct Analysis { | 165 | pub struct Analysis { |
164 | imp: AnalysisImpl | 166 | imp: AnalysisImpl |
165 | } | 167 | } |
@@ -236,6 +238,11 @@ impl Analysis { | |||
236 | let file = self.imp.file_syntax(file_id); | 238 | let file = self.imp.file_syntax(file_id); |
237 | ra_editor::folding_ranges(&file) | 239 | ra_editor::folding_ranges(&file) |
238 | } | 240 | } |
241 | |||
242 | pub fn resolve_callable(&self, file_id: FileId, offset: TextUnit, token: &JobToken) | ||
243 | -> Option<(FnDescriptor, Option<usize>)> { | ||
244 | self.imp.resolve_callable(file_id, offset, token) | ||
245 | } | ||
239 | } | 246 | } |
240 | 247 | ||
241 | #[derive(Debug)] | 248 | #[derive(Debug)] |
@@ -250,3 +257,9 @@ impl LibraryData { | |||
250 | LibraryData { root } | 257 | LibraryData { root } |
251 | } | 258 | } |
252 | } | 259 | } |
260 | |||
261 | #[test] | ||
262 | fn analysis_is_send() { | ||
263 | fn is_send<T: Send>() {} | ||
264 | is_send::<Analysis>(); | ||
265 | } | ||
diff --git a/crates/ra_analysis/src/module_map.rs b/crates/ra_analysis/src/module_map.rs index a21f55fff..c1799e3d4 100644 --- a/crates/ra_analysis/src/module_map.rs +++ b/crates/ra_analysis/src/module_map.rs | |||
@@ -1,157 +1,34 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | use { | 2 | use crate::{ |
3 | FileId, | 3 | FileId, |
4 | db::{ | 4 | db::{SyntaxDatabase}, |
5 | Query, QueryRegistry, QueryCtx, | ||
6 | file_set | ||
7 | }, | ||
8 | queries::file_syntax, | ||
9 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | 5 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, |
10 | }; | 6 | }; |
11 | 7 | ||
12 | pub(crate) fn register_queries(reg: &mut QueryRegistry) { | 8 | salsa::query_group! { |
13 | reg.add(MODULE_DESCR, "MODULE_DESCR"); | 9 | pub(crate) trait ModulesDatabase: SyntaxDatabase { |
14 | reg.add(MODULE_TREE, "MODULE_TREE"); | 10 | fn module_tree(key: ()) -> Arc<ModuleTreeDescriptor> { |
15 | } | 11 | type ModuleTreeQuery; |
16 | |||
17 | pub(crate) fn module_tree(ctx: QueryCtx) -> Arc<ModuleTreeDescriptor> { | ||
18 | ctx.get(MODULE_TREE, ()) | ||
19 | } | ||
20 | |||
21 | const MODULE_DESCR: Query<FileId, ModuleDescriptor> = Query(30, |ctx, &file_id| { | ||
22 | let file = file_syntax(ctx, file_id); | ||
23 | ModuleDescriptor::new(file.ast()) | ||
24 | }); | ||
25 | |||
26 | const MODULE_TREE: Query<(), ModuleTreeDescriptor> = Query(31, |ctx, _| { | ||
27 | let file_set = file_set(ctx); | ||
28 | let mut files = Vec::new(); | ||
29 | for &file_id in file_set.0.iter() { | ||
30 | let module_descr = ctx.get(MODULE_DESCR, file_id); | ||
31 | files.push((file_id, module_descr)); | ||
32 | } | ||
33 | ModuleTreeDescriptor::new(files.iter().map(|(file_id, descr)| (*file_id, &**descr)), &file_set.1) | ||
34 | }); | ||
35 | |||
36 | #[cfg(test)] | ||
37 | mod tests { | ||
38 | use std::collections::HashMap; | ||
39 | use im; | ||
40 | use relative_path::{RelativePath, RelativePathBuf}; | ||
41 | use { | ||
42 | db::{Db}, | ||
43 | imp::FileResolverImp, | ||
44 | FileId, FileResolver, | ||
45 | }; | ||
46 | use super::*; | ||
47 | |||
48 | #[derive(Debug)] | ||
49 | struct FileMap(im::HashMap<FileId, RelativePathBuf>); | ||
50 | |||
51 | impl FileResolver for FileMap { | ||
52 | fn file_stem(&self, file_id: FileId) -> String { | ||
53 | self.0[&file_id].file_stem().unwrap().to_string() | ||
54 | } | 12 | } |
55 | fn resolve(&self, file_id: FileId, rel: &RelativePath) -> Option<FileId> { | 13 | fn module_descriptor(file_id: FileId) -> Arc<ModuleDescriptor> { |
56 | let path = self.0[&file_id].join(rel).normalize(); | 14 | type ModuleDescriptorQuery; |
57 | self.0.iter() | ||
58 | .filter_map(|&(id, ref p)| Some(id).filter(|_| p == &path)) | ||
59 | .next() | ||
60 | } | 15 | } |
61 | } | 16 | } |
17 | } | ||
62 | 18 | ||
63 | struct Fixture { | ||
64 | next_file_id: u32, | ||
65 | fm: im::HashMap<FileId, RelativePathBuf>, | ||
66 | db: Db, | ||
67 | } | ||
68 | |||
69 | impl Fixture { | ||
70 | fn new() -> Fixture { | ||
71 | Fixture { | ||
72 | next_file_id: 1, | ||
73 | fm: im::HashMap::new(), | ||
74 | db: Db::new(), | ||
75 | } | ||
76 | } | ||
77 | fn add_file(&mut self, path: &str, text: &str) -> FileId { | ||
78 | assert!(path.starts_with("/")); | ||
79 | let file_id = FileId(self.next_file_id); | ||
80 | self.next_file_id += 1; | ||
81 | self.fm.insert(file_id, RelativePathBuf::from(&path[1..])); | ||
82 | let mut new_state = self.db.state().clone(); | ||
83 | new_state.file_map.insert(file_id, Arc::new(text.to_string())); | ||
84 | new_state.file_resolver = FileResolverImp::new( | ||
85 | Arc::new(FileMap(self.fm.clone())) | ||
86 | ); | ||
87 | self.db = self.db.with_changes(new_state, &[file_id], true); | ||
88 | file_id | ||
89 | } | ||
90 | fn remove_file(&mut self, file_id: FileId) { | ||
91 | self.fm.remove(&file_id); | ||
92 | let mut new_state = self.db.state().clone(); | ||
93 | new_state.file_map.remove(&file_id); | ||
94 | new_state.file_resolver = FileResolverImp::new( | ||
95 | Arc::new(FileMap(self.fm.clone())) | ||
96 | ); | ||
97 | self.db = self.db.with_changes(new_state, &[file_id], true); | ||
98 | } | ||
99 | fn change_file(&mut self, file_id: FileId, new_text: &str) { | ||
100 | let mut new_state = self.db.state().clone(); | ||
101 | new_state.file_map.insert(file_id, Arc::new(new_text.to_string())); | ||
102 | self.db = self.db.with_changes(new_state, &[file_id], false); | ||
103 | } | ||
104 | fn check_parent_modules( | ||
105 | &self, | ||
106 | file_id: FileId, | ||
107 | expected: &[FileId], | ||
108 | queries: &[(&'static str, u64)] | ||
109 | ) { | ||
110 | let (tree, events) = self.db.trace_query(|ctx| module_tree(ctx)); | ||
111 | let actual = tree.parent_modules(file_id) | ||
112 | .into_iter() | ||
113 | .map(|link| link.owner(&tree)) | ||
114 | .collect::<Vec<_>>(); | ||
115 | assert_eq!(actual.as_slice(), expected); | ||
116 | let mut counts = HashMap::new(); | ||
117 | events.into_iter() | ||
118 | .for_each(|event| *counts.entry(event).or_insert(0) += 1); | ||
119 | for &(query_id, expected_count) in queries.iter() { | ||
120 | let actual_count = *counts.get(&query_id).unwrap_or(&0); | ||
121 | assert_eq!( | ||
122 | actual_count, | ||
123 | expected_count, | ||
124 | "counts for {} differ", | ||
125 | query_id, | ||
126 | ) | ||
127 | } | ||
128 | |||
129 | } | ||
130 | } | ||
131 | |||
132 | #[test] | ||
133 | fn test_parent_module() { | ||
134 | let mut f = Fixture::new(); | ||
135 | let foo = f.add_file("/foo.rs", ""); | ||
136 | f.check_parent_modules(foo, &[], &[("MODULE_DESCR", 1)]); | ||
137 | |||
138 | let lib = f.add_file("/lib.rs", "mod foo;"); | ||
139 | f.check_parent_modules(foo, &[lib], &[("MODULE_DESCR", 1)]); | ||
140 | f.check_parent_modules(foo, &[lib], &[("MODULE_DESCR", 0)]); | ||
141 | |||
142 | f.change_file(lib, ""); | ||
143 | f.check_parent_modules(foo, &[], &[("MODULE_DESCR", 1)]); | ||
144 | |||
145 | f.change_file(lib, "mod foo;"); | ||
146 | f.check_parent_modules(foo, &[lib], &[("MODULE_DESCR", 1)]); | ||
147 | |||
148 | f.change_file(lib, "mod bar;"); | ||
149 | f.check_parent_modules(foo, &[], &[("MODULE_DESCR", 1)]); | ||
150 | 19 | ||
151 | f.change_file(lib, "mod foo;"); | 20 | fn module_descriptor(db: &impl ModulesDatabase, file_id: FileId) -> Arc<ModuleDescriptor> { |
152 | f.check_parent_modules(foo, &[lib], &[("MODULE_DESCR", 1)]); | 21 | let file = db.file_syntax(file_id); |
22 | Arc::new(ModuleDescriptor::new(file.ast())) | ||
23 | } | ||
153 | 24 | ||
154 | f.remove_file(lib); | 25 | fn module_tree(db: &impl ModulesDatabase, (): ()) -> Arc<ModuleTreeDescriptor> { |
155 | f.check_parent_modules(foo, &[], &[("MODULE_DESCR", 0)]); | 26 | let file_set = db.file_set(()); |
27 | let mut files = Vec::new(); | ||
28 | for &file_id in file_set.files.iter() { | ||
29 | let module_descr = db.module_descriptor(file_id); | ||
30 | files.push((file_id, module_descr)); | ||
156 | } | 31 | } |
32 | let res = ModuleTreeDescriptor::new(files.iter().map(|(file_id, descr)| (*file_id, &**descr)), &file_set.resolver); | ||
33 | Arc::new(res) | ||
157 | } | 34 | } |
diff --git a/crates/ra_analysis/src/queries.rs b/crates/ra_analysis/src/queries.rs deleted file mode 100644 index 062a2f420..000000000 --- a/crates/ra_analysis/src/queries.rs +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | use std::sync::Arc; | ||
2 | use ra_syntax::File; | ||
3 | use ra_editor::LineIndex; | ||
4 | use { | ||
5 | FileId, | ||
6 | db::{Query, QueryCtx, QueryRegistry}, | ||
7 | symbol_index::SymbolIndex, | ||
8 | }; | ||
9 | |||
10 | pub(crate) use db::{file_text, file_set}; | ||
11 | |||
12 | pub(crate) fn file_syntax(ctx: QueryCtx, file_id: FileId) -> File { | ||
13 | (&*ctx.get(FILE_SYNTAX, file_id)).clone() | ||
14 | } | ||
15 | pub(crate) fn file_lines(ctx: QueryCtx, file_id: FileId) -> Arc<LineIndex> { | ||
16 | ctx.get(FILE_LINES, file_id) | ||
17 | } | ||
18 | pub(crate) fn file_symbols(ctx: QueryCtx, file_id: FileId) -> Arc<SymbolIndex> { | ||
19 | ctx.get(FILE_SYMBOLS, file_id) | ||
20 | } | ||
21 | |||
22 | const FILE_SYNTAX: Query<FileId, File> = Query(16, |ctx, file_id: &FileId| { | ||
23 | let text = file_text(ctx, *file_id); | ||
24 | File::parse(&*text) | ||
25 | }); | ||
26 | const FILE_LINES: Query<FileId, LineIndex> = Query(17, |ctx, file_id: &FileId| { | ||
27 | let text = file_text(ctx, *file_id); | ||
28 | LineIndex::new(&*text) | ||
29 | }); | ||
30 | const FILE_SYMBOLS: Query<FileId, SymbolIndex> = Query(18, |ctx, file_id: &FileId| { | ||
31 | let syntax = file_syntax(ctx, *file_id); | ||
32 | SymbolIndex::for_file(*file_id, syntax) | ||
33 | }); | ||
34 | |||
35 | pub(crate) fn register_queries(reg: &mut QueryRegistry) { | ||
36 | reg.add(FILE_SYNTAX, "FILE_SYNTAX"); | ||
37 | reg.add(FILE_LINES, "FILE_LINES"); | ||
38 | reg.add(FILE_SYMBOLS, "FILE_SYMBOLS"); | ||
39 | } | ||
diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs index 32a8c5bd0..76bcecd38 100644 --- a/crates/ra_analysis/src/roots.rs +++ b/crates/ra_analysis/src/roots.rs | |||
@@ -5,16 +5,18 @@ use std::{ | |||
5 | 5 | ||
6 | use once_cell::sync::OnceCell; | 6 | use once_cell::sync::OnceCell; |
7 | use rayon::prelude::*; | 7 | use rayon::prelude::*; |
8 | use rustc_hash::FxHashMap; | 8 | use salsa::Database; |
9 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
9 | use ra_editor::LineIndex; | 10 | use ra_editor::LineIndex; |
10 | use ra_syntax::File; | 11 | use ra_syntax::File; |
11 | 12 | ||
12 | use { | 13 | use crate::{ |
13 | FileId, | 14 | FileId, |
14 | imp::FileResolverImp, | 15 | imp::FileResolverImp, |
15 | symbol_index::SymbolIndex, | 16 | symbol_index::SymbolIndex, |
16 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | 17 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, |
17 | db::Db, | 18 | db::{self, FilesDatabase, SyntaxDatabase}, |
19 | module_map::ModulesDatabase, | ||
18 | }; | 20 | }; |
19 | 21 | ||
20 | pub(crate) trait SourceRoot { | 22 | pub(crate) trait SourceRoot { |
@@ -25,62 +27,68 @@ pub(crate) trait SourceRoot { | |||
25 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>); | 27 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>); |
26 | } | 28 | } |
27 | 29 | ||
28 | #[derive(Default, Debug)] | 30 | #[derive(Default, Debug, Clone)] |
29 | pub(crate) struct WritableSourceRoot { | 31 | pub(crate) struct WritableSourceRoot { |
30 | db: Db, | 32 | db: db::RootDatabase, |
31 | } | 33 | } |
32 | 34 | ||
33 | impl WritableSourceRoot { | 35 | impl WritableSourceRoot { |
34 | pub fn apply_changes( | 36 | pub fn apply_changes( |
35 | &self, | 37 | &mut self, |
36 | changes: &mut dyn Iterator<Item=(FileId, Option<String>)>, | 38 | changes: &mut dyn Iterator<Item=(FileId, Option<String>)>, |
37 | file_resolver: Option<FileResolverImp>, | 39 | file_resolver: Option<FileResolverImp>, |
38 | ) -> WritableSourceRoot { | 40 | ) { |
39 | let resolver_changed = file_resolver.is_some(); | 41 | let mut changed = FxHashSet::default(); |
40 | let mut changed_files = Vec::new(); | 42 | let mut removed = FxHashSet::default(); |
41 | let mut new_state = self.db.state().clone(); | ||
42 | |||
43 | for (file_id, text) in changes { | 43 | for (file_id, text) in changes { |
44 | changed_files.push(file_id); | ||
45 | match text { | 44 | match text { |
46 | Some(text) => { | ||
47 | new_state.file_map.insert(file_id, Arc::new(text)); | ||
48 | }, | ||
49 | None => { | 45 | None => { |
50 | new_state.file_map.remove(&file_id); | 46 | removed.insert(file_id); |
47 | } | ||
48 | Some(text) => { | ||
49 | self.db.query(db::FileTextQuery) | ||
50 | .set(file_id, Arc::new(text)); | ||
51 | changed.insert(file_id); | ||
51 | } | 52 | } |
52 | } | 53 | } |
53 | } | 54 | } |
54 | if let Some(file_resolver) = file_resolver { | 55 | let file_set = self.db.file_set(()); |
55 | new_state.file_resolver = file_resolver | 56 | let mut files: FxHashSet<FileId> = file_set |
56 | } | 57 | .files |
57 | WritableSourceRoot { | 58 | .clone(); |
58 | db: self.db.with_changes(new_state, &changed_files, resolver_changed) | 59 | for file_id in removed { |
60 | files.remove(&file_id); | ||
59 | } | 61 | } |
62 | files.extend(changed); | ||
63 | let resolver = file_resolver.unwrap_or_else(|| file_set.resolver.clone()); | ||
64 | self.db.query(db::FileSetQuery) | ||
65 | .set((), Arc::new(db::FileSet { files, resolver })); | ||
60 | } | 66 | } |
61 | } | 67 | } |
62 | 68 | ||
63 | impl SourceRoot for WritableSourceRoot { | 69 | impl SourceRoot for WritableSourceRoot { |
64 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor> { | 70 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor> { |
65 | self.db.make_query(::module_map::module_tree) | 71 | self.db.module_tree(()) |
66 | } | 72 | } |
67 | |||
68 | fn contains(&self, file_id: FileId) -> bool { | 73 | fn contains(&self, file_id: FileId) -> bool { |
69 | self.db.state().file_map.contains_key(&file_id) | 74 | self.db.file_set(()) |
75 | .files | ||
76 | .contains(&file_id) | ||
70 | } | 77 | } |
71 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { | 78 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { |
72 | self.db.make_query(|ctx| ::queries::file_lines(ctx, file_id)) | 79 | self.db.file_lines(file_id) |
73 | } | 80 | } |
74 | fn syntax(&self, file_id: FileId) -> File { | 81 | fn syntax(&self, file_id: FileId) -> File { |
75 | self.db.make_query(|ctx| ::queries::file_syntax(ctx, file_id)) | 82 | self.db.file_syntax(file_id) |
76 | } | 83 | } |
77 | fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) { | 84 | fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) { |
78 | self.db.make_query(|ctx| { | 85 | let db = &self.db; |
79 | let file_set = ::queries::file_set(ctx); | 86 | let symbols = db.file_set(()); |
80 | let syms = file_set.0.iter() | 87 | let symbols = symbols |
81 | .map(|file_id| ::queries::file_symbols(ctx, *file_id)); | 88 | .files |
82 | acc.extend(syms); | 89 | .iter() |
83 | }); | 90 | .map(|&file_id| db.file_symbols(file_id)); |
91 | acc.extend(symbols); | ||
84 | } | 92 | } |
85 | } | 93 | } |
86 | 94 | ||
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index ffbb6a29f..54672fde4 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::{ | |||
9 | }; | 9 | }; |
10 | use fst::{self, Streamer}; | 10 | use fst::{self, Streamer}; |
11 | use rayon::prelude::*; | 11 | use rayon::prelude::*; |
12 | use {Query, FileId, JobToken}; | 12 | use crate::{Query, FileId, JobToken}; |
13 | 13 | ||
14 | #[derive(Debug)] | 14 | #[derive(Debug)] |
15 | pub(crate) struct SymbolIndex { | 15 | pub(crate) struct SymbolIndex { |
@@ -17,6 +17,15 @@ pub(crate) struct SymbolIndex { | |||
17 | map: fst::Map, | 17 | map: fst::Map, |
18 | } | 18 | } |
19 | 19 | ||
20 | impl PartialEq for SymbolIndex { | ||
21 | fn eq(&self, other: &SymbolIndex) -> bool { | ||
22 | self.symbols == other.symbols | ||
23 | } | ||
24 | } | ||
25 | |||
26 | impl Eq for SymbolIndex { | ||
27 | } | ||
28 | |||
20 | impl Hash for SymbolIndex { | 29 | impl Hash for SymbolIndex { |
21 | fn hash<H: Hasher>(&self, hasher: &mut H) { | 30 | fn hash<H: Hasher>(&self, hasher: &mut H) { |
22 | self.symbols.hash(hasher) | 31 | self.symbols.hash(hasher) |
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index a886cd0ff..2d3679fa9 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | extern crate relative_path; | 1 | extern crate relative_path; |
2 | extern crate ra_analysis; | 2 | extern crate ra_analysis; |
3 | extern crate rustc_hash; | 3 | extern crate rustc_hash; |
4 | extern crate ra_editor; | ||
5 | extern crate ra_syntax; | ||
4 | extern crate test_utils; | 6 | extern crate test_utils; |
5 | 7 | ||
6 | use std::{ | 8 | use std::{ |
@@ -9,8 +11,8 @@ use std::{ | |||
9 | 11 | ||
10 | use rustc_hash::FxHashMap; | 12 | use rustc_hash::FxHashMap; |
11 | use relative_path::{RelativePath, RelativePathBuf}; | 13 | use relative_path::{RelativePath, RelativePathBuf}; |
12 | use ra_analysis::{Analysis, AnalysisHost, FileId, FileResolver, JobHandle, CrateGraph, CrateId}; | 14 | use ra_analysis::{Analysis, AnalysisHost, FileId, FileResolver, JobHandle, CrateGraph, CrateId, FnDescriptor}; |
13 | use test_utils::assert_eq_dbg; | 15 | use test_utils::{assert_eq_dbg, extract_offset}; |
14 | 16 | ||
15 | #[derive(Debug)] | 17 | #[derive(Debug)] |
16 | struct FileMap(Vec<(FileId, RelativePathBuf)>); | 18 | struct FileMap(Vec<(FileId, RelativePathBuf)>); |
@@ -39,7 +41,7 @@ impl FileResolver for FileMap { | |||
39 | } | 41 | } |
40 | } | 42 | } |
41 | 43 | ||
42 | fn analysis_host(files: &'static [(&'static str, &'static str)]) -> AnalysisHost { | 44 | fn analysis_host(files: &[(&str, &str)]) -> AnalysisHost { |
43 | let mut host = AnalysisHost::new(); | 45 | let mut host = AnalysisHost::new(); |
44 | let mut file_map = Vec::new(); | 46 | let mut file_map = Vec::new(); |
45 | for (id, &(path, contents)) in files.iter().enumerate() { | 47 | for (id, &(path, contents)) in files.iter().enumerate() { |
@@ -53,10 +55,20 @@ fn analysis_host(files: &'static [(&'static str, &'static str)]) -> AnalysisHost | |||
53 | host | 55 | host |
54 | } | 56 | } |
55 | 57 | ||
56 | fn analysis(files: &'static [(&'static str, &'static str)]) -> Analysis { | 58 | fn analysis(files: &[(&str, &str)]) -> Analysis { |
57 | analysis_host(files).analysis() | 59 | analysis_host(files).analysis() |
58 | } | 60 | } |
59 | 61 | ||
62 | fn get_signature(text: &str) -> (FnDescriptor, Option<usize>) { | ||
63 | let (offset, code) = extract_offset(text); | ||
64 | let code = code.as_str(); | ||
65 | |||
66 | let (_handle, token) = JobHandle::new(); | ||
67 | let snap = analysis(&[("/lib.rs", code)]); | ||
68 | |||
69 | snap.resolve_callable(FileId(1), offset, &token).unwrap() | ||
70 | } | ||
71 | |||
60 | #[test] | 72 | #[test] |
61 | fn test_resolve_module() { | 73 | fn test_resolve_module() { |
62 | let snap = analysis(&[ | 74 | let snap = analysis(&[ |
@@ -145,3 +157,85 @@ fn test_resolve_crate_root() { | |||
145 | vec![CrateId(1)], | 157 | vec![CrateId(1)], |
146 | ); | 158 | ); |
147 | } | 159 | } |
160 | |||
161 | #[test] | ||
162 | fn test_fn_signature_two_args_first() { | ||
163 | let (desc, param) = get_signature( | ||
164 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} | ||
165 | fn bar() { foo(<|>3, ); }"#); | ||
166 | |||
167 | assert_eq!(desc.name, "foo".to_string()); | ||
168 | assert_eq!(desc.params, vec!("x".to_string(),"y".to_string())); | ||
169 | assert_eq!(desc.ret_type, Some("-> u32".into())); | ||
170 | assert_eq!(param, Some(0)); | ||
171 | } | ||
172 | |||
173 | #[test] | ||
174 | fn test_fn_signature_two_args_second() { | ||
175 | let (desc, param) = get_signature( | ||
176 | r#"fn foo(x: u32, y: u32) -> u32 {x + y} | ||
177 | fn bar() { foo(3, <|>); }"#); | ||
178 | |||
179 | assert_eq!(desc.name, "foo".to_string()); | ||
180 | assert_eq!(desc.params, vec!("x".to_string(),"y".to_string())); | ||
181 | assert_eq!(desc.ret_type, Some("-> u32".into())); | ||
182 | assert_eq!(param, Some(1)); | ||
183 | } | ||
184 | |||
185 | #[test] | ||
186 | fn test_fn_signature_for_impl() { | ||
187 | let (desc, param) = get_signature( | ||
188 | r#"struct F; impl F { pub fn new() { F{}} } | ||
189 | fn bar() {let _ : F = F::new(<|>);}"#); | ||
190 | |||
191 | assert_eq!(desc.name, "new".to_string()); | ||
192 | assert_eq!(desc.params, Vec::<String>::new()); | ||
193 | assert_eq!(desc.ret_type, None); | ||
194 | assert_eq!(param, None); | ||
195 | } | ||
196 | |||
197 | #[test] | ||
198 | fn test_fn_signature_for_method_self() { | ||
199 | let (desc, param) = get_signature( | ||
200 | r#"struct F; | ||
201 | impl F { | ||
202 | pub fn new() -> F{ | ||
203 | F{} | ||
204 | } | ||
205 | |||
206 | pub fn do_it(&self) {} | ||
207 | } | ||
208 | |||
209 | fn bar() { | ||
210 | let f : F = F::new(); | ||
211 | f.do_it(<|>); | ||
212 | }"#); | ||
213 | |||
214 | assert_eq!(desc.name, "do_it".to_string()); | ||
215 | assert_eq!(desc.params, vec!["&self".to_string()]); | ||
216 | assert_eq!(desc.ret_type, None); | ||
217 | assert_eq!(param, None); | ||
218 | } | ||
219 | |||
220 | #[test] | ||
221 | fn test_fn_signature_for_method_with_arg() { | ||
222 | let (desc, param) = get_signature( | ||
223 | r#"struct F; | ||
224 | impl F { | ||
225 | pub fn new() -> F{ | ||
226 | F{} | ||
227 | } | ||
228 | |||
229 | pub fn do_it(&self, x: i32) {} | ||
230 | } | ||
231 | |||
232 | fn bar() { | ||
233 | let f : F = F::new(); | ||
234 | f.do_it(<|>); | ||
235 | }"#); | ||
236 | |||
237 | assert_eq!(desc.name, "do_it".to_string()); | ||
238 | assert_eq!(desc.params, vec!["&self".to_string(), "x".to_string()]); | ||
239 | assert_eq!(desc.ret_type, None); | ||
240 | assert_eq!(param, Some(1)); | ||
241 | } | ||
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml index 5e7bf3ed4..0b8d6f3dd 100644 --- a/crates/ra_cli/Cargo.toml +++ b/crates/ra_cli/Cargo.toml | |||
@@ -1,4 +1,5 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | ||
2 | name = "ra_cli" | 3 | name = "ra_cli" |
3 | version = "0.1.0" | 4 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
diff --git a/crates/ra_editor/Cargo.toml b/crates/ra_editor/Cargo.toml index 91cefc8d7..7791da156 100644 --- a/crates/ra_editor/Cargo.toml +++ b/crates/ra_editor/Cargo.toml | |||
@@ -1,4 +1,5 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | ||
2 | name = "ra_editor" | 3 | name = "ra_editor" |
3 | version = "0.1.0" | 4 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs index 216d592ff..7b0a48c81 100644 --- a/crates/ra_editor/src/code_actions.rs +++ b/crates/ra_editor/src/code_actions.rs | |||
@@ -11,7 +11,7 @@ use ra_syntax::{ | |||
11 | }, | 11 | }, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use {EditBuilder, Edit, find_node_at_offset}; | 14 | use crate::{EditBuilder, Edit, find_node_at_offset}; |
15 | 15 | ||
16 | #[derive(Debug)] | 16 | #[derive(Debug)] |
17 | pub struct LocalEdit { | 17 | pub struct LocalEdit { |
@@ -136,7 +136,7 @@ fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<Synta | |||
136 | #[cfg(test)] | 136 | #[cfg(test)] |
137 | mod tests { | 137 | mod tests { |
138 | use super::*; | 138 | use super::*; |
139 | use test_utils::{check_action, check_action_range}; | 139 | use crate::test_utils::{check_action, check_action_range}; |
140 | 140 | ||
141 | #[test] | 141 | #[test] |
142 | fn test_swap_comma() { | 142 | fn test_swap_comma() { |
diff --git a/crates/ra_editor/src/completion.rs b/crates/ra_editor/src/completion.rs index 20b8484b3..b6095dca9 100644 --- a/crates/ra_editor/src/completion.rs +++ b/crates/ra_editor/src/completion.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::{ | |||
9 | text_utils::is_subrange, | 9 | text_utils::is_subrange, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use { | 12 | use crate::{ |
13 | AtomEdit, find_node_at_offset, | 13 | AtomEdit, find_node_at_offset, |
14 | scope::{FnScopes, ModuleScope}, | 14 | scope::{FnScopes, ModuleScope}, |
15 | }; | 15 | }; |
diff --git a/crates/ra_editor/src/edit.rs b/crates/ra_editor/src/edit.rs index 2839ac20a..46e687319 100644 --- a/crates/ra_editor/src/edit.rs +++ b/crates/ra_editor/src/edit.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use {TextRange, TextUnit}; | 1 | use crate::{TextRange, TextUnit}; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | AtomEdit, | 3 | AtomEdit, |
4 | text_utils::contains_offset_nonstrict, | 4 | text_utils::contains_offset_nonstrict, |
diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs index 3aabd54ae..a1699d449 100644 --- a/crates/ra_editor/src/folding_ranges.rs +++ b/crates/ra_editor/src/folding_ranges.rs | |||
@@ -1,8 +1,10 @@ | |||
1 | use rustc_hash::FxHashSet; | 1 | use rustc_hash::FxHashSet; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | ast, | ||
5 | AstNode, | ||
4 | File, TextRange, SyntaxNodeRef, | 6 | File, TextRange, SyntaxNodeRef, |
5 | SyntaxKind, | 7 | SyntaxKind::{self, *}, |
6 | Direction, | 8 | Direction, |
7 | }; | 9 | }; |
8 | 10 | ||
@@ -20,67 +22,97 @@ pub struct Fold { | |||
20 | 22 | ||
21 | pub fn folding_ranges(file: &File) -> Vec<Fold> { | 23 | pub fn folding_ranges(file: &File) -> Vec<Fold> { |
22 | let mut res = vec![]; | 24 | let mut res = vec![]; |
23 | let mut visited = FxHashSet::default(); | 25 | let mut visited_comments = FxHashSet::default(); |
24 | 26 | ||
25 | for node in file.syntax().descendants() { | 27 | for node in file.syntax().descendants() { |
26 | if visited.contains(&node) { | 28 | // Fold items that span multiple lines |
29 | if let Some(kind) = fold_kind(node.kind()) { | ||
30 | if has_newline(node) { | ||
31 | res.push(Fold { range: node.range(), kind }); | ||
32 | } | ||
33 | } | ||
34 | |||
35 | // Also fold groups of comments | ||
36 | if visited_comments.contains(&node) { | ||
27 | continue; | 37 | continue; |
28 | } | 38 | } |
39 | if node.kind() == COMMENT { | ||
40 | contiguous_range_for_comment(node, &mut visited_comments) | ||
41 | .map(|range| res.push(Fold { range, kind: FoldKind::Comment })); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | res | ||
46 | } | ||
29 | 47 | ||
30 | let range_and_kind = match node.kind() { | 48 | fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> { |
31 | SyntaxKind::COMMENT => ( | 49 | match kind { |
32 | contiguous_range_for(SyntaxKind::COMMENT, node, &mut visited), | 50 | COMMENT => Some(FoldKind::Comment), |
33 | Some(FoldKind::Comment), | 51 | USE_ITEM => Some(FoldKind::Imports), |
34 | ), | 52 | _ => None |
35 | SyntaxKind::USE_ITEM => ( | 53 | } |
36 | contiguous_range_for(SyntaxKind::USE_ITEM, node, &mut visited), | 54 | } |
37 | Some(FoldKind::Imports), | 55 | |
38 | ), | 56 | fn has_newline( |
39 | _ => (None, None), | 57 | node: SyntaxNodeRef, |
40 | }; | 58 | ) -> bool { |
41 | 59 | for descendant in node.descendants() { | |
42 | match range_and_kind { | 60 | if let Some(ws) = ast::Whitespace::cast(descendant) { |
43 | (Some(range), Some(kind)) => { | 61 | if ws.has_newlines() { |
44 | res.push(Fold { | 62 | return true; |
45 | range: range, | 63 | } |
46 | kind: kind | 64 | } else if let Some(comment) = ast::Comment::cast(descendant) { |
47 | }); | 65 | if comment.has_newlines() { |
66 | return true; | ||
48 | } | 67 | } |
49 | _ => {} | ||
50 | } | 68 | } |
51 | } | 69 | } |
52 | 70 | ||
53 | res | 71 | false |
54 | } | 72 | } |
55 | 73 | ||
56 | fn contiguous_range_for<'a>( | 74 | fn contiguous_range_for_comment<'a>( |
57 | kind: SyntaxKind, | 75 | first: SyntaxNodeRef<'a>, |
58 | node: SyntaxNodeRef<'a>, | ||
59 | visited: &mut FxHashSet<SyntaxNodeRef<'a>>, | 76 | visited: &mut FxHashSet<SyntaxNodeRef<'a>>, |
60 | ) -> Option<TextRange> { | 77 | ) -> Option<TextRange> { |
61 | visited.insert(node); | 78 | visited.insert(first); |
62 | 79 | ||
63 | let left = node; | 80 | // Only fold comments of the same flavor |
64 | let mut right = node; | 81 | let group_flavor = ast::Comment::cast(first)?.flavor(); |
65 | for node in node.siblings(Direction::Next) { | 82 | |
66 | visited.insert(node); | 83 | let mut last = first; |
67 | match node.kind() { | 84 | for node in first.siblings(Direction::Next) { |
68 | SyntaxKind::WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (), | 85 | if let Some(ws) = ast::Whitespace::cast(node) { |
69 | k => { | 86 | // There is a blank line, which means the group ends here |
70 | if k == kind { | 87 | if ws.count_newlines_lazy().take(2).count() == 2 { |
71 | right = node | 88 | break; |
72 | } else { | 89 | } |
73 | break; | 90 | |
74 | } | 91 | // Ignore whitespace without blank lines |
92 | continue; | ||
93 | } | ||
94 | |||
95 | match ast::Comment::cast(node) { | ||
96 | Some(next_comment) if next_comment.flavor() == group_flavor => { | ||
97 | visited.insert(node); | ||
98 | last = node; | ||
99 | } | ||
100 | // The comment group ends because either: | ||
101 | // * An element of a different kind was reached | ||
102 | // * A comment of a different flavor was reached | ||
103 | _ => { | ||
104 | break | ||
75 | } | 105 | } |
76 | } | 106 | } |
77 | } | 107 | } |
78 | if left != right { | 108 | |
109 | if first != last { | ||
79 | Some(TextRange::from_to( | 110 | Some(TextRange::from_to( |
80 | left.range().start(), | 111 | first.range().start(), |
81 | right.range().end(), | 112 | last.range().end(), |
82 | )) | 113 | )) |
83 | } else { | 114 | } else { |
115 | // The group consists of only one element, therefore it cannot be folded | ||
84 | None | 116 | None |
85 | } | 117 | } |
86 | } | 118 | } |
@@ -88,52 +120,65 @@ fn contiguous_range_for<'a>( | |||
88 | #[cfg(test)] | 120 | #[cfg(test)] |
89 | mod tests { | 121 | mod tests { |
90 | use super::*; | 122 | use super::*; |
123 | use test_utils::extract_ranges; | ||
124 | |||
125 | fn do_check(text: &str, fold_kinds: &[FoldKind]) { | ||
126 | let (ranges, text) = extract_ranges(text); | ||
127 | let file = File::parse(&text); | ||
128 | let folds = folding_ranges(&file); | ||
129 | |||
130 | assert_eq!(folds.len(), ranges.len()); | ||
131 | for ((fold, range), fold_kind) in folds.into_iter().zip(ranges.into_iter()).zip(fold_kinds.into_iter()) { | ||
132 | assert_eq!(fold.range.start(), range.start()); | ||
133 | assert_eq!(fold.range.end(), range.end()); | ||
134 | assert_eq!(&fold.kind, fold_kind); | ||
135 | } | ||
136 | } | ||
91 | 137 | ||
92 | #[test] | 138 | #[test] |
93 | fn test_fold_comments() { | 139 | fn test_fold_comments() { |
94 | let text = r#" | 140 | let text = r#" |
95 | // Hello | 141 | <|>// Hello |
96 | // this is a multiline | 142 | // this is a multiline |
97 | // comment | 143 | // comment |
98 | // | 144 | //<|> |
99 | 145 | ||
100 | // But this is not | 146 | // But this is not |
101 | 147 | ||
102 | fn main() { | 148 | fn main() { |
103 | // We should | 149 | <|>// We should |
104 | // also | 150 | // also |
105 | // fold | 151 | // fold |
106 | // this one. | 152 | // this one.<|> |
153 | <|>//! But this one is different | ||
154 | //! because it has another flavor<|> | ||
155 | <|>/* As does this | ||
156 | multiline comment */<|> | ||
107 | }"#; | 157 | }"#; |
108 | 158 | ||
109 | let file = File::parse(&text); | 159 | let fold_kinds = &[ |
110 | let folds = folding_ranges(&file); | 160 | FoldKind::Comment, |
111 | assert_eq!(folds.len(), 2); | 161 | FoldKind::Comment, |
112 | assert_eq!(folds[0].range.start(), 1.into()); | 162 | FoldKind::Comment, |
113 | assert_eq!(folds[0].range.end(), 46.into()); | 163 | FoldKind::Comment, |
114 | assert_eq!(folds[0].kind, FoldKind::Comment); | 164 | ]; |
115 | 165 | do_check(text, fold_kinds); | |
116 | assert_eq!(folds[1].range.start(), 84.into()); | ||
117 | assert_eq!(folds[1].range.end(), 137.into()); | ||
118 | assert_eq!(folds[1].kind, FoldKind::Comment); | ||
119 | } | 166 | } |
120 | 167 | ||
121 | #[test] | 168 | #[test] |
122 | fn test_fold_imports() { | 169 | fn test_fold_imports() { |
123 | let text = r#" | 170 | let text = r#" |
124 | use std::str; | 171 | <|>use std::{ |
125 | use std::vec; | 172 | str, |
126 | use std::io as iop; | 173 | vec, |
174 | io as iop | ||
175 | };<|> | ||
127 | 176 | ||
128 | fn main() { | 177 | fn main() { |
129 | }"#; | 178 | }"#; |
130 | 179 | ||
131 | let file = File::parse(&text); | 180 | let folds = &[FoldKind::Imports]; |
132 | let folds = folding_ranges(&file); | 181 | do_check(text, folds); |
133 | assert_eq!(folds.len(), 1); | ||
134 | assert_eq!(folds[0].range.start(), 1.into()); | ||
135 | assert_eq!(folds[0].range.end(), 48.into()); | ||
136 | assert_eq!(folds[0].kind, FoldKind::Imports); | ||
137 | } | 182 | } |
138 | 183 | ||
139 | 184 | ||
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index 710afc65d..bd61fd191 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs | |||
@@ -164,7 +164,7 @@ pub fn resolve_local_name(file: &File, offset: TextUnit, name_ref: ast::NameRef) | |||
164 | #[cfg(test)] | 164 | #[cfg(test)] |
165 | mod tests { | 165 | mod tests { |
166 | use super::*; | 166 | use super::*; |
167 | use test_utils::{assert_eq_dbg, extract_offset, add_cursor}; | 167 | use crate::test_utils::{assert_eq_dbg, extract_offset, add_cursor}; |
168 | 168 | ||
169 | #[test] | 169 | #[test] |
170 | fn test_highlighting() { | 170 | fn test_highlighting() { |
diff --git a/crates/ra_editor/src/line_index.rs b/crates/ra_editor/src/line_index.rs index 9cd8da3a8..95d64b8a8 100644 --- a/crates/ra_editor/src/line_index.rs +++ b/crates/ra_editor/src/line_index.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use superslice::Ext; | 1 | use superslice::Ext; |
2 | use ::TextUnit; | 2 | use crate::TextUnit; |
3 | 3 | ||
4 | #[derive(Clone, Debug, Hash)] | 4 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
5 | pub struct LineIndex { | 5 | pub struct LineIndex { |
6 | newlines: Vec<TextUnit>, | 6 | newlines: Vec<TextUnit>, |
7 | } | 7 | } |
diff --git a/crates/ra_editor/src/scope/fn_scope.rs b/crates/ra_editor/src/scope/fn_scope.rs index 9a48bda02..99d698b60 100644 --- a/crates/ra_editor/src/scope/fn_scope.rs +++ b/crates/ra_editor/src/scope/fn_scope.rs | |||
@@ -174,7 +174,7 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { | |||
174 | } | 174 | } |
175 | } | 175 | } |
176 | ast::Expr::LambdaExpr(e) => { | 176 | ast::Expr::LambdaExpr(e) => { |
177 | let mut scope = scopes.new_scope(scope); | 177 | let scope = scopes.new_scope(scope); |
178 | scopes.add_params_bindings(scope, e.param_list()); | 178 | scopes.add_params_bindings(scope, e.param_list()); |
179 | if let Some(body) = e.body() { | 179 | if let Some(body) = e.body() { |
180 | scopes.set_scope(body.syntax(), scope); | 180 | scopes.set_scope(body.syntax(), scope); |
@@ -256,7 +256,7 @@ pub fn resolve_local_name<'a>(name_ref: ast::NameRef, scopes: &'a FnScopes) -> O | |||
256 | mod tests { | 256 | mod tests { |
257 | use super::*; | 257 | use super::*; |
258 | use ra_syntax::File; | 258 | use ra_syntax::File; |
259 | use {find_node_at_offset, test_utils::extract_offset}; | 259 | use crate::{find_node_at_offset, test_utils::extract_offset}; |
260 | 260 | ||
261 | fn do_check(code: &str, expected: &[&str]) { | 261 | fn do_check(code: &str, expected: &[&str]) { |
262 | let (off, code) = extract_offset(code); | 262 | let (off, code) = extract_offset(code); |
diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs index e5cc5ca28..d9e4b2df7 100644 --- a/crates/ra_editor/src/symbols.rs +++ b/crates/ra_editor/src/symbols.rs | |||
@@ -6,7 +6,7 @@ use ra_syntax::{ | |||
6 | walk::{walk, WalkEvent}, | 6 | walk::{walk, WalkEvent}, |
7 | }, | 7 | }, |
8 | }; | 8 | }; |
9 | use TextRange; | 9 | use crate::TextRange; |
10 | 10 | ||
11 | #[derive(Debug, Clone)] | 11 | #[derive(Debug, Clone)] |
12 | pub struct StructureNode { | 12 | pub struct StructureNode { |
@@ -17,7 +17,7 @@ pub struct StructureNode { | |||
17 | pub kind: SyntaxKind, | 17 | pub kind: SyntaxKind, |
18 | } | 18 | } |
19 | 19 | ||
20 | #[derive(Debug, Clone, Hash)] | 20 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
21 | pub struct FileSymbol { | 21 | pub struct FileSymbol { |
22 | pub name: SmolStr, | 22 | pub name: SmolStr, |
23 | pub node_range: TextRange, | 23 | pub node_range: TextRange, |
diff --git a/crates/ra_editor/src/test_utils.rs b/crates/ra_editor/src/test_utils.rs index c4ea4db6c..49eb530d5 100644 --- a/crates/ra_editor/src/test_utils.rs +++ b/crates/ra_editor/src/test_utils.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use ra_syntax::{File, TextUnit, TextRange}; | 1 | use ra_syntax::{File, TextUnit, TextRange}; |
2 | pub use _test_utils::*; | 2 | pub use crate::_test_utils::*; |
3 | use LocalEdit; | 3 | use crate::LocalEdit; |
4 | 4 | ||
5 | pub fn check_action<F: Fn(&File, TextUnit) -> Option<LocalEdit>> ( | 5 | pub fn check_action<F: Fn(&File, TextUnit) -> Option<LocalEdit>> ( |
6 | before: &str, | 6 | before: &str, |
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index 1dc658f9b..542b9e10b 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ | |||
10 | SyntaxKind::*, | 10 | SyntaxKind::*, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | use {LocalEdit, EditBuilder, find_node_at_offset}; | 13 | use crate::{LocalEdit, EditBuilder, find_node_at_offset}; |
14 | 14 | ||
15 | pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { | 15 | pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { |
16 | let range = if range.is_empty() { | 16 | let range = if range.is_empty() { |
@@ -244,7 +244,7 @@ fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str { | |||
244 | #[cfg(test)] | 244 | #[cfg(test)] |
245 | mod tests { | 245 | mod tests { |
246 | use super::*; | 246 | use super::*; |
247 | use test_utils::{check_action, extract_range, extract_offset, add_cursor}; | 247 | use crate::test_utils::{check_action, extract_range, extract_offset, add_cursor}; |
248 | 248 | ||
249 | fn check_join_lines(before: &str, after: &str) { | 249 | fn check_join_lines(before: &str, after: &str) { |
250 | check_action(before, after, |file, offset| { | 250 | check_action(before, after, |file, offset| { |
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 1fe6b2ebe..2b3257117 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml | |||
@@ -1,4 +1,5 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | ||
2 | name = "ra_lsp_server" | 3 | name = "ra_lsp_server" |
3 | version = "0.1.0" | 4 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 3c628f29c..5598ec75f 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -7,6 +7,7 @@ use languageserver_types::{ | |||
7 | TextDocumentSyncKind, | 7 | TextDocumentSyncKind, |
8 | ExecuteCommandOptions, | 8 | ExecuteCommandOptions, |
9 | CompletionOptions, | 9 | CompletionOptions, |
10 | SignatureHelpOptions, | ||
10 | DocumentOnTypeFormattingOptions, | 11 | DocumentOnTypeFormattingOptions, |
11 | }; | 12 | }; |
12 | 13 | ||
@@ -26,7 +27,9 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
26 | resolve_provider: None, | 27 | resolve_provider: None, |
27 | trigger_characters: None, | 28 | trigger_characters: None, |
28 | }), | 29 | }), |
29 | signature_help_provider: None, | 30 | signature_help_provider: Some(SignatureHelpOptions { |
31 | trigger_characters: Some(vec!["(".to_string(), ",".to_string()]) | ||
32 | }), | ||
30 | definition_provider: Some(true), | 33 | definition_provider: Some(true), |
31 | type_definition_provider: None, | 34 | type_definition_provider: None, |
32 | implementation_provider: None, | 35 | implementation_provider: None, |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 08a656569..a75b160c5 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -7,7 +7,7 @@ use ra_editor::{LineIndex, LineCol, Edit, AtomEdit}; | |||
7 | use ra_syntax::{SyntaxKind, TextUnit, TextRange}; | 7 | use ra_syntax::{SyntaxKind, TextUnit, TextRange}; |
8 | use ra_analysis::{FileId, SourceChange, SourceFileEdit, FileSystemEdit}; | 8 | use ra_analysis::{FileId, SourceChange, SourceFileEdit, FileSystemEdit}; |
9 | 9 | ||
10 | use { | 10 | use crate::{ |
11 | Result, | 11 | Result, |
12 | server_world::ServerWorld, | 12 | server_world::ServerWorld, |
13 | req, | 13 | req, |
@@ -299,7 +299,7 @@ pub fn to_location( | |||
299 | Ok(loc) | 299 | Ok(loc) |
300 | } | 300 | } |
301 | 301 | ||
302 | pub trait MapConvWith<'a>: Sized { | 302 | pub trait MapConvWith<'a>: Sized + 'a { |
303 | type Ctx; | 303 | type Ctx; |
304 | type Output; | 304 | type Output; |
305 | 305 | ||
@@ -309,7 +309,7 @@ pub trait MapConvWith<'a>: Sized { | |||
309 | } | 309 | } |
310 | 310 | ||
311 | impl<'a, I> MapConvWith<'a> for I | 311 | impl<'a, I> MapConvWith<'a> for I |
312 | where I: Iterator, | 312 | where I: Iterator + 'a, |
313 | I::Item: ConvWith | 313 | I::Item: ConvWith |
314 | { | 314 | { |
315 | type Ctx = <I::Item as ConvWith>::Ctx; | 315 | type Ctx = <I::Item as ConvWith>::Ctx; |
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 60652d55e..7224b1476 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -34,5 +34,7 @@ mod project_model; | |||
34 | pub mod thread_watcher; | 34 | pub mod thread_watcher; |
35 | 35 | ||
36 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 36 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; |
37 | pub use caps::server_capabilities; | 37 | pub use crate::{ |
38 | pub use main_loop::main_loop; | 38 | main_loop::main_loop, |
39 | caps::server_capabilities, | ||
40 | }; | ||
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index ab8be15e9..5acb39b60 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -13,7 +13,7 @@ use ra_syntax::{ | |||
13 | text_utils::contains_offset_nonstrict | 13 | text_utils::contains_offset_nonstrict |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use ::{ | 16 | use crate::{ |
17 | req::{self, Decoration}, Result, | 17 | req::{self, Decoration}, Result, |
18 | conv::{Conv, ConvWith, TryConvWith, MapConvWith, to_location}, | 18 | conv::{Conv, ConvWith, TryConvWith, MapConvWith, to_location}, |
19 | server_world::ServerWorld, | 19 | server_world::ServerWorld, |
@@ -411,6 +411,42 @@ pub fn handle_folding_range( | |||
411 | Ok(res) | 411 | Ok(res) |
412 | } | 412 | } |
413 | 413 | ||
414 | pub fn handle_signature_help( | ||
415 | world: ServerWorld, | ||
416 | params: req::TextDocumentPositionParams, | ||
417 | token: JobToken, | ||
418 | ) -> Result<Option<req::SignatureHelp>> { | ||
419 | use languageserver_types::{ParameterInformation, SignatureInformation}; | ||
420 | |||
421 | let file_id = params.text_document.try_conv_with(&world)?; | ||
422 | let line_index = world.analysis().file_line_index(file_id); | ||
423 | let offset = params.position.conv_with(&line_index); | ||
424 | |||
425 | if let Some((descriptor, active_param)) = world.analysis().resolve_callable(file_id, offset, &token) { | ||
426 | let parameters : Vec<ParameterInformation> = | ||
427 | descriptor.params.iter().map(|param| | ||
428 | ParameterInformation { | ||
429 | label: param.clone(), | ||
430 | documentation: None | ||
431 | } | ||
432 | ).collect(); | ||
433 | |||
434 | let sig_info = SignatureInformation { | ||
435 | label: descriptor.label, | ||
436 | documentation: None, | ||
437 | parameters: Some(parameters) | ||
438 | }; | ||
439 | |||
440 | Ok(Some(req::SignatureHelp { | ||
441 | signatures: vec![sig_info], | ||
442 | active_signature: Some(0), | ||
443 | active_parameter: active_param.map(|a| a as u64) | ||
444 | })) | ||
445 | } else { | ||
446 | Ok(None) | ||
447 | } | ||
448 | } | ||
449 | |||
414 | pub fn handle_code_action( | 450 | pub fn handle_code_action( |
415 | world: ServerWorld, | 451 | world: ServerWorld, |
416 | params: req::CodeActionParams, | 452 | params: req::CodeActionParams, |
@@ -442,7 +478,7 @@ pub fn handle_code_action( | |||
442 | } | 478 | } |
443 | 479 | ||
444 | pub fn publish_diagnostics( | 480 | pub fn publish_diagnostics( |
445 | world: ServerWorld, | 481 | world: &ServerWorld, |
446 | file_id: FileId, | 482 | file_id: FileId, |
447 | ) -> Result<req::PublishDiagnosticsParams> { | 483 | ) -> Result<req::PublishDiagnosticsParams> { |
448 | let uri = world.file_id_to_uri(file_id)?; | 484 | let uri = world.file_id_to_uri(file_id)?; |
@@ -461,7 +497,7 @@ pub fn publish_diagnostics( | |||
461 | } | 497 | } |
462 | 498 | ||
463 | pub fn publish_decorations( | 499 | pub fn publish_decorations( |
464 | world: ServerWorld, | 500 | world: &ServerWorld, |
465 | file_id: FileId, | 501 | file_id: FileId, |
466 | ) -> Result<req::PublishDecorationsParams> { | 502 | ) -> Result<req::PublishDecorationsParams> { |
467 | let uri = world.file_id_to_uri(file_id)?; | 503 | let uri = world.file_id_to_uri(file_id)?; |
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index 402615e42..cf2477cb5 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs | |||
@@ -16,7 +16,7 @@ use gen_lsp_server::{ | |||
16 | }; | 16 | }; |
17 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::FxHashMap; |
18 | 18 | ||
19 | use { | 19 | use crate::{ |
20 | req, | 20 | req, |
21 | Result, | 21 | Result, |
22 | vfs::{self, FileEvent}, | 22 | vfs::{self, FileEvent}, |
@@ -255,6 +255,7 @@ fn on_request( | |||
255 | .on::<req::Completion>(handlers::handle_completion)? | 255 | .on::<req::Completion>(handlers::handle_completion)? |
256 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? | 256 | .on::<req::CodeActionRequest>(handlers::handle_code_action)? |
257 | .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? | 257 | .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? |
258 | .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? | ||
258 | .finish(); | 259 | .finish(); |
259 | match req { | 260 | match req { |
260 | Ok((id, handle)) => { | 261 | Ok((id, handle)) => { |
@@ -390,7 +391,7 @@ fn update_file_notifications_on_threadpool( | |||
390 | ) { | 391 | ) { |
391 | pool.spawn(move || { | 392 | pool.spawn(move || { |
392 | for file_id in subscriptions { | 393 | for file_id in subscriptions { |
393 | match handlers::publish_diagnostics(world.clone(), file_id) { | 394 | match handlers::publish_diagnostics(&world, file_id) { |
394 | Err(e) => { | 395 | Err(e) => { |
395 | error!("failed to compute diagnostics: {:?}", e) | 396 | error!("failed to compute diagnostics: {:?}", e) |
396 | } | 397 | } |
@@ -399,7 +400,7 @@ fn update_file_notifications_on_threadpool( | |||
399 | sender.send(Task::Notify(not)); | 400 | sender.send(Task::Notify(not)); |
400 | } | 401 | } |
401 | } | 402 | } |
402 | match handlers::publish_decorations(world.clone(), file_id) { | 403 | match handlers::publish_decorations(&world, file_id) { |
403 | Err(e) => { | 404 | Err(e) => { |
404 | error!("failed to compute decorations: {:?}", e) | 405 | error!("failed to compute decorations: {:?}", e) |
405 | } | 406 | } |
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index 43e4fd654..c144d9596 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs | |||
@@ -5,7 +5,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
5 | use cargo_metadata::{metadata_run, CargoOpt}; | 5 | use cargo_metadata::{metadata_run, CargoOpt}; |
6 | use ra_syntax::SmolStr; | 6 | use ra_syntax::SmolStr; |
7 | 7 | ||
8 | use { | 8 | use crate::{ |
9 | Result, | 9 | Result, |
10 | thread_watcher::{Worker, ThreadWatcher}, | 10 | thread_watcher::{Worker, ThreadWatcher}, |
11 | }; | 11 | }; |
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index f80957589..1630edf7f 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs | |||
@@ -14,6 +14,7 @@ pub use languageserver_types::{ | |||
14 | CompletionParams, CompletionResponse, | 14 | CompletionParams, CompletionResponse, |
15 | DocumentOnTypeFormattingParams, | 15 | DocumentOnTypeFormattingParams, |
16 | TextDocumentEdit, | 16 | TextDocumentEdit, |
17 | SignatureHelp, Hover | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | pub enum SyntaxTree {} | 20 | pub enum SyntaxTree {} |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index c4cdf83d4..9b3013ae8 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; | |||
8 | use languageserver_types::Url; | 8 | use languageserver_types::Url; |
9 | use ra_analysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver}; | 9 | use ra_analysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver}; |
10 | 10 | ||
11 | use { | 11 | use crate::{ |
12 | Result, | 12 | Result, |
13 | path_map::{PathMap, Root}, | 13 | path_map::{PathMap, Root}, |
14 | vfs::{FileEvent, FileEventKind}, | 14 | vfs::{FileEvent, FileEventKind}, |
@@ -23,7 +23,6 @@ pub struct ServerWorldState { | |||
23 | pub mem_map: FxHashMap<FileId, Option<String>>, | 23 | pub mem_map: FxHashMap<FileId, Option<String>>, |
24 | } | 24 | } |
25 | 25 | ||
26 | #[derive(Clone)] | ||
27 | pub struct ServerWorld { | 26 | pub struct ServerWorld { |
28 | pub workspaces: Arc<Vec<CargoWorkspace>>, | 27 | pub workspaces: Arc<Vec<CargoWorkspace>>, |
29 | pub analysis: Analysis, | 28 | pub analysis: Analysis, |
diff --git a/crates/ra_lsp_server/src/thread_watcher.rs b/crates/ra_lsp_server/src/thread_watcher.rs index 86a3a91e0..3257effcb 100644 --- a/crates/ra_lsp_server/src/thread_watcher.rs +++ b/crates/ra_lsp_server/src/thread_watcher.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::thread; | 1 | use std::thread; |
2 | use crossbeam_channel::{bounded, unbounded, Sender, Receiver}; | 2 | use crossbeam_channel::{bounded, unbounded, Sender, Receiver}; |
3 | use drop_bomb::DropBomb; | 3 | use drop_bomb::DropBomb; |
4 | use Result; | 4 | use crate::Result; |
5 | 5 | ||
6 | pub struct Worker<I, O> { | 6 | pub struct Worker<I, O> { |
7 | pub inp: Sender<I>, | 7 | pub inp: Sender<I>, |
diff --git a/crates/ra_lsp_server/src/vfs.rs b/crates/ra_lsp_server/src/vfs.rs index a1c1783f2..d8f9b1aac 100644 --- a/crates/ra_lsp_server/src/vfs.rs +++ b/crates/ra_lsp_server/src/vfs.rs | |||
@@ -5,7 +5,7 @@ use std::{ | |||
5 | 5 | ||
6 | use walkdir::WalkDir; | 6 | use walkdir::WalkDir; |
7 | 7 | ||
8 | use { | 8 | use crate::{ |
9 | thread_watcher::{Worker, ThreadWatcher}, | 9 | thread_watcher::{Worker, ThreadWatcher}, |
10 | }; | 10 | }; |
11 | 11 | ||
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index dced45f55..7265b5999 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs | |||
@@ -12,7 +12,7 @@ mod support; | |||
12 | 12 | ||
13 | use ra_lsp_server::req::{Runnables, RunnablesParams}; | 13 | use ra_lsp_server::req::{Runnables, RunnablesParams}; |
14 | 14 | ||
15 | use support::project; | 15 | use crate::support::project; |
16 | 16 | ||
17 | 17 | ||
18 | const LOG: &'static str = ""; | 18 | const LOG: &'static str = ""; |
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs index 8fe2aa816..d1339f62f 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/support.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs | |||
@@ -25,7 +25,7 @@ use ra_lsp_server::{main_loop, req, thread_watcher::{ThreadWatcher, Worker}}; | |||
25 | 25 | ||
26 | pub fn project(fixture: &str) -> Server { | 26 | pub fn project(fixture: &str) -> Server { |
27 | static INIT: Once = Once::new(); | 27 | static INIT: Once = Once::new(); |
28 | INIT.call_once(|| Logger::with_env_or_str(::LOG).start().unwrap()); | 28 | INIT.call_once(|| Logger::with_env_or_str(crate::LOG).start().unwrap()); |
29 | 29 | ||
30 | let tmp_dir = TempDir::new("test-project") | 30 | let tmp_dir = TempDir::new("test-project") |
31 | .unwrap(); | 31 | .unwrap(); |
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 6345e4725..34bb1c591 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml | |||
@@ -1,4 +1,5 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | ||
2 | name = "ra_syntax" | 3 | name = "ra_syntax" |
3 | version = "0.1.0" | 4 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs index a6678093d..e686a5704 100644 --- a/crates/ra_syntax/src/algo/mod.rs +++ b/crates/ra_syntax/src/algo/mod.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | pub mod walk; | 1 | pub mod walk; |
2 | pub mod visit; | 2 | pub mod visit; |
3 | 3 | ||
4 | use { | 4 | use crate::{ |
5 | SyntaxNodeRef, TextUnit, TextRange, | 5 | SyntaxNodeRef, TextUnit, TextRange, |
6 | text_utils::{contains_offset_nonstrict, is_subrange}, | 6 | text_utils::{contains_offset_nonstrict, is_subrange}, |
7 | }; | 7 | }; |
diff --git a/crates/ra_syntax/src/algo/visit.rs b/crates/ra_syntax/src/algo/visit.rs index 9f1c127c7..1ae988a87 100644 --- a/crates/ra_syntax/src/algo/visit.rs +++ b/crates/ra_syntax/src/algo/visit.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use std::marker::PhantomData; | 1 | use std::marker::PhantomData; |
2 | use {SyntaxNodeRef, AstNode}; | 2 | use crate::{SyntaxNodeRef, AstNode}; |
3 | 3 | ||
4 | 4 | ||
5 | pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> { | 5 | pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> { |
diff --git a/crates/ra_syntax/src/algo/walk.rs b/crates/ra_syntax/src/algo/walk.rs index 8e294d965..d34415626 100644 --- a/crates/ra_syntax/src/algo/walk.rs +++ b/crates/ra_syntax/src/algo/walk.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use { | 1 | use crate::{ |
2 | SyntaxNodeRef, | 2 | SyntaxNodeRef, |
3 | algo::generate, | 3 | algo::generate, |
4 | }; | 4 | }; |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index ef7b5b1a1..160d186b8 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | // This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run | 1 | // This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run |
2 | // Do not edit manually | 2 | // Do not edit manually |
3 | 3 | ||
4 | use { | 4 | use crate::{ |
5 | ast, | 5 | ast, |
6 | SyntaxNodeRef, AstNode, | 6 | SyntaxNodeRef, AstNode, |
7 | SyntaxKind::*, | 7 | SyntaxKind::*, |
@@ -1387,7 +1387,11 @@ impl<'a> AstNode<'a> for PathExpr<'a> { | |||
1387 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | 1387 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | impl<'a> PathExpr<'a> {} | 1390 | impl<'a> PathExpr<'a> { |
1391 | pub fn path(self) -> Option<Path<'a>> { | ||
1392 | super::child_opt(self) | ||
1393 | } | ||
1394 | } | ||
1391 | 1395 | ||
1392 | // PathPat | 1396 | // PathPat |
1393 | #[derive(Debug, Clone, Copy)] | 1397 | #[derive(Debug, Clone, Copy)] |
@@ -2193,3 +2197,21 @@ impl<'a> WhileExpr<'a> { | |||
2193 | } | 2197 | } |
2194 | } | 2198 | } |
2195 | 2199 | ||
2200 | // Whitespace | ||
2201 | #[derive(Debug, Clone, Copy)] | ||
2202 | pub struct Whitespace<'a> { | ||
2203 | syntax: SyntaxNodeRef<'a>, | ||
2204 | } | ||
2205 | |||
2206 | impl<'a> AstNode<'a> for Whitespace<'a> { | ||
2207 | fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { | ||
2208 | match syntax.kind() { | ||
2209 | WHITESPACE => Some(Whitespace { syntax }), | ||
2210 | _ => None, | ||
2211 | } | ||
2212 | } | ||
2213 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | ||
2214 | } | ||
2215 | |||
2216 | impl<'a> Whitespace<'a> {} | ||
2217 | |||
diff --git a/crates/ra_syntax/src/ast/generated.rs.tera b/crates/ra_syntax/src/ast/generated.rs.tera index ffa9c4134..5cb7a35ed 100644 --- a/crates/ra_syntax/src/ast/generated.rs.tera +++ b/crates/ra_syntax/src/ast/generated.rs.tera | |||
@@ -3,7 +3,7 @@ the below applies to the result of this template | |||
3 | #}// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run | 3 | #}// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-kinds` is run |
4 | // Do not edit manually | 4 | // Do not edit manually |
5 | 5 | ||
6 | use { | 6 | use crate::{ |
7 | ast, | 7 | ast, |
8 | SyntaxNodeRef, AstNode, | 8 | SyntaxNodeRef, AstNode, |
9 | SyntaxKind::*, | 9 | SyntaxKind::*, |
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs index 10dac72e5..88193a1ed 100644 --- a/crates/ra_syntax/src/ast/mod.rs +++ b/crates/ra_syntax/src/ast/mod.rs | |||
@@ -4,7 +4,7 @@ use std::marker::PhantomData; | |||
4 | 4 | ||
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | 6 | ||
7 | use { | 7 | use crate::{ |
8 | SmolStr, SyntaxNodeRef, SyntaxKind::*, | 8 | SmolStr, SyntaxNodeRef, SyntaxKind::*, |
9 | yellow::{RefRoot, SyntaxNodeChildren}, | 9 | yellow::{RefRoot, SyntaxNodeChildren}, |
10 | }; | 10 | }; |
@@ -100,8 +100,8 @@ impl<'a> Lifetime<'a> { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | impl<'a> Comment<'a> { | 102 | impl<'a> Comment<'a> { |
103 | pub fn text(&self) -> SmolStr { | 103 | pub fn text(&self) -> &SmolStr { |
104 | self.syntax().leaf_text().unwrap().clone() | 104 | self.syntax().leaf_text().unwrap() |
105 | } | 105 | } |
106 | 106 | ||
107 | pub fn flavor(&self) -> CommentFlavor { | 107 | pub fn flavor(&self) -> CommentFlavor { |
@@ -120,9 +120,17 @@ impl<'a> Comment<'a> { | |||
120 | pub fn prefix(&self) -> &'static str { | 120 | pub fn prefix(&self) -> &'static str { |
121 | self.flavor().prefix() | 121 | self.flavor().prefix() |
122 | } | 122 | } |
123 | |||
124 | pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> { | ||
125 | self.text().chars().filter(|&c| c == '\n').map(|_| &()) | ||
126 | } | ||
127 | |||
128 | pub fn has_newlines(&self) -> bool { | ||
129 | self.count_newlines_lazy().count() > 0 | ||
130 | } | ||
123 | } | 131 | } |
124 | 132 | ||
125 | #[derive(Debug)] | 133 | #[derive(Debug, PartialEq, Eq)] |
126 | pub enum CommentFlavor { | 134 | pub enum CommentFlavor { |
127 | Line, | 135 | Line, |
128 | Doc, | 136 | Doc, |
@@ -142,6 +150,20 @@ impl CommentFlavor { | |||
142 | } | 150 | } |
143 | } | 151 | } |
144 | 152 | ||
153 | impl<'a> Whitespace<'a> { | ||
154 | pub fn text(&self) -> &SmolStr { | ||
155 | &self.syntax().leaf_text().unwrap() | ||
156 | } | ||
157 | |||
158 | pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> { | ||
159 | self.text().chars().filter(|&c| c == '\n').map(|_| &()) | ||
160 | } | ||
161 | |||
162 | pub fn has_newlines(&self) -> bool { | ||
163 | self.count_newlines_lazy().count() > 0 | ||
164 | } | ||
165 | } | ||
166 | |||
145 | impl<'a> Name<'a> { | 167 | impl<'a> Name<'a> { |
146 | pub fn text(&self) -> SmolStr { | 168 | pub fn text(&self) -> SmolStr { |
147 | let ident = self.syntax().first_child() | 169 | let ident = self.syntax().first_child() |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 9da0c2c13..ea8063d3b 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -342,7 +342,7 @@ Grammar( | |||
342 | "TupleExpr": (), | 342 | "TupleExpr": (), |
343 | "ArrayExpr": (), | 343 | "ArrayExpr": (), |
344 | "ParenExpr": (), | 344 | "ParenExpr": (), |
345 | "PathExpr": (), | 345 | "PathExpr": (options: ["Path"]), |
346 | "LambdaExpr": ( | 346 | "LambdaExpr": ( |
347 | options: [ | 347 | options: [ |
348 | "ParamList", | 348 | "ParamList", |
@@ -538,5 +538,6 @@ Grammar( | |||
538 | options: [ "NameRef" ] | 538 | options: [ "NameRef" ] |
539 | ), | 539 | ), |
540 | "Comment": (), | 540 | "Comment": (), |
541 | "Whitespace": (), | ||
541 | }, | 542 | }, |
542 | ) | 543 | ) |
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index a720d255f..e21de68c5 100644 --- a/crates/ra_syntax/src/grammar/expressions/atom.rs +++ b/crates/ra_syntax/src/grammar/expressions/atom.rs | |||
@@ -30,7 +30,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = | |||
30 | token_set_union![ | 30 | token_set_union![ |
31 | LITERAL_FIRST, | 31 | LITERAL_FIRST, |
32 | token_set![L_CURLY, L_PAREN, L_BRACK, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW, | 32 | token_set![L_CURLY, L_PAREN, L_BRACK, PIPE, MOVE_KW, IF_KW, WHILE_KW, MATCH_KW, UNSAFE_KW, |
33 | RETURN_KW, IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ], | 33 | RETURN_KW, IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ], |
34 | ]; | 34 | ]; |
35 | 35 | ||
36 | const EXPR_RECOVERY_SET: TokenSet = | 36 | const EXPR_RECOVERY_SET: TokenSet = |
diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar/mod.rs index 2cb11dc1e..1199ba230 100644 --- a/crates/ra_syntax/src/grammar/mod.rs +++ b/crates/ra_syntax/src/grammar/mod.rs | |||
@@ -31,7 +31,7 @@ mod type_args; | |||
31 | mod type_params; | 31 | mod type_params; |
32 | mod types; | 32 | mod types; |
33 | 33 | ||
34 | use { | 34 | use crate::{ |
35 | token_set::TokenSet, | 35 | token_set::TokenSet, |
36 | parser_api::{Marker, CompletedMarker, Parser}, | 36 | parser_api::{Marker, CompletedMarker, Parser}, |
37 | SyntaxKind::{self, *}, | 37 | SyntaxKind::{self, *}, |
diff --git a/crates/ra_syntax/src/lexer/comments.rs b/crates/ra_syntax/src/lexer/comments.rs index eb417c2dc..afe6886a1 100644 --- a/crates/ra_syntax/src/lexer/comments.rs +++ b/crates/ra_syntax/src/lexer/comments.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use lexer::ptr::Ptr; | 1 | use crate::lexer::ptr::Ptr; |
2 | 2 | ||
3 | use SyntaxKind::{self, *}; | 3 | use crate::SyntaxKind::{self, *}; |
4 | 4 | ||
5 | pub(crate) fn scan_shebang(ptr: &mut Ptr) -> bool { | 5 | pub(crate) fn scan_shebang(ptr: &mut Ptr) -> bool { |
6 | if ptr.at_str("!/") { | 6 | if ptr.at_str("!/") { |
diff --git a/crates/ra_syntax/src/lexer/mod.rs b/crates/ra_syntax/src/lexer/mod.rs index 3e11db88b..9dc0b63d6 100644 --- a/crates/ra_syntax/src/lexer/mod.rs +++ b/crates/ra_syntax/src/lexer/mod.rs | |||
@@ -4,7 +4,7 @@ mod numbers; | |||
4 | mod ptr; | 4 | mod ptr; |
5 | mod strings; | 5 | mod strings; |
6 | 6 | ||
7 | use { | 7 | use crate::{ |
8 | SyntaxKind::{self, *}, | 8 | SyntaxKind::{self, *}, |
9 | TextUnit, | 9 | TextUnit, |
10 | }; | 10 | }; |
diff --git a/crates/ra_syntax/src/lexer/numbers.rs b/crates/ra_syntax/src/lexer/numbers.rs index 22e7d4e99..46daf5e52 100644 --- a/crates/ra_syntax/src/lexer/numbers.rs +++ b/crates/ra_syntax/src/lexer/numbers.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use lexer::classes::*; | 1 | use crate::lexer::classes::*; |
2 | use lexer::ptr::Ptr; | 2 | use crate::lexer::ptr::Ptr; |
3 | 3 | ||
4 | use SyntaxKind::{self, *}; | 4 | use crate::SyntaxKind::{self, *}; |
5 | 5 | ||
6 | pub(crate) fn scan_number(c: char, ptr: &mut Ptr) -> SyntaxKind { | 6 | pub(crate) fn scan_number(c: char, ptr: &mut Ptr) -> SyntaxKind { |
7 | if c == '0' { | 7 | if c == '0' { |
diff --git a/crates/ra_syntax/src/lexer/ptr.rs b/crates/ra_syntax/src/lexer/ptr.rs index c9a5354ea..c4708cb1c 100644 --- a/crates/ra_syntax/src/lexer/ptr.rs +++ b/crates/ra_syntax/src/lexer/ptr.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use TextUnit; | 1 | use crate::TextUnit; |
2 | 2 | ||
3 | use std::str::Chars; | 3 | use std::str::Chars; |
4 | 4 | ||
diff --git a/crates/ra_syntax/src/lexer/strings.rs b/crates/ra_syntax/src/lexer/strings.rs index 5ff483d14..bceacdcac 100644 --- a/crates/ra_syntax/src/lexer/strings.rs +++ b/crates/ra_syntax/src/lexer/strings.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use SyntaxKind::{self, *}; | 1 | use crate::SyntaxKind::{self, *}; |
2 | 2 | ||
3 | use lexer::ptr::Ptr; | 3 | use crate::lexer::ptr::Ptr; |
4 | 4 | ||
5 | pub(crate) fn is_string_literal_start(c: char, c1: Option<char>, c2: Option<char>) -> bool { | 5 | pub(crate) fn is_string_literal_start(c: char, c1: Option<char>, c2: Option<char>) -> bool { |
6 | match (c, c1, c2) { | 6 | match (c, c1, c2) { |
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 703469629..7eba5ee61 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -46,7 +46,7 @@ mod yellow; | |||
46 | pub mod utils; | 46 | pub mod utils; |
47 | pub mod text_utils; | 47 | pub mod text_utils; |
48 | 48 | ||
49 | pub use { | 49 | pub use crate::{ |
50 | rowan::{SmolStr, TextRange, TextUnit}, | 50 | rowan::{SmolStr, TextRange, TextUnit}, |
51 | ast::AstNode, | 51 | ast::AstNode, |
52 | lexer::{tokenize, Token}, | 52 | lexer::{tokenize, Token}, |
@@ -55,11 +55,11 @@ pub use { | |||
55 | reparsing::AtomEdit, | 55 | reparsing::AtomEdit, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | use { | 58 | use crate::{ |
59 | yellow::{GreenNode}, | 59 | yellow::{GreenNode}, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | #[derive(Clone, Debug, Hash)] | 62 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
63 | pub struct File { | 63 | pub struct File { |
64 | root: SyntaxNode | 64 | root: SyntaxNode |
65 | } | 65 | } |
diff --git a/crates/ra_syntax/src/parser_api.rs b/crates/ra_syntax/src/parser_api.rs index 772d753af..cc23bb75e 100644 --- a/crates/ra_syntax/src/parser_api.rs +++ b/crates/ra_syntax/src/parser_api.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use { | 1 | use crate::{ |
2 | token_set::TokenSet, | 2 | token_set::TokenSet, |
3 | parser_impl::ParserImpl, | 3 | parser_impl::ParserImpl, |
4 | SyntaxKind::{self, ERROR}, | 4 | SyntaxKind::{self, ERROR}, |
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs index 95e5ce4cc..928d2cc7a 100644 --- a/crates/ra_syntax/src/parser_impl/event.rs +++ b/crates/ra_syntax/src/parser_impl/event.rs | |||
@@ -8,7 +8,7 @@ | |||
8 | //! `start node`, `finish node`, and `FileBuilder` converts | 8 | //! `start node`, `finish node`, and `FileBuilder` converts |
9 | //! this stream to a real tree. | 9 | //! this stream to a real tree. |
10 | use std::mem; | 10 | use std::mem; |
11 | use { | 11 | use crate::{ |
12 | TextUnit, TextRange, SmolStr, | 12 | TextUnit, TextRange, SmolStr, |
13 | lexer::Token, | 13 | lexer::Token, |
14 | parser_impl::Sink, | 14 | parser_impl::Sink, |
diff --git a/crates/ra_syntax/src/parser_impl/input.rs b/crates/ra_syntax/src/parser_impl/input.rs index c0fe4d488..ac6d900d8 100644 --- a/crates/ra_syntax/src/parser_impl/input.rs +++ b/crates/ra_syntax/src/parser_impl/input.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use {lexer::Token, SyntaxKind, SyntaxKind::EOF, TextRange, TextUnit}; | 1 | use crate::{lexer::Token, SyntaxKind, SyntaxKind::EOF, TextRange, TextUnit}; |
2 | 2 | ||
3 | use std::ops::{Add, AddAssign}; | 3 | use std::ops::{Add, AddAssign}; |
4 | 4 | ||
diff --git a/crates/ra_syntax/src/parser_impl/mod.rs b/crates/ra_syntax/src/parser_impl/mod.rs index 8d74cef0e..c2a6448e7 100644 --- a/crates/ra_syntax/src/parser_impl/mod.rs +++ b/crates/ra_syntax/src/parser_impl/mod.rs | |||
@@ -3,7 +3,7 @@ mod input; | |||
3 | 3 | ||
4 | use std::cell::Cell; | 4 | use std::cell::Cell; |
5 | 5 | ||
6 | use { | 6 | use crate::{ |
7 | TextUnit, SmolStr, | 7 | TextUnit, SmolStr, |
8 | lexer::Token, | 8 | lexer::Token, |
9 | parser_api::Parser, | 9 | parser_api::Parser, |
@@ -13,7 +13,7 @@ use { | |||
13 | }, | 13 | }, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use SyntaxKind::{self, EOF, TOMBSTONE}; | 16 | use crate::SyntaxKind::{self, EOF, TOMBSTONE}; |
17 | 17 | ||
18 | pub(crate) trait Sink { | 18 | pub(crate) trait Sink { |
19 | type Tree; | 19 | type Tree; |
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index d8b6a6a10..16272fe88 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | use algo; | 1 | use crate::algo; |
2 | use grammar; | 2 | use crate::grammar; |
3 | use lexer::{tokenize, Token}; | 3 | use crate::lexer::{tokenize, Token}; |
4 | use yellow::{self, GreenNode, SyntaxNodeRef, SyntaxError}; | 4 | use crate::yellow::{self, GreenNode, SyntaxNodeRef, SyntaxError}; |
5 | use parser_impl; | 5 | use crate::parser_impl; |
6 | use parser_api::Parser; | 6 | use crate::parser_api::Parser; |
7 | use { | 7 | use crate::{ |
8 | TextUnit, TextRange, | 8 | TextUnit, TextRange, |
9 | SyntaxKind::*, | 9 | SyntaxKind::*, |
10 | }; | 10 | }; |
11 | use text_utils::replace_range; | 11 | use crate::text_utils::replace_range; |
12 | 12 | ||
13 | #[derive(Debug, Clone)] | 13 | #[derive(Debug, Clone)] |
14 | pub struct AtomEdit { | 14 | pub struct AtomEdit { |
diff --git a/crates/ra_syntax/src/syntax_kinds/mod.rs b/crates/ra_syntax/src/syntax_kinds/mod.rs index 332cd13ac..3041e5633 100644 --- a/crates/ra_syntax/src/syntax_kinds/mod.rs +++ b/crates/ra_syntax/src/syntax_kinds/mod.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | mod generated; | 1 | mod generated; |
2 | 2 | ||
3 | use std::fmt; | 3 | use std::fmt; |
4 | use SyntaxKind::*; | 4 | use crate::SyntaxKind::*; |
5 | 5 | ||
6 | pub use self::generated::SyntaxKind; | 6 | pub use self::generated::SyntaxKind; |
7 | 7 | ||
diff --git a/crates/ra_syntax/src/text_utils.rs b/crates/ra_syntax/src/text_utils.rs index 58ae1e43e..adf26ef30 100644 --- a/crates/ra_syntax/src/text_utils.rs +++ b/crates/ra_syntax/src/text_utils.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use {TextRange, TextUnit}; | 1 | use crate::{TextRange, TextUnit}; |
2 | 2 | ||
3 | pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | 3 | pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { |
4 | range.start() <= offset && offset <= range.end() | 4 | range.start() <= offset && offset <= range.end() |
diff --git a/crates/ra_syntax/src/token_set.rs b/crates/ra_syntax/src/token_set.rs index c83fba81b..d407dfa48 100644 --- a/crates/ra_syntax/src/token_set.rs +++ b/crates/ra_syntax/src/token_set.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use SyntaxKind; | 1 | use crate::SyntaxKind; |
2 | 2 | ||
3 | #[derive(Clone, Copy)] | 3 | #[derive(Clone, Copy)] |
4 | pub(crate) struct TokenSet(pub(crate) u128); | 4 | pub(crate) struct TokenSet(pub(crate) u128); |
@@ -29,7 +29,7 @@ macro_rules! token_set_union { | |||
29 | 29 | ||
30 | #[test] | 30 | #[test] |
31 | fn token_set_works_for_tokens() { | 31 | fn token_set_works_for_tokens() { |
32 | use SyntaxKind::*; | 32 | use crate::SyntaxKind::*; |
33 | let ts = token_set! { EOF, SHEBANG }; | 33 | let ts = token_set! { EOF, SHEBANG }; |
34 | assert!(ts.contains(EOF)); | 34 | assert!(ts.contains(EOF)); |
35 | assert!(ts.contains(SHEBANG)); | 35 | assert!(ts.contains(SHEBANG)); |
diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs index e274f7471..df1f4b372 100644 --- a/crates/ra_syntax/src/utils.rs +++ b/crates/ra_syntax/src/utils.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use std::fmt::Write; | 1 | use std::fmt::Write; |
2 | use { | 2 | use crate::{ |
3 | algo::walk::{walk, WalkEvent}, | 3 | algo::walk::{walk, WalkEvent}, |
4 | SyntaxKind, File, SyntaxNodeRef | 4 | SyntaxKind, File, SyntaxNodeRef |
5 | }; | 5 | }; |
diff --git a/crates/ra_syntax/src/yellow/builder.rs b/crates/ra_syntax/src/yellow/builder.rs index c307b2bd0..67a1a382b 100644 --- a/crates/ra_syntax/src/yellow/builder.rs +++ b/crates/ra_syntax/src/yellow/builder.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use rowan::GreenNodeBuilder; | 1 | use rowan::GreenNodeBuilder; |
2 | use { | 2 | use crate::{ |
3 | TextUnit, SmolStr, | 3 | TextUnit, SmolStr, |
4 | parser_impl::Sink, | 4 | parser_impl::Sink, |
5 | yellow::{GreenNode, SyntaxError, RaTypes}, | 5 | yellow::{GreenNode, SyntaxError, RaTypes}, |
diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow/mod.rs index 710320f47..ab9bca0f0 100644 --- a/crates/ra_syntax/src/yellow/mod.rs +++ b/crates/ra_syntax/src/yellow/mod.rs | |||
@@ -6,7 +6,7 @@ use std::{ | |||
6 | hash::{Hash, Hasher}, | 6 | hash::{Hash, Hasher}, |
7 | }; | 7 | }; |
8 | use rowan::Types; | 8 | use rowan::Types; |
9 | use {SyntaxKind, TextUnit, TextRange, SmolStr}; | 9 | use crate::{SyntaxKind, TextUnit, TextRange, SmolStr}; |
10 | use self::syntax_text::SyntaxText; | 10 | use self::syntax_text::SyntaxText; |
11 | 11 | ||
12 | pub use rowan::{TreeRoot}; | 12 | pub use rowan::{TreeRoot}; |
@@ -70,16 +70,16 @@ impl<'a> SyntaxNodeRef<'a> { | |||
70 | self.0.leaf_text() | 70 | self.0.leaf_text() |
71 | } | 71 | } |
72 | pub fn ancestors(self) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | 72 | pub fn ancestors(self) -> impl Iterator<Item=SyntaxNodeRef<'a>> { |
73 | ::algo::generate(Some(self), |&node| node.parent()) | 73 | crate::algo::generate(Some(self), |&node| node.parent()) |
74 | } | 74 | } |
75 | pub fn descendants(self) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | 75 | pub fn descendants(self) -> impl Iterator<Item=SyntaxNodeRef<'a>> { |
76 | ::algo::walk::walk(self).filter_map(|event| match event { | 76 | crate::algo::walk::walk(self).filter_map(|event| match event { |
77 | ::algo::walk::WalkEvent::Enter(node) => Some(node), | 77 | crate::algo::walk::WalkEvent::Enter(node) => Some(node), |
78 | ::algo::walk::WalkEvent::Exit(_) => None, | 78 | crate::algo::walk::WalkEvent::Exit(_) => None, |
79 | }) | 79 | }) |
80 | } | 80 | } |
81 | pub fn siblings(self, direction: Direction) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | 81 | pub fn siblings(self, direction: Direction) -> impl Iterator<Item=SyntaxNodeRef<'a>> { |
82 | ::algo::generate(Some(self), move |&node| match direction { | 82 | crate::algo::generate(Some(self), move |&node| match direction { |
83 | Direction::Next => node.next_sibling(), | 83 | Direction::Next => node.next_sibling(), |
84 | Direction::Prev => node.prev_sibling(), | 84 | Direction::Prev => node.prev_sibling(), |
85 | }) | 85 | }) |
@@ -156,7 +156,7 @@ impl<R: TreeRoot<RaTypes>> Iterator for SyntaxNodeChildren<R> { | |||
156 | 156 | ||
157 | 157 | ||
158 | fn has_short_text(kind: SyntaxKind) -> bool { | 158 | fn has_short_text(kind: SyntaxKind) -> bool { |
159 | use SyntaxKind::*; | 159 | use crate::SyntaxKind::*; |
160 | match kind { | 160 | match kind { |
161 | IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, | 161 | IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, |
162 | _ => false, | 162 | _ => false, |
diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs index 0db1049de..ae33b993d 100644 --- a/crates/ra_syntax/src/yellow/syntax_text.rs +++ b/crates/ra_syntax/src/yellow/syntax_text.rs | |||
@@ -2,7 +2,7 @@ use std::{ | |||
2 | fmt, ops, | 2 | fmt, ops, |
3 | }; | 3 | }; |
4 | 4 | ||
5 | use { | 5 | use crate::{ |
6 | SyntaxNodeRef, TextRange, TextUnit, | 6 | SyntaxNodeRef, TextRange, TextUnit, |
7 | text_utils::{intersect, contains_offset_nonstrict}, | 7 | text_utils::{intersect, contains_offset_nonstrict}, |
8 | }; | 8 | }; |
diff --git a/crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.rs b/crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.rs new file mode 100644 index 000000000..f1ed30220 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.rs | |||
@@ -0,0 +1,3 @@ | |||
1 | fn main() { | ||
2 | make_query(crate::module_map::module_tree); | ||
3 | } | ||
diff --git a/crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.txt b/crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.txt new file mode 100644 index 000000000..364315180 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.txt | |||
@@ -0,0 +1,41 @@ | |||
1 | ROOT@[0; 62) | ||
2 | FN_DEF@[0; 61) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 7) | ||
6 | IDENT@[3; 7) "main" | ||
7 | PARAM_LIST@[7; 9) | ||
8 | L_PAREN@[7; 8) | ||
9 | R_PAREN@[8; 9) | ||
10 | WHITESPACE@[9; 10) | ||
11 | BLOCK@[10; 61) | ||
12 | L_CURLY@[10; 11) | ||
13 | WHITESPACE@[11; 16) | ||
14 | EXPR_STMT@[16; 59) | ||
15 | CALL_EXPR@[16; 58) | ||
16 | PATH_EXPR@[16; 26) | ||
17 | PATH@[16; 26) | ||
18 | PATH_SEGMENT@[16; 26) | ||
19 | NAME_REF@[16; 26) | ||
20 | IDENT@[16; 26) "make_query" | ||
21 | ARG_LIST@[26; 58) | ||
22 | L_PAREN@[26; 27) | ||
23 | PATH_EXPR@[27; 57) | ||
24 | PATH@[27; 57) | ||
25 | PATH@[27; 44) | ||
26 | PATH@[27; 32) | ||
27 | PATH_SEGMENT@[27; 32) | ||
28 | CRATE_KW@[27; 32) | ||
29 | COLONCOLON@[32; 34) | ||
30 | PATH_SEGMENT@[34; 44) | ||
31 | NAME_REF@[34; 44) | ||
32 | IDENT@[34; 44) "module_map" | ||
33 | COLONCOLON@[44; 46) | ||
34 | PATH_SEGMENT@[46; 57) | ||
35 | NAME_REF@[46; 57) | ||
36 | IDENT@[46; 57) "module_tree" | ||
37 | R_PAREN@[57; 58) | ||
38 | SEMI@[58; 59) | ||
39 | WHITESPACE@[59; 60) | ||
40 | R_CURLY@[60; 61) | ||
41 | WHITESPACE@[61; 62) | ||
diff --git a/crates/salsa/Cargo.toml b/crates/salsa/Cargo.toml deleted file mode 100644 index 9eb83234f..000000000 --- a/crates/salsa/Cargo.toml +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | [package] | ||
2 | name = "salsa" | ||
3 | version = "0.1.0" | ||
4 | authors = ["Aleksey Kladov <[email protected]>"] | ||
5 | |||
6 | [dependencies] | ||
7 | parking_lot = "0.6.3" | ||
8 | im = "12.0.0" | ||
diff --git a/crates/salsa/src/lib.rs b/crates/salsa/src/lib.rs deleted file mode 100644 index 35deed374..000000000 --- a/crates/salsa/src/lib.rs +++ /dev/null | |||
@@ -1,293 +0,0 @@ | |||
1 | extern crate im; | ||
2 | extern crate parking_lot; | ||
3 | |||
4 | use std::{ | ||
5 | sync::Arc, | ||
6 | collections::{HashSet, HashMap}, | ||
7 | cell::RefCell, | ||
8 | }; | ||
9 | use parking_lot::Mutex; | ||
10 | |||
11 | pub type GroundQueryFn<T, D> = Box<Fn(&T, &D) -> (D, OutputFingerprint) + Send + Sync + 'static>; | ||
12 | pub type QueryFn<T, D> = Box<Fn(&QueryCtx<T, D>, &D) -> (D, OutputFingerprint) + Send + Sync + 'static>; | ||
13 | |||
14 | #[derive(Debug)] | ||
15 | pub struct Db<T, D> { | ||
16 | db: Arc<DbState<T, D>>, | ||
17 | query_config: Arc<QueryConfig<T, D>>, | ||
18 | } | ||
19 | |||
20 | pub struct QueryConfig<T, D> { | ||
21 | ground_fn: HashMap<QueryTypeId, GroundQueryFn<T, D>>, | ||
22 | query_fn: HashMap<QueryTypeId, QueryFn<T, D>>, | ||
23 | } | ||
24 | |||
25 | impl<T, D> ::std::fmt::Debug for QueryConfig<T, D> { | ||
26 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||
27 | ::std::fmt::Display::fmt("QueryConfig { ... }", f) | ||
28 | } | ||
29 | } | ||
30 | |||
31 | #[derive(Debug)] | ||
32 | struct DbState<T, D> { | ||
33 | ground_data: T, | ||
34 | gen: Gen, | ||
35 | graph: Mutex<im::HashMap<QueryId, (Gen, Arc<QueryRecord<D>>)>>, | ||
36 | } | ||
37 | |||
38 | #[derive(Debug)] | ||
39 | struct QueryRecord<D> { | ||
40 | params: D, | ||
41 | output: D, | ||
42 | output_fingerprint: OutputFingerprint, | ||
43 | deps: Vec<(QueryId, OutputFingerprint)>, | ||
44 | } | ||
45 | |||
46 | impl<T, D> DbState<T, D> { | ||
47 | fn record( | ||
48 | &self, | ||
49 | query_id: QueryId, | ||
50 | params: D, | ||
51 | output: D, | ||
52 | output_fingerprint: OutputFingerprint, | ||
53 | deps: Vec<(QueryId, OutputFingerprint)>, | ||
54 | ) { | ||
55 | let gen = self.gen; | ||
56 | let record = QueryRecord { | ||
57 | params, | ||
58 | output, | ||
59 | output_fingerprint, | ||
60 | deps, | ||
61 | }; | ||
62 | self.graph.lock().insert(query_id, (gen, Arc::new(record))); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | impl<T, D> QueryConfig<T, D> { | ||
67 | pub fn new() -> Self { | ||
68 | QueryConfig { | ||
69 | ground_fn: HashMap::new(), | ||
70 | query_fn: HashMap::new(), | ||
71 | } | ||
72 | } | ||
73 | pub fn with_ground_query( | ||
74 | mut self, | ||
75 | query_type: QueryTypeId, | ||
76 | query_fn: GroundQueryFn<T, D> | ||
77 | ) -> Self { | ||
78 | let prev = self.ground_fn.insert(query_type, query_fn); | ||
79 | assert!(prev.is_none()); | ||
80 | self | ||
81 | } | ||
82 | pub fn with_query( | ||
83 | mut self, | ||
84 | query_type: QueryTypeId, | ||
85 | query_fn: QueryFn<T, D>, | ||
86 | ) -> Self { | ||
87 | let prev = self.query_fn.insert(query_type, query_fn); | ||
88 | assert!(prev.is_none()); | ||
89 | self | ||
90 | } | ||
91 | } | ||
92 | |||
93 | pub struct QueryCtx<T, D> { | ||
94 | db: Arc<DbState<T, D>>, | ||
95 | query_config: Arc<QueryConfig<T, D>>, | ||
96 | stack: RefCell<Vec<Vec<(QueryId, OutputFingerprint)>>>, | ||
97 | executed: RefCell<Vec<QueryTypeId>>, | ||
98 | } | ||
99 | |||
100 | impl<T, D> QueryCtx<T, D> | ||
101 | where | ||
102 | D: Clone | ||
103 | { | ||
104 | fn new(db: &Db<T, D>) -> QueryCtx<T, D> { | ||
105 | QueryCtx { | ||
106 | db: Arc::clone(&db.db), | ||
107 | query_config: Arc::clone(&db.query_config), | ||
108 | stack: RefCell::new(vec![Vec::new()]), | ||
109 | executed: RefCell::new(Vec::new()), | ||
110 | } | ||
111 | } | ||
112 | pub fn get( | ||
113 | &self, | ||
114 | query_id: QueryId, | ||
115 | params: D, | ||
116 | ) -> D { | ||
117 | let (res, output_fingerprint) = self.get_inner(query_id, params); | ||
118 | self.record_dep(query_id, output_fingerprint); | ||
119 | res | ||
120 | } | ||
121 | pub fn trace(&self) -> Vec<QueryTypeId> { | ||
122 | ::std::mem::replace(&mut *self.executed.borrow_mut(), Vec::new()) | ||
123 | } | ||
124 | |||
125 | fn get_inner( | ||
126 | &self, | ||
127 | query_id: QueryId, | ||
128 | params: D, | ||
129 | ) -> (D, OutputFingerprint) { | ||
130 | let (gen, record) = { | ||
131 | let guard = self.db.graph.lock(); | ||
132 | match guard.get(&query_id).map(|it| it.clone()){ | ||
133 | None => { | ||
134 | drop(guard); | ||
135 | return self.force(query_id, params); | ||
136 | }, | ||
137 | Some(it) => it, | ||
138 | } | ||
139 | }; | ||
140 | if gen == self.db.gen { | ||
141 | return (record.output.clone(), record.output_fingerprint) | ||
142 | } | ||
143 | if self.query_config.ground_fn.contains_key(&query_id.0) { | ||
144 | let (invalidated, record) = { | ||
145 | let guard = self.db.graph.lock(); | ||
146 | let (gen, ref record) = guard[&query_id]; | ||
147 | (gen == INVALIDATED, record.clone()) | ||
148 | }; | ||
149 | if invalidated { | ||
150 | return self.force(query_id, params); | ||
151 | } else { | ||
152 | return (record.output.clone(), record.output_fingerprint); | ||
153 | } | ||
154 | } | ||
155 | for (dep_query_id, prev_fingerprint) in record.deps.iter().cloned() { | ||
156 | let dep_params: D = { | ||
157 | let guard = self.db.graph.lock(); | ||
158 | guard[&dep_query_id] | ||
159 | .1 | ||
160 | .params | ||
161 | .clone() | ||
162 | }; | ||
163 | if prev_fingerprint != self.get_inner(dep_query_id, dep_params).1 { | ||
164 | return self.force(query_id, params) | ||
165 | } | ||
166 | } | ||
167 | let gen = self.db.gen; | ||
168 | { | ||
169 | let mut guard = self.db.graph.lock(); | ||
170 | guard[&query_id].0 = gen; | ||
171 | } | ||
172 | (record.output.clone(), record.output_fingerprint) | ||
173 | } | ||
174 | fn force( | ||
175 | &self, | ||
176 | query_id: QueryId, | ||
177 | params: D, | ||
178 | ) -> (D, OutputFingerprint) { | ||
179 | self.executed.borrow_mut().push(query_id.0); | ||
180 | self.stack.borrow_mut().push(Vec::new()); | ||
181 | |||
182 | let (res, output_fingerprint) = if let Some(f) = self.query_config.ground_fn.get(&query_id.0) { | ||
183 | f(&self.db.ground_data, ¶ms) | ||
184 | } else if let Some(f) = self.query_config.query_fn.get(&query_id.0) { | ||
185 | f(self, ¶ms) | ||
186 | } else { | ||
187 | panic!("unknown query type: {:?}", query_id.0); | ||
188 | }; | ||
189 | |||
190 | let res: D = res.into(); | ||
191 | |||
192 | let deps = self.stack.borrow_mut().pop().unwrap(); | ||
193 | self.db.record(query_id, params, res.clone(), output_fingerprint, deps); | ||
194 | (res, output_fingerprint) | ||
195 | } | ||
196 | fn record_dep( | ||
197 | &self, | ||
198 | query_id: QueryId, | ||
199 | output_fingerprint: OutputFingerprint, | ||
200 | ) -> () { | ||
201 | let mut stack = self.stack.borrow_mut(); | ||
202 | let deps = stack.last_mut().unwrap(); | ||
203 | deps.push((query_id, output_fingerprint)) | ||
204 | } | ||
205 | } | ||
206 | |||
207 | pub struct Invalidations { | ||
208 | types: HashSet<QueryTypeId>, | ||
209 | ids: Vec<QueryId>, | ||
210 | } | ||
211 | |||
212 | impl Invalidations { | ||
213 | pub fn new() -> Invalidations { | ||
214 | Invalidations { | ||
215 | types: HashSet::new(), | ||
216 | ids: Vec::new(), | ||
217 | } | ||
218 | } | ||
219 | pub fn invalidate( | ||
220 | &mut self, | ||
221 | query_type: QueryTypeId, | ||
222 | params: impl Iterator<Item=InputFingerprint>, | ||
223 | ) { | ||
224 | self.types.insert(query_type); | ||
225 | self.ids.extend(params.map(|it| QueryId(query_type, it))) | ||
226 | } | ||
227 | } | ||
228 | |||
229 | impl<T, D> Db<T, D> | ||
230 | where | ||
231 | D: Clone | ||
232 | { | ||
233 | pub fn new(query_config: QueryConfig<T, D>, ground_data: T) -> Db<T, D> { | ||
234 | Db { | ||
235 | db: Arc::new(DbState { ground_data, gen: Gen(0), graph: Default::default() }), | ||
236 | query_config: Arc::new(query_config), | ||
237 | } | ||
238 | } | ||
239 | pub fn ground_data(&self) -> &T { | ||
240 | &self.db.ground_data | ||
241 | } | ||
242 | pub fn with_ground_data( | ||
243 | &self, | ||
244 | ground_data: T, | ||
245 | invalidations: Invalidations, | ||
246 | ) -> Db<T, D> { | ||
247 | for id in self.query_config.ground_fn.keys() { | ||
248 | assert!( | ||
249 | invalidations.types.contains(id), | ||
250 | "all ground queries must be invalidated" | ||
251 | ); | ||
252 | } | ||
253 | |||
254 | let gen = Gen(self.db.gen.0 + 1); | ||
255 | let mut graph = self.db.graph.lock().clone(); | ||
256 | for id in invalidations.ids { | ||
257 | if let Some((gen, _)) = graph.get_mut(&id) { | ||
258 | *gen = INVALIDATED; | ||
259 | } | ||
260 | } | ||
261 | let graph = Mutex::new(graph); | ||
262 | Db { | ||
263 | db: Arc::new(DbState { ground_data, gen, graph }), | ||
264 | query_config: Arc::clone(&self.query_config) | ||
265 | } | ||
266 | } | ||
267 | pub fn query_ctx(&self) -> QueryCtx<T, D> { | ||
268 | QueryCtx::new(self) | ||
269 | } | ||
270 | pub fn get( | ||
271 | &self, | ||
272 | query_id: QueryId, | ||
273 | params: D, | ||
274 | ) -> (D, Vec<QueryTypeId>) { | ||
275 | let ctx = self.query_ctx(); | ||
276 | let res = ctx.get(query_id, params.into()); | ||
277 | let executed = ::std::mem::replace(&mut *ctx.executed.borrow_mut(), Vec::new()); | ||
278 | (res, executed) | ||
279 | } | ||
280 | } | ||
281 | |||
282 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
283 | struct Gen(u64); | ||
284 | const INVALIDATED: Gen = Gen(!0); | ||
285 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
286 | pub struct InputFingerprint(pub u64); | ||
287 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
288 | pub struct OutputFingerprint(pub u64); | ||
289 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
290 | pub struct QueryTypeId(pub u16); | ||
291 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
292 | pub struct QueryId(pub QueryTypeId, pub InputFingerprint); | ||
293 | |||
diff --git a/crates/salsa/tests/integration.rs b/crates/salsa/tests/integration.rs deleted file mode 100644 index aed9219be..000000000 --- a/crates/salsa/tests/integration.rs +++ /dev/null | |||
@@ -1,170 +0,0 @@ | |||
1 | extern crate salsa; | ||
2 | use std::{ | ||
3 | iter::once, | ||
4 | sync::Arc, | ||
5 | collections::hash_map::{HashMap, DefaultHasher}, | ||
6 | any::Any, | ||
7 | hash::{Hash, Hasher}, | ||
8 | }; | ||
9 | |||
10 | type State = HashMap<u32, String>; | ||
11 | type Data = Arc<Any + Send + Sync + 'static>; | ||
12 | const GET_TEXT: salsa::QueryTypeId = salsa::QueryTypeId(1); | ||
13 | const GET_FILES: salsa::QueryTypeId = salsa::QueryTypeId(2); | ||
14 | const FILE_NEWLINES: salsa::QueryTypeId = salsa::QueryTypeId(3); | ||
15 | const TOTAL_NEWLINES: salsa::QueryTypeId = salsa::QueryTypeId(4); | ||
16 | |||
17 | fn mk_ground_query<T, R>( | ||
18 | state: &State, | ||
19 | params: &Data, | ||
20 | f: fn(&State, &T) -> R, | ||
21 | ) -> (Data, salsa::OutputFingerprint) | ||
22 | where | ||
23 | T: 'static, | ||
24 | R: Hash + Send + Sync + 'static, | ||
25 | { | ||
26 | let params = params.downcast_ref().unwrap(); | ||
27 | let result = f(state, params); | ||
28 | let fingerprint = o_print(&result); | ||
29 | (Arc::new(result), fingerprint) | ||
30 | } | ||
31 | |||
32 | fn get<T, R>(db: &salsa::Db<State, Data>, query_type: salsa::QueryTypeId, param: T) -> (Arc<R>, Vec<salsa::QueryTypeId>) | ||
33 | where | ||
34 | T: Hash + Send + Sync + 'static, | ||
35 | R: Send + Sync + 'static, | ||
36 | { | ||
37 | let i_print = i_print(¶m); | ||
38 | let param = Arc::new(param); | ||
39 | let (res, trace) = db.get(salsa::QueryId(query_type, i_print), param); | ||
40 | (res.downcast().unwrap(), trace) | ||
41 | } | ||
42 | |||
43 | struct QueryCtx<'a>(&'a salsa::QueryCtx<State, Data>); | ||
44 | |||
45 | impl<'a> QueryCtx<'a> { | ||
46 | fn get_text(&self, id: u32) -> Arc<String> { | ||
47 | let i_print = i_print(&id); | ||
48 | let text = self.0.get(salsa::QueryId(GET_TEXT, i_print), Arc::new(id)); | ||
49 | text.downcast().unwrap() | ||
50 | } | ||
51 | fn get_files(&self) -> Arc<Vec<u32>> { | ||
52 | let i_print = i_print(&()); | ||
53 | let files = self.0.get(salsa::QueryId(GET_FILES, i_print), Arc::new(())); | ||
54 | let res = files.downcast().unwrap(); | ||
55 | res | ||
56 | } | ||
57 | fn get_n_lines(&self, id: u32) -> usize { | ||
58 | let i_print = i_print(&id); | ||
59 | let n_lines = self.0.get(salsa::QueryId(FILE_NEWLINES, i_print), Arc::new(id)); | ||
60 | *n_lines.downcast().unwrap() | ||
61 | } | ||
62 | } | ||
63 | |||
64 | fn mk_query<T, R>( | ||
65 | query_ctx: &salsa::QueryCtx<State, Data>, | ||
66 | params: &Data, | ||
67 | f: fn(QueryCtx, &T) -> R, | ||
68 | ) -> (Data, salsa::OutputFingerprint) | ||
69 | where | ||
70 | T: 'static, | ||
71 | R: Hash + Send + Sync + 'static, | ||
72 | { | ||
73 | let params: &T = params.downcast_ref().unwrap(); | ||
74 | let query_ctx = QueryCtx(query_ctx); | ||
75 | let result = f(query_ctx, params); | ||
76 | let fingerprint = o_print(&result); | ||
77 | (Arc::new(result), fingerprint) | ||
78 | } | ||
79 | |||
80 | fn mk_queries() -> salsa::QueryConfig<State, Data> { | ||
81 | salsa::QueryConfig::<State, Data>::new() | ||
82 | .with_ground_query(GET_TEXT, Box::new(|state, id| { | ||
83 | mk_ground_query::<u32, String>(state, id, |state, id| state[id].clone()) | ||
84 | })) | ||
85 | .with_ground_query(GET_FILES, Box::new(|state, id| { | ||
86 | mk_ground_query::<(), Vec<u32>>(state, id, |state, &()| state.keys().cloned().collect()) | ||
87 | })) | ||
88 | .with_query(FILE_NEWLINES, Box::new(|query_ctx, id| { | ||
89 | mk_query(query_ctx, id, |query_ctx, &id| { | ||
90 | let text = query_ctx.get_text(id); | ||
91 | text.lines().count() | ||
92 | }) | ||
93 | })) | ||
94 | .with_query(TOTAL_NEWLINES, Box::new(|query_ctx, id| { | ||
95 | mk_query(query_ctx, id, |query_ctx, &()| { | ||
96 | let mut total = 0; | ||
97 | for &id in query_ctx.get_files().iter() { | ||
98 | total += query_ctx.get_n_lines(id) | ||
99 | } | ||
100 | total | ||
101 | }) | ||
102 | })) | ||
103 | } | ||
104 | |||
105 | #[test] | ||
106 | fn test_number_of_lines() { | ||
107 | let mut state = State::new(); | ||
108 | let db = salsa::Db::new(mk_queries(), state.clone()); | ||
109 | let (newlines, trace) = get::<(), usize>(&db, TOTAL_NEWLINES, ()); | ||
110 | assert_eq!(*newlines, 0); | ||
111 | assert_eq!(trace.len(), 2); | ||
112 | let (newlines, trace) = get::<(), usize>(&db, TOTAL_NEWLINES, ()); | ||
113 | assert_eq!(*newlines, 0); | ||
114 | assert_eq!(trace.len(), 0); | ||
115 | |||
116 | state.insert(1, "hello\nworld".to_string()); | ||
117 | let mut inv = salsa::Invalidations::new(); | ||
118 | inv.invalidate(GET_TEXT, once(i_print(&1u32))); | ||
119 | inv.invalidate(GET_FILES, once(i_print(&()))); | ||
120 | let db = db.with_ground_data(state.clone(), inv); | ||
121 | let (newlines, trace) = get::<(), usize>(&db, TOTAL_NEWLINES, ()); | ||
122 | assert_eq!(*newlines, 2); | ||
123 | assert_eq!(trace.len(), 4); | ||
124 | |||
125 | state.insert(2, "spam\neggs".to_string()); | ||
126 | let mut inv = salsa::Invalidations::new(); | ||
127 | inv.invalidate(GET_TEXT, once(i_print(&2u32))); | ||
128 | inv.invalidate(GET_FILES, once(i_print(&()))); | ||
129 | let db = db.with_ground_data(state.clone(), inv); | ||
130 | let (newlines, trace) = get::<(), usize>(&db, TOTAL_NEWLINES, ()); | ||
131 | assert_eq!(*newlines, 4); | ||
132 | assert_eq!(trace.len(), 4); | ||
133 | |||
134 | let mut invs = vec![]; | ||
135 | for i in 0..10 { | ||
136 | let id = i + 10; | ||
137 | invs.push(i_print(&id)); | ||
138 | state.insert(id, "spam".to_string()); | ||
139 | } | ||
140 | let mut inv = salsa::Invalidations::new(); | ||
141 | inv.invalidate(GET_TEXT, invs.into_iter()); | ||
142 | inv.invalidate(GET_FILES, once(i_print(&()))); | ||
143 | let db = db.with_ground_data(state.clone(), inv); | ||
144 | let (newlines, trace) = get::<(), usize>(&db, TOTAL_NEWLINES, ()); | ||
145 | assert_eq!(*newlines, 14); | ||
146 | assert_eq!(trace.len(), 22); | ||
147 | |||
148 | state.insert(15, String::new()); | ||
149 | let mut inv = salsa::Invalidations::new(); | ||
150 | inv.invalidate(GET_TEXT, once(i_print(&15u32))); | ||
151 | inv.invalidate(GET_FILES, once(i_print(&()))); | ||
152 | let db = db.with_ground_data(state.clone(), inv); | ||
153 | let (newlines, trace) = get::<(), usize>(&db, TOTAL_NEWLINES, ()); | ||
154 | assert_eq!(*newlines, 13); | ||
155 | assert_eq!(trace.len(), 4); | ||
156 | } | ||
157 | |||
158 | fn o_print<T: Hash>(x: &T) -> salsa::OutputFingerprint { | ||
159 | let mut hasher = DefaultHasher::new(); | ||
160 | x.hash(&mut hasher); | ||
161 | let hash = hasher.finish(); | ||
162 | salsa::OutputFingerprint(hash) | ||
163 | } | ||
164 | |||
165 | fn i_print<T: Hash>(x: &T) -> salsa::InputFingerprint { | ||
166 | let mut hasher = DefaultHasher::new(); | ||
167 | x.hash(&mut hasher); | ||
168 | let hash = hasher.finish(); | ||
169 | salsa::InputFingerprint(hash) | ||
170 | } | ||
diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml index 41316581e..fe0998ab8 100644 --- a/crates/test_utils/Cargo.toml +++ b/crates/test_utils/Cargo.toml | |||
@@ -1,4 +1,5 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | ||
2 | name = "test_utils" | 3 | name = "test_utils" |
3 | version = "0.1.0" | 4 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 068eb80ce..ee73153f0 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -38,22 +38,44 @@ pub fn assert_eq_dbg(expected: &str, actual: &impl fmt::Debug) { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn extract_offset(text: &str) -> (TextUnit, String) { | 40 | pub fn extract_offset(text: &str) -> (TextUnit, String) { |
41 | let cursor = "<|>"; | 41 | match try_extract_offset(text) { |
42 | let cursor_pos = match text.find(cursor) { | ||
43 | None => panic!("text should contain cursor marker"), | 42 | None => panic!("text should contain cursor marker"), |
44 | Some(pos) => pos, | 43 | Some(result) => result, |
45 | }; | 44 | } |
45 | } | ||
46 | |||
47 | pub fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> { | ||
48 | let cursor = "<|>"; | ||
49 | let cursor_pos = text.find(cursor)?; | ||
46 | let mut new_text = String::with_capacity(text.len() - cursor.len()); | 50 | let mut new_text = String::with_capacity(text.len() - cursor.len()); |
47 | new_text.push_str(&text[..cursor_pos]); | 51 | new_text.push_str(&text[..cursor_pos]); |
48 | new_text.push_str(&text[cursor_pos + cursor.len()..]); | 52 | new_text.push_str(&text[cursor_pos + cursor.len()..]); |
49 | let cursor_pos = TextUnit::from(cursor_pos as u32); | 53 | let cursor_pos = TextUnit::from(cursor_pos as u32); |
50 | (cursor_pos, new_text) | 54 | Some((cursor_pos, new_text)) |
51 | } | 55 | } |
52 | 56 | ||
53 | pub fn extract_range(text: &str) -> (TextRange, String) { | 57 | pub fn extract_range(text: &str) -> (TextRange, String) { |
54 | let (start, text) = extract_offset(text); | 58 | match try_extract_range(text) { |
55 | let (end, text) = extract_offset(&text); | 59 | None => panic!("text should contain cursor marker"), |
56 | (TextRange::from_to(start, end), text) | 60 | Some(result) => result, |
61 | } | ||
62 | } | ||
63 | |||
64 | pub fn try_extract_range(text: &str) -> Option<(TextRange, String)> { | ||
65 | let (start, text) = try_extract_offset(text)?; | ||
66 | let (end, text) = try_extract_offset(&text)?; | ||
67 | Some((TextRange::from_to(start, end), text)) | ||
68 | } | ||
69 | |||
70 | pub fn extract_ranges(text: &str) -> (Vec<TextRange>, String) { | ||
71 | let mut ranges = Vec::new(); | ||
72 | let mut text = String::from(text); | ||
73 | while let Some((range, new_text)) = try_extract_range(&text) { | ||
74 | text = new_text; | ||
75 | ranges.push(range); | ||
76 | } | ||
77 | |||
78 | (ranges, text) | ||
57 | } | 79 | } |
58 | 80 | ||
59 | pub fn add_cursor(text: &str, offset: TextUnit) -> String { | 81 | pub fn add_cursor(text: &str, offset: TextUnit) -> String { |
diff --git a/crates/tools/Cargo.toml b/crates/tools/Cargo.toml index d03910986..e2fecc60d 100644 --- a/crates/tools/Cargo.toml +++ b/crates/tools/Cargo.toml | |||
@@ -1,4 +1,5 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | ||
2 | name = "tools" | 3 | name = "tools" |
3 | version = "0.1.0" | 4 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index ff8f23c7a..d1c525f68 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -20,8 +20,8 @@ export function activate(context: vscode.ExtensionContext) { | |||
20 | f: (...args: any[]) => Promise<boolean> | 20 | f: (...args: any[]) => Promise<boolean> |
21 | ) { | 21 | ) { |
22 | const defaultCmd = `default:${name}`; | 22 | const defaultCmd = `default:${name}`; |
23 | const original = async (...args: any[]) => | 23 | const original = (...args: any[]) => |
24 | await vscode.commands.executeCommand(defaultCmd, ...args); | 24 | vscode.commands.executeCommand(defaultCmd, ...args); |
25 | 25 | ||
26 | registerCommand(name, async (...args: any[]) => { | 26 | registerCommand(name, async (...args: any[]) => { |
27 | const editor = vscode.window.activeTextEditor; | 27 | const editor = vscode.window.activeTextEditor; |