diff options
28 files changed, 171 insertions, 112 deletions
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 9c404f4c3..79adc9321 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md | |||
@@ -1,6 +1,6 @@ | |||
1 | # Architecture | 1 | # Architecture |
2 | 2 | ||
3 | This document describes high-level architecture of rust-analyzer. | 3 | This document describes the high-level architecture of rust-analyzer. |
4 | If you want to familiarize yourself with the code base, you are just | 4 | If you want to familiarize yourself with the code base, you are just |
5 | in the right place! | 5 | in the right place! |
6 | 6 | ||
@@ -12,10 +12,10 @@ On the highest level, rust-analyzer is a thing which accepts input source code | |||
12 | from the client and produces a structured semantic model of the code. | 12 | from the client and produces a structured semantic model of the code. |
13 | 13 | ||
14 | More specifically, input data consists of a set of test files (`(PathBuf, | 14 | More specifically, input data consists of a set of test files (`(PathBuf, |
15 | String)` pairs) and an information about project structure, the so called | 15 | String)` pairs) and information about project structure, captured in the so called |
16 | `CrateGraph`. Crate graph specifies which files are crate roots, which cfg flags | 16 | `CrateGraph`. The crate graph specifies which files are crate roots, which cfg |
17 | are specified for each crate (TODO: actually implement this) and what are | 17 | flags are specified for each crate (TODO: actually implement this) and what |
18 | dependencies between the crates. The analyzer keeps all these input data in | 18 | dependencies exist between the crates. The analyzer keeps all this input data in |
19 | memory and never does any IO. Because the input data is source code, which | 19 | memory and never does any IO. Because the input data is source code, which |
20 | typically measures in tens of megabytes at most, keeping all input data in | 20 | typically measures in tens of megabytes at most, keeping all input data in |
21 | memory is OK. | 21 | memory is OK. |
@@ -28,8 +28,8 @@ declarations, etc. | |||
28 | The client can submit a small delta of input data (typically, a change to a | 28 | The client can submit a small delta of input data (typically, a change to a |
29 | single file) and get a fresh code model which accounts for changes. | 29 | single file) and get a fresh code model which accounts for changes. |
30 | 30 | ||
31 | Underlying engine makes sure that model is computed lazily (on-demand) and can | 31 | The underlying engine makes sure that model is computed lazily (on-demand) and |
32 | be quickly updated for small modifications. | 32 | can be quickly updated for small modifications. |
33 | 33 | ||
34 | 34 | ||
35 | ## Code generation | 35 | ## Code generation |
@@ -37,7 +37,7 @@ be quickly updated for small modifications. | |||
37 | Some of the components of this repository are generated through automatic | 37 | Some of the components of this repository are generated through automatic |
38 | processes. These are outlined below: | 38 | processes. These are outlined below: |
39 | 39 | ||
40 | - `gen-syntax`: The kinds of tokens are reused in several places, so a generator | 40 | - `gen-syntax`: The kinds of tokens that are reused in several places, so a generator |
41 | is used. We use tera templates to generate the files listed below, based on | 41 | is used. We use tera templates to generate the files listed below, based on |
42 | the grammar described in [grammar.ron]: | 42 | the grammar described in [grammar.ron]: |
43 | - [ast/generated.rs][ast generated] in `ra_syntax` based on | 43 | - [ast/generated.rs][ast generated] in `ra_syntax` based on |
@@ -58,17 +58,16 @@ processes. These are outlined below: | |||
58 | ### `crates/ra_syntax` | 58 | ### `crates/ra_syntax` |
59 | 59 | ||
60 | Rust syntax tree structure and parser. See | 60 | Rust syntax tree structure and parser. See |
61 | [RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design | 61 | [RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design notes. |
62 | notes. | ||
63 | 62 | ||
64 | - [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees. | 63 | - [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees. |
65 | - `grammar` module is the actual parser. It is a hand-written recursive descent parsers, which | 64 | - `grammar` module is the actual parser. It is a hand-written recursive descent parser, which |
66 | 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), | 65 | produces a sequence of events like "start node X", "finish not Y". It works similarly to [kotlin's parser](https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java), |
67 | 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) | 66 | which is a good source of 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) |
68 | is what we use for the definition of the Rust language. | 67 | is what we use for the definition of the Rust language. |
69 | - `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `rowan` trees. | 68 | - `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `rowan` trees. |
70 | This is the thing that turns a flat list of events into a tree (see `EventProcessor`) | 69 | This is the thing that turns a flat list of events into a tree (see `EventProcessor`) |
71 | - `ast` a type safe API on top of the raw `rowan` tree. | 70 | - `ast` provides a type safe API on top of the raw `rowan` tree. |
72 | - `grammar.ron` RON description of the grammar, which is used to | 71 | - `grammar.ron` RON description of the grammar, which is used to |
73 | generate `syntax_kinds` and `ast` modules, using `cargo gen-syntax` command. | 72 | generate `syntax_kinds` and `ast` modules, using `cargo gen-syntax` command. |
74 | - `algo`: generic tree algorithms, including `walk` for O(1) stack | 73 | - `algo`: generic tree algorithms, including `walk` for O(1) stack |
@@ -90,7 +89,7 @@ fixes a bug in the grammar. | |||
90 | We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and | 89 | We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and |
91 | on-demand computation. Roughly, you can think of salsa as a key-value store, but | 90 | on-demand computation. Roughly, you can think of salsa as a key-value store, but |
92 | it also can compute derived values using specified functions. The `ra_db` crate | 91 | it also can compute derived values using specified functions. The `ra_db` crate |
93 | provides a basic infrastructure for interacting with salsa. Crucially, it | 92 | provides basic infrastructure for interacting with salsa. Crucially, it |
94 | defines most of the "input" queries: facts supplied by the client of the | 93 | defines most of the "input" queries: facts supplied by the client of the |
95 | analyzer. Reading the docs of the `ra_db::input` module should be useful: | 94 | analyzer. Reading the docs of the `ra_db::input` module should be useful: |
96 | everything else is strictly derived from those inputs. | 95 | everything else is strictly derived from those inputs. |
@@ -102,7 +101,7 @@ HIR provides high-level "object oriented" access to Rust code. | |||
102 | The principal difference between HIR and syntax trees is that HIR is bound to a | 101 | The principal difference between HIR and syntax trees is that HIR is bound to a |
103 | particular crate instance. That is, it has cfg flags and features applied (in | 102 | particular crate instance. That is, it has cfg flags and features applied (in |
104 | theory, in practice this is to be implemented). So, the relation between | 103 | theory, in practice this is to be implemented). So, the relation between |
105 | syntax and HIR is many-to-one. The `source_binder` modules is responsible for | 104 | syntax and HIR is many-to-one. The `source_binder` module is responsible for |
106 | guessing a HIR for a particular source position. | 105 | guessing a HIR for a particular source position. |
107 | 106 | ||
108 | Underneath, HIR works on top of salsa, using a `HirDatabase` trait. | 107 | Underneath, HIR works on top of salsa, using a `HirDatabase` trait. |
@@ -111,12 +110,12 @@ Underneath, HIR works on top of salsa, using a `HirDatabase` trait. | |||
111 | 110 | ||
112 | A stateful library for analyzing many Rust files as they change. `AnalysisHost` | 111 | A stateful library for analyzing many Rust files as they change. `AnalysisHost` |
113 | is a mutable entity (clojure's atom) which holds the current state, incorporates | 112 | is a mutable entity (clojure's atom) which holds the current state, incorporates |
114 | changes and handles out `Analysis` --- an immutable and consistent snapshot of | 113 | changes and hands out `Analysis` --- an immutable and consistent snapshot of |
115 | world state at a point in time, which actually powers analysis. | 114 | the world state at a point in time, which actually powers analysis. |
116 | 115 | ||
117 | One interesting aspect of analysis is its support for cancellation. When a | 116 | One interesting aspect of analysis is its support for cancellation. When a |
118 | change is applied to `AnalysisHost`, first all currently active snapshots are | 117 | change is applied to `AnalysisHost`, first all currently active snapshots are |
119 | cancelled. Only after all snapshots are dropped the change actually affects the | 118 | canceled. Only after all snapshots are dropped the change actually affects the |
120 | database. | 119 | database. |
121 | 120 | ||
122 | APIs in this crate are IDE centric: they take text offsets as input and produce | 121 | APIs in this crate are IDE centric: they take text offsets as input and produce |
@@ -142,7 +141,7 @@ An LSP implementation which wraps `ra_ide_api` into a langauge server protocol. | |||
142 | 141 | ||
143 | ### `crates/ra_vfs` | 142 | ### `crates/ra_vfs` |
144 | 143 | ||
145 | Although `hir` and `ra_ide_api` don't do any io, we need to be able to read | 144 | Although `hir` and `ra_ide_api` don't do any IO, we need to be able to read |
146 | files from disk at the end of the day. This is what `ra_vfs` does. It also | 145 | files from disk at the end of the day. This is what `ra_vfs` does. It also |
147 | manages overlays: "dirty" files in the editor, whose "true" contents is | 146 | manages overlays: "dirty" files in the editor, whose "true" contents is |
148 | different from data on disk. | 147 | different from data on disk. |
@@ -175,16 +174,16 @@ VS Code plugin | |||
175 | ## Common workflows | 174 | ## Common workflows |
176 | 175 | ||
177 | To try out VS Code extensions, run `cargo install-code`. This installs both the | 176 | To try out VS Code extensions, run `cargo install-code`. This installs both the |
178 | `ra_lsp_server` binary and VS Code extension. To install only the binary, use | 177 | `ra_lsp_server` binary and the VS Code extension. To install only the binary, use |
179 | `cargo install --path crates/ra_lsp_server --force` | 178 | `cargo install --path crates/ra_lsp_server --force` |
180 | 179 | ||
181 | To see logs from the language server, set `RUST_LOG=info` env variable. To see | 180 | To see logs from the language server, set `RUST_LOG=info` env variable. To see |
182 | all communication between the server and the client, use | 181 | all communication between the server and the client, use |
183 | `RUST_LOG=gen_lsp_server=debug` (will print quite a bit of stuff). | 182 | `RUST_LOG=gen_lsp_server=debug` (this will print quite a bit of stuff). |
184 | 183 | ||
185 | To run tests, just `cargo test`. | 184 | To run tests, just `cargo test`. |
186 | 185 | ||
187 | To work on VS Code extension, launch code inside `editors/code` and use `F5` to | 186 | To work on the VS Code extension, launch code inside `editors/code` and use `F5` to |
188 | launch/debug. To automatically apply formatter and linter suggestions, use `npm | 187 | launch/debug. To automatically apply formatter and linter suggestions, use `npm |
189 | run fix`. | 188 | run fix`. |
190 | 189 | ||
diff --git a/crates/gen_lsp_server/src/lib.rs b/crates/gen_lsp_server/src/lib.rs index b20652928..16ac799ac 100644 --- a/crates/gen_lsp_server/src/lib.rs +++ b/crates/gen_lsp_server/src/lib.rs | |||
@@ -78,10 +78,10 @@ pub use crate::{ | |||
78 | }; | 78 | }; |
79 | 79 | ||
80 | /// Main entry point: runs the server from initialization to shutdown. | 80 | /// Main entry point: runs the server from initialization to shutdown. |
81 | /// To attach server to standard input/output streams, use `stdio_transport` | 81 | /// To attach server to standard input/output streams, use the `stdio_transport` |
82 | /// function to create corresponding `sender` and `receiver` pair. | 82 | /// function to create corresponding `sender` and `receiver` pair. |
83 | /// | 83 | /// |
84 | ///`server` should use `handle_shutdown` function to handle the `Shutdown` | 84 | /// `server` should use the `handle_shutdown` function to handle the `Shutdown` |
85 | /// request. | 85 | /// request. |
86 | pub fn run_server( | 86 | pub fn run_server( |
87 | caps: ServerCapabilities, | 87 | caps: ServerCapabilities, |
@@ -104,7 +104,7 @@ pub fn run_server( | |||
104 | Ok(()) | 104 | Ok(()) |
105 | } | 105 | } |
106 | 106 | ||
107 | /// if `req` is `Shutdown`, respond to it and return `None`, otherwise return `Some(req)` | 107 | /// If `req` is `Shutdown`, respond to it and return `None`, otherwise return `Some(req)` |
108 | pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> { | 108 | pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> { |
109 | match req.cast::<Shutdown>() { | 109 | match req.cast::<Shutdown>() { |
110 | Ok((id, ())) => { | 110 | Ok((id, ())) => { |
diff --git a/crates/gen_lsp_server/src/msg.rs b/crates/gen_lsp_server/src/msg.rs index f68cbc541..94bef374c 100644 --- a/crates/gen_lsp_server/src/msg.rs +++ b/crates/gen_lsp_server/src/msg.rs | |||
@@ -54,7 +54,7 @@ pub enum ErrorCode { | |||
54 | ServerErrorEnd = -32000, | 54 | ServerErrorEnd = -32000, |
55 | ServerNotInitialized = -32002, | 55 | ServerNotInitialized = -32002, |
56 | UnknownErrorCode = -32001, | 56 | UnknownErrorCode = -32001, |
57 | RequestCancelled = -32800, | 57 | RequestCanceled = -32800, |
58 | ContentModified = -32801, | 58 | ContentModified = -32801, |
59 | } | 59 | } |
60 | 60 | ||
diff --git a/crates/ra_db/src/cancelation.rs b/crates/ra_db/src/cancellation.rs index 56ce27bff..8d38eebfb 100644 --- a/crates/ra_db/src/cancelation.rs +++ b/crates/ra_db/src/cancellation.rs | |||
@@ -8,11 +8,11 @@ | |||
8 | //! * user types next character, while syntax highlighting *is still in | 8 | //! * user types next character, while syntax highlighting *is still in |
9 | //! progress*. | 9 | //! progress*. |
10 | //! | 10 | //! |
11 | //! In this situation, we want to react to modification as quckly as possible. | 11 | //! In this situation, we want to react to modification as quickly as possible. |
12 | //! At the same time, in-progress results are not very interesting, because they | 12 | //! At the same time, in-progress results are not very interesting, because they |
13 | //! are invalidated by the edit anyway. So, we first cancel all in-flight | 13 | //! are invalidated by the edit anyway. So, we first cancel all in-flight |
14 | //! requests, and then apply modification knowing that it won't intrfere with | 14 | //! requests, and then apply modification knowing that it won't interfere with |
15 | //! any background processing (this bit is handled by salsa, see | 15 | //! any background processing (this bit is handled by salsa, see the |
16 | //! `BaseDatabase::check_canceled` method). | 16 | //! `BaseDatabase::check_canceled` method). |
17 | 17 | ||
18 | /// An "error" signifing that the operation was canceled. | 18 | /// An "error" signifing that the operation was canceled. |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 7c3dd9296..023183e29 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | /// This modules specifies the input to rust-analyzer. In some sense, this is | 1 | /// This module specifies the input to rust-analyzer. In some sense, this is |
2 | /// **the** most important module, because all other fancy stuff is strictly | 2 | /// **the** most important module, because all other fancy stuff is strictly |
3 | /// derived from this input. | 3 | /// derived from this input. |
4 | /// | 4 | /// |
5 | /// Note that neither this module, nor any other part of the analyzer's core do | 5 | /// Note that neither this module, nor any other part of the analyzer's core do |
6 | /// actual IO. See `vfs` and `project_model` in `ra_lsp_server` crate for how | 6 | /// actual IO. See `vfs` and `project_model` in the `ra_lsp_server` crate for how |
7 | /// actual IO is done and lowered to input. | 7 | /// actual IO is done and lowered to input. |
8 | use std::sync::Arc; | 8 | use std::sync::Arc; |
9 | 9 | ||
@@ -17,17 +17,17 @@ use rustc_hash::FxHashSet; | |||
17 | /// `FileId` is an integer which uniquely identifies a file. File paths are | 17 | /// `FileId` is an integer which uniquely identifies a file. File paths are |
18 | /// messy and system-dependent, so most of the code should work directly with | 18 | /// messy and system-dependent, so most of the code should work directly with |
19 | /// `FileId`, without inspecting the path. The mapping between `FileId` and path | 19 | /// `FileId`, without inspecting the path. The mapping between `FileId` and path |
20 | /// and `SourceRoot` is constant. File rename is represented as a pair of | 20 | /// and `SourceRoot` is constant. A file rename is represented as a pair of |
21 | /// deletion/creation. | 21 | /// deletion/creation. |
22 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 22 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
23 | pub struct FileId(pub u32); | 23 | pub struct FileId(pub u32); |
24 | 24 | ||
25 | /// Files are grouped into source roots. A source root is a directory on the | 25 | /// Files are grouped into source roots. A source root is a directory on the |
26 | /// file systems which is watched for changes. Typically it corresponds to a | 26 | /// file systems which is watched for changes. Typically it corresponds to a |
27 | /// Cargo package. Source roots *might* be nested: in this case, file belongs to | 27 | /// Rust crate. Source roots *might* be nested: in this case, a file belongs to |
28 | /// the nearest enclosing source root. Path to files are always relative to a | 28 | /// the nearest enclosing source root. Paths to files are always relative to a |
29 | /// source root, and analyzer does not know the root path of the source root at | 29 | /// source root, and the analyzer does not know the root path of the source root at |
30 | /// all. So, a file from one source root can't refere a file in another source | 30 | /// all. So, a file from one source root can't refer to a file in another source |
31 | /// root by path. | 31 | /// root by path. |
32 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] | 32 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] |
33 | pub struct SourceRootId(pub u32); | 33 | pub struct SourceRootId(pub u32); |
@@ -38,15 +38,15 @@ pub struct SourceRoot { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | /// `CrateGraph` is a bit of information which turns a set of text files into a | 40 | /// `CrateGraph` is a bit of information which turns a set of text files into a |
41 | /// number of Rust crates. Each Crate is the `FileId` of it's root module, the | 41 | /// number of Rust crates. Each crate is defined by the `FileId` of its root module, |
42 | /// set of cfg flags (not yet implemented) and the set of dependencies. Note | 42 | /// the set of cfg flags (not yet implemented) and the set of dependencies. Note |
43 | /// that, due to cfg's, there might be several crates for a single `FileId`! As | 43 | /// that, due to cfg's, there might be several crates for a single `FileId`! As |
44 | /// in the rust-lang proper, a crate does not have a name. Instead, names are | 44 | /// in the rust-lang proper, a crate does not have a name. Instead, names are |
45 | /// specified on dependency edges. That is, a crate might be known under | 45 | /// specified on dependency edges. That is, a crate might be known under |
46 | /// different names in different dependant crates. | 46 | /// different names in different dependent crates. |
47 | /// | 47 | /// |
48 | /// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust | 48 | /// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust |
49 | /// langauge proper, not a concept of the build system. In practice, we get | 49 | /// language proper, not a concept of the build system. In practice, we get |
50 | /// `CrateGraph` by lowering `cargo metadata` output. | 50 | /// `CrateGraph` by lowering `cargo metadata` output. |
51 | #[derive(Debug, Clone, Default, PartialEq, Eq)] | 51 | #[derive(Debug, Clone, Default, PartialEq, Eq)] |
52 | pub struct CrateGraph { | 52 | pub struct CrateGraph { |
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index e680d9fc3..fb8ea2496 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! ra_db defines basic database traits. Concrete DB is defined by ra_ide_api. | 1 | //! ra_db defines basic database traits. The concrete DB is defined by ra_ide_api. |
2 | mod cancelation; | 2 | mod cancellation; |
3 | mod syntax_ptr; | 3 | mod syntax_ptr; |
4 | mod input; | 4 | mod input; |
5 | mod loc2id; | 5 | mod loc2id; |
@@ -8,7 +8,7 @@ pub mod mock; | |||
8 | use ra_syntax::{TextUnit, TextRange, SourceFile, TreePtr}; | 8 | use ra_syntax::{TextUnit, TextRange, SourceFile, TreePtr}; |
9 | 9 | ||
10 | pub use crate::{ | 10 | pub use crate::{ |
11 | cancelation::{Canceled, Cancelable}, | 11 | cancellation::{Canceled, Cancelable}, |
12 | syntax_ptr::LocalSyntaxPtr, | 12 | syntax_ptr::LocalSyntaxPtr, |
13 | input::{ | 13 | input::{ |
14 | FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, | 14 | FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, |
diff --git a/crates/ra_db/src/loc2id.rs b/crates/ra_db/src/loc2id.rs index 1d6761897..254c52629 100644 --- a/crates/ra_db/src/loc2id.rs +++ b/crates/ra_db/src/loc2id.rs | |||
@@ -5,7 +5,7 @@ use rustc_hash::FxHashMap; | |||
5 | use ra_arena::{Arena, ArenaId}; | 5 | use ra_arena::{Arena, ArenaId}; |
6 | 6 | ||
7 | /// There are two principle ways to refer to things: | 7 | /// There are two principle ways to refer to things: |
8 | /// - by their locatinon (module in foo/bar/baz.rs at line 42) | 8 | /// - by their location (module in foo/bar/baz.rs at line 42) |
9 | /// - by their numeric id (module `ModuleId(42)`) | 9 | /// - by their numeric id (module `ModuleId(42)`) |
10 | /// | 10 | /// |
11 | /// The first one is more powerful (you can actually find the thing in question | 11 | /// The first one is more powerful (you can actually find the thing in question |
@@ -13,7 +13,7 @@ use ra_arena::{Arena, ArenaId}; | |||
13 | /// | 13 | /// |
14 | /// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a | 14 | /// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a |
15 | /// bidirectional mapping between positional and numeric ids, we can use compact | 15 | /// bidirectional mapping between positional and numeric ids, we can use compact |
16 | /// representation wich still allows us to get the actual item | 16 | /// representation which still allows us to get the actual item. |
17 | #[derive(Debug)] | 17 | #[derive(Debug)] |
18 | struct Loc2IdMap<LOC, ID> | 18 | struct Loc2IdMap<LOC, ID> |
19 | where | 19 | where |
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 902032e14..66c016180 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -13,8 +13,8 @@ use crate::{ | |||
13 | ty::InferenceResult, | 13 | ty::InferenceResult, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | /// hir::Crate describes a single crate. It's the main inteface with which | 16 | /// hir::Crate describes a single crate. It's the main interface with which |
17 | /// crate's dependencies interact. Mostly, it should be just a proxy for the | 17 | /// a crate's dependencies interact. Mostly, it should be just a proxy for the |
18 | /// root module. | 18 | /// root module. |
19 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 19 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
20 | pub struct Crate { | 20 | pub struct Crate { |
@@ -75,9 +75,10 @@ impl Module { | |||
75 | } | 75 | } |
76 | 76 | ||
77 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. | 77 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. |
78 | pub fn defenition_source(&self, db: &impl HirDatabase) -> Cancelable<(FileId, ModuleSource)> { | 78 | pub fn definition_source(&self, db: &impl HirDatabase) -> Cancelable<(FileId, ModuleSource)> { |
79 | self.defenition_source_impl(db) | 79 | self.definition_source_impl(db) |
80 | } | 80 | } |
81 | |||
81 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. | 82 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. |
82 | /// `None` for the crate root. | 83 | /// `None` for the crate root. |
83 | pub fn declaration_source( | 84 | pub fn declaration_source( |
@@ -91,20 +92,24 @@ impl Module { | |||
91 | pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { | 92 | pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { |
92 | self.krate_impl(db) | 93 | self.krate_impl(db) |
93 | } | 94 | } |
95 | |||
94 | /// Topmost parent of this module. Every module has a `crate_root`, but some | 96 | /// Topmost parent of this module. Every module has a `crate_root`, but some |
95 | /// might miss `krate`. This can happen if a module's file is not included | 97 | /// might be missing `krate`. This can happen if a module's file is not included |
96 | /// into any module tree of any target from Cargo.toml. | 98 | /// in the module tree of any target in Cargo.toml. |
97 | pub fn crate_root(&self, db: &impl HirDatabase) -> Cancelable<Module> { | 99 | pub fn crate_root(&self, db: &impl HirDatabase) -> Cancelable<Module> { |
98 | self.crate_root_impl(db) | 100 | self.crate_root_impl(db) |
99 | } | 101 | } |
102 | |||
100 | /// Finds a child module with the specified name. | 103 | /// Finds a child module with the specified name. |
101 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 104 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { |
102 | self.child_impl(db, name) | 105 | self.child_impl(db, name) |
103 | } | 106 | } |
107 | |||
104 | /// Finds a parent module. | 108 | /// Finds a parent module. |
105 | pub fn parent(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | 109 | pub fn parent(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { |
106 | self.parent_impl(db) | 110 | self.parent_impl(db) |
107 | } | 111 | } |
112 | |||
108 | pub fn path_to_root(&self, db: &impl HirDatabase) -> Cancelable<Vec<Module>> { | 113 | pub fn path_to_root(&self, db: &impl HirDatabase) -> Cancelable<Vec<Module>> { |
109 | let mut res = vec![self.clone()]; | 114 | let mut res = vec![self.clone()]; |
110 | let mut curr = self.clone(); | 115 | let mut curr = self.clone(); |
@@ -114,13 +119,16 @@ impl Module { | |||
114 | } | 119 | } |
115 | Ok(res) | 120 | Ok(res) |
116 | } | 121 | } |
122 | |||
117 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 123 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
118 | pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { | 124 | pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { |
119 | self.scope_impl(db) | 125 | self.scope_impl(db) |
120 | } | 126 | } |
127 | |||
121 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable<PerNs<DefId>> { | 128 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable<PerNs<DefId>> { |
122 | self.resolve_path_impl(db, path) | 129 | self.resolve_path_impl(db, path) |
123 | } | 130 | } |
131 | |||
124 | pub fn problems( | 132 | pub fn problems( |
125 | &self, | 133 | &self, |
126 | db: &impl HirDatabase, | 134 | db: &impl HirDatabase, |
@@ -140,6 +148,7 @@ impl StructField { | |||
140 | pub fn name(&self) -> &Name { | 148 | pub fn name(&self) -> &Name { |
141 | &self.name | 149 | &self.name |
142 | } | 150 | } |
151 | |||
143 | pub fn type_ref(&self) -> &TypeRef { | 152 | pub fn type_ref(&self) -> &TypeRef { |
144 | &self.type_ref | 153 | &self.type_ref |
145 | } | 154 | } |
@@ -160,18 +169,21 @@ impl VariantData { | |||
160 | _ => &[], | 169 | _ => &[], |
161 | } | 170 | } |
162 | } | 171 | } |
172 | |||
163 | pub fn is_struct(&self) -> bool { | 173 | pub fn is_struct(&self) -> bool { |
164 | match self { | 174 | match self { |
165 | VariantData::Struct(..) => true, | 175 | VariantData::Struct(..) => true, |
166 | _ => false, | 176 | _ => false, |
167 | } | 177 | } |
168 | } | 178 | } |
179 | |||
169 | pub fn is_tuple(&self) -> bool { | 180 | pub fn is_tuple(&self) -> bool { |
170 | match self { | 181 | match self { |
171 | VariantData::Tuple(..) => true, | 182 | VariantData::Tuple(..) => true, |
172 | _ => false, | 183 | _ => false, |
173 | } | 184 | } |
174 | } | 185 | } |
186 | |||
175 | pub fn is_unit(&self) -> bool { | 187 | pub fn is_unit(&self) -> bool { |
176 | match self { | 188 | match self { |
177 | VariantData::Unit => true, | 189 | VariantData::Unit => true, |
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 56e14fac1..1cb408cff 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -37,7 +37,7 @@ impl Module { | |||
37 | Ok(Some(link.name(&module_tree).clone())) | 37 | Ok(Some(link.name(&module_tree).clone())) |
38 | } | 38 | } |
39 | 39 | ||
40 | pub fn defenition_source_impl( | 40 | pub fn definition_source_impl( |
41 | &self, | 41 | &self, |
42 | db: &impl HirDatabase, | 42 | db: &impl HirDatabase, |
43 | ) -> Cancelable<(FileId, ModuleSource)> { | 43 | ) -> Cancelable<(FileId, ModuleSource)> { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 07cf0d10a..7dbe93f2b 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -26,6 +26,7 @@ pub trait HirDatabase: SyntaxDatabase | |||
26 | type HirSourceFileQuery; | 26 | type HirSourceFileQuery; |
27 | use fn HirFileId::hir_source_file; | 27 | use fn HirFileId::hir_source_file; |
28 | } | 28 | } |
29 | |||
29 | fn expand_macro_invocation(invoc: MacroCallId) -> Option<Arc<MacroExpansion>> { | 30 | fn expand_macro_invocation(invoc: MacroCallId) -> Option<Arc<MacroExpansion>> { |
30 | type ExpandMacroCallQuery; | 31 | type ExpandMacroCallQuery; |
31 | use fn crate::macros::expand_macro_invocation; | 32 | use fn crate::macros::expand_macro_invocation; |
@@ -80,10 +81,12 @@ pub trait HirDatabase: SyntaxDatabase | |||
80 | type InputModuleItemsQuery; | 81 | type InputModuleItemsQuery; |
81 | use fn query_definitions::input_module_items; | 82 | use fn query_definitions::input_module_items; |
82 | } | 83 | } |
84 | |||
83 | fn item_map(source_root_id: SourceRootId) -> Cancelable<Arc<ItemMap>> { | 85 | fn item_map(source_root_id: SourceRootId) -> Cancelable<Arc<ItemMap>> { |
84 | type ItemMapQuery; | 86 | type ItemMapQuery; |
85 | use fn query_definitions::item_map; | 87 | use fn query_definitions::item_map; |
86 | } | 88 | } |
89 | |||
87 | fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { | 90 | fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { |
88 | type ModuleTreeQuery; | 91 | type ModuleTreeQuery; |
89 | use fn crate::module_tree::ModuleTree::module_tree_query; | 92 | use fn crate::module_tree::ModuleTree::module_tree_query; |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index a31f086f7..ebb83d084 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -33,8 +33,7 @@ pub struct Body { | |||
33 | /// IDs. This is needed to go from e.g. a position in a file to the HIR | 33 | /// IDs. This is needed to go from e.g. a position in a file to the HIR |
34 | /// expression containing it; but for type inference etc., we want to operate on | 34 | /// expression containing it; but for type inference etc., we want to operate on |
35 | /// a structure that is agnostic to the actual positions of expressions in the | 35 | /// a structure that is agnostic to the actual positions of expressions in the |
36 | /// file, so that we don't recompute the type inference whenever some whitespace | 36 | /// file, so that we don't recompute types whenever some whitespace is typed. |
37 | /// is typed. | ||
38 | #[derive(Debug, Eq, PartialEq)] | 37 | #[derive(Debug, Eq, PartialEq)] |
39 | pub struct BodySyntaxMapping { | 38 | pub struct BodySyntaxMapping { |
40 | body: Arc<Body>, | 39 | body: Arc<Body>, |
@@ -74,20 +73,25 @@ impl BodySyntaxMapping { | |||
74 | pub fn expr_syntax(&self, expr: ExprId) -> Option<LocalSyntaxPtr> { | 73 | pub fn expr_syntax(&self, expr: ExprId) -> Option<LocalSyntaxPtr> { |
75 | self.expr_syntax_mapping_back.get(expr).cloned() | 74 | self.expr_syntax_mapping_back.get(expr).cloned() |
76 | } | 75 | } |
76 | |||
77 | pub fn syntax_expr(&self, ptr: LocalSyntaxPtr) -> Option<ExprId> { | 77 | pub fn syntax_expr(&self, ptr: LocalSyntaxPtr) -> Option<ExprId> { |
78 | self.expr_syntax_mapping.get(&ptr).cloned() | 78 | self.expr_syntax_mapping.get(&ptr).cloned() |
79 | } | 79 | } |
80 | |||
80 | pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { | 81 | pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { |
81 | self.expr_syntax_mapping | 82 | self.expr_syntax_mapping |
82 | .get(&LocalSyntaxPtr::new(node.syntax())) | 83 | .get(&LocalSyntaxPtr::new(node.syntax())) |
83 | .cloned() | 84 | .cloned() |
84 | } | 85 | } |
86 | |||
85 | pub fn pat_syntax(&self, pat: PatId) -> Option<LocalSyntaxPtr> { | 87 | pub fn pat_syntax(&self, pat: PatId) -> Option<LocalSyntaxPtr> { |
86 | self.pat_syntax_mapping_back.get(pat).cloned() | 88 | self.pat_syntax_mapping_back.get(pat).cloned() |
87 | } | 89 | } |
90 | |||
88 | pub fn syntax_pat(&self, ptr: LocalSyntaxPtr) -> Option<PatId> { | 91 | pub fn syntax_pat(&self, ptr: LocalSyntaxPtr) -> Option<PatId> { |
89 | self.pat_syntax_mapping.get(&ptr).cloned() | 92 | self.pat_syntax_mapping.get(&ptr).cloned() |
90 | } | 93 | } |
94 | |||
91 | pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { | 95 | pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { |
92 | self.pat_syntax_mapping | 96 | self.pat_syntax_mapping |
93 | .get(&LocalSyntaxPtr::new(node.syntax())) | 97 | .get(&LocalSyntaxPtr::new(node.syntax())) |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 8ac49eba3..0aa687a08 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -9,25 +9,25 @@ use crate::{ | |||
9 | 9 | ||
10 | use crate::code_model_api::Module; | 10 | use crate::code_model_api::Module; |
11 | 11 | ||
12 | /// hir makes a heavy use of ids: integer (u32) handlers to various things. You | 12 | /// hir makes heavy use of ids: integer (u32) handlers to various things. You |
13 | /// can think of id as a pointer (but without a lifetime) or a file descriptor | 13 | /// can think of id as a pointer (but without a lifetime) or a file descriptor |
14 | /// (but for hir objects). | 14 | /// (but for hir objects). |
15 | /// | 15 | /// |
16 | /// This module defines a bunch of ids we are using. The most important ones are | 16 | /// This module defines a bunch of ids we are using. The most important ones are |
17 | /// probably `HirFileId` and `DefId`. | 17 | /// probably `HirFileId` and `DefId`. |
18 | 18 | ||
19 | /// Input to the analyzer is a set of file, where each file is indetified by | 19 | /// Input to the analyzer is a set of files, where each file is indentified by |
20 | /// `FileId` and contains source code. However, another source of source code in | 20 | /// `FileId` and contains source code. However, another source of source code in |
21 | /// Rust are macros: each macro can be thought of as producing a "temporary | 21 | /// Rust are macros: each macro can be thought of as producing a "temporary |
22 | /// file". To assign id to such file, we use the id of a macro call that | 22 | /// file". To assign an id to such a file, we use the id of the macro call that |
23 | /// produced the file. So, a `HirFileId` is either a `FileId` (source code | 23 | /// produced the file. So, a `HirFileId` is either a `FileId` (source code |
24 | /// written by user), or a `MacroCallId` (source code produced by macro). | 24 | /// written by user), or a `MacroCallId` (source code produced by macro). |
25 | /// | 25 | /// |
26 | /// What is a `MacroCallId`? Simplifying, it's a `HirFileId` of a file containin | 26 | /// What is a `MacroCallId`? Simplifying, it's a `HirFileId` of a file containin |
27 | /// the call plus the offset of the macro call in the file. Note that this is a | 27 | /// the call plus the offset of the macro call in the file. Note that this is a |
28 | /// recursive definition! Nethetheless, size_of of `HirFileId` is finite | 28 | /// recursive definition! However, the size_of of `HirFileId` is finite |
29 | /// (because everything bottoms out at the real `FileId`) and small | 29 | /// (because everything bottoms out at the real `FileId`) and small |
30 | /// (`MacroCallId` uses location interner). | 30 | /// (`MacroCallId` uses the location interner). |
31 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 31 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
32 | pub struct HirFileId(HirFileIdRepr); | 32 | pub struct HirFileId(HirFileIdRepr); |
33 | 33 | ||
@@ -235,7 +235,7 @@ pub struct SourceItemId { | |||
235 | pub(crate) item_id: Option<SourceFileItemId>, | 235 | pub(crate) item_id: Option<SourceFileItemId>, |
236 | } | 236 | } |
237 | 237 | ||
238 | /// Maps item's `SyntaxNode`s to `SourceFileItemId` and back. | 238 | /// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back. |
239 | #[derive(Debug, PartialEq, Eq)] | 239 | #[derive(Debug, PartialEq, Eq)] |
240 | pub struct SourceFileItems { | 240 | pub struct SourceFileItems { |
241 | file_id: HirFileId, | 241 | file_id: HirFileId, |
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index bb0ad84e4..4acda9af3 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -128,13 +128,13 @@ impl ImplItem { | |||
128 | pub struct ImplId(pub RawId); | 128 | pub struct ImplId(pub RawId); |
129 | impl_arena_id!(ImplId); | 129 | impl_arena_id!(ImplId); |
130 | 130 | ||
131 | /// Collection of impl blocks is a two-step process: First we collect the blocks | 131 | /// The collection of impl blocks is a two-step process: first we collect the |
132 | /// per-module; then we build an index of all impl blocks in the crate. This | 132 | /// blocks per-module; then we build an index of all impl blocks in the crate. |
133 | /// way, we avoid having to do this process for the whole crate whenever someone | 133 | /// This way, we avoid having to do this process for the whole crate whenever |
134 | /// types in any file; as long as the impl blocks in the file don't change, we | 134 | /// a file is changed; as long as the impl blocks in the file don't change, |
135 | /// don't need to do the second step again. | 135 | /// we don't need to do the second step again. |
136 | /// | 136 | /// |
137 | /// (The second step does not yet exist currently.) | 137 | /// (The second step does not yet exist.) |
138 | #[derive(Debug, PartialEq, Eq)] | 138 | #[derive(Debug, PartialEq, Eq)] |
139 | pub struct ModuleImplBlocks { | 139 | pub struct ModuleImplBlocks { |
140 | impls: Arena<ImplId, ImplData>, | 140 | impls: Arena<ImplId, ImplData>, |
@@ -150,7 +150,7 @@ impl ModuleImplBlocks { | |||
150 | } | 150 | } |
151 | 151 | ||
152 | fn collect(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> { | 152 | fn collect(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> { |
153 | let (file_id, module_source) = module.defenition_source(db)?; | 153 | let (file_id, module_source) = module.definition_source(db)?; |
154 | let node = match &module_source { | 154 | let node = match &module_source { |
155 | ModuleSource::SourceFile(node) => node.syntax(), | 155 | ModuleSource::SourceFile(node) => node.syntax(), |
156 | ModuleSource::Module(node) => node.syntax(), | 156 | ModuleSource::Module(node) => node.syntax(), |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index eb19d8be1..ca7f395a8 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | //! HIR (previsouly known as descriptors) provides a high-level OO acess to Rust | 1 | //! HIR (previously known as descriptors) provides a high-level object oriented |
2 | //! code. | 2 | //! access to Rust code. |
3 | //! | 3 | //! |
4 | //! The principal difference between HIR and syntax trees is that HIR is bound | 4 | //! The principal difference between HIR and syntax trees is that HIR is bound |
5 | //! to a particular crate instance. That is, it has cfg flags and features | 5 | //! to a particular crate instance. That is, it has cfg flags and features |
6 | //! applied. So, there relation between syntax and HIR is many-to-one. | 6 | //! applied. So, the relation between syntax and HIR is many-to-one. |
7 | 7 | ||
8 | macro_rules! ctry { | 8 | macro_rules! ctry { |
9 | ($expr:expr) => { | 9 | ($expr:expr) => { |
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index eb1c86091..e455b2ad5 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs | |||
@@ -4,9 +4,9 @@ | |||
4 | /// that is produced after expansion. See `HirFileId` and `MacroCallId` for how | 4 | /// that is produced after expansion. See `HirFileId` and `MacroCallId` for how |
5 | /// do we do that. | 5 | /// do we do that. |
6 | /// | 6 | /// |
7 | /// When file-management question is resolved, all that is left is a token tree | 7 | /// When the file-management question is resolved, all that is left is a |
8 | /// to token tree transformation plus hygent. We don't have either of thouse | 8 | /// token-tree-to-token-tree transformation plus hygiene. We don't have either of |
9 | /// yet, so all macros are string based at the moment! | 9 | /// those yet, so all macros are string based at the moment! |
10 | use std::sync::Arc; | 10 | use std::sync::Arc; |
11 | 11 | ||
12 | use ra_db::LocalSyntaxPtr; | 12 | use ra_db::LocalSyntaxPtr; |
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index 91aab5c74..d2c92f150 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs | |||
@@ -85,9 +85,9 @@ impl_arena_id!(LinkId); | |||
85 | 85 | ||
86 | /// Physically, rust source is organized as a set of files, but logically it is | 86 | /// Physically, rust source is organized as a set of files, but logically it is |
87 | /// organized as a tree of modules. Usually, a single file corresponds to a | 87 | /// organized as a tree of modules. Usually, a single file corresponds to a |
88 | /// single module, but it is not nessary the case. | 88 | /// single module, but it is not neccessarily always the case. |
89 | /// | 89 | /// |
90 | /// Module encapsulate the logic of transitioning from the fuzzy world of files | 90 | /// `ModuleTree` encapsulates the logic of transitioning from the fuzzy world of files |
91 | /// (which can have multiple parents) to the precise world of modules (which | 91 | /// (which can have multiple parents) to the precise world of modules (which |
92 | /// always have one parent). | 92 | /// always have one parent). |
93 | #[derive(Default, Debug, PartialEq, Eq)] | 93 | #[derive(Default, Debug, PartialEq, Eq)] |
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index 3e6ce8b95..d9683549c 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs | |||
@@ -3,7 +3,7 @@ use std::fmt; | |||
3 | use ra_syntax::{ast, SmolStr}; | 3 | use ra_syntax::{ast, SmolStr}; |
4 | 4 | ||
5 | /// `Name` is a wrapper around string, which is used in hir for both references | 5 | /// `Name` is a wrapper around string, which is used in hir for both references |
6 | /// and declarations. In theory, names should also carry hygene info, but we are | 6 | /// and declarations. In theory, names should also carry hygiene info, but we are |
7 | /// not there yet! | 7 | /// not there yet! |
8 | #[derive(Clone, PartialEq, Eq, Hash)] | 8 | #[derive(Clone, PartialEq, Eq, Hash)] |
9 | pub struct Name { | 9 | pub struct Name { |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 20adc9ec4..6bf949654 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -1,18 +1,18 @@ | |||
1 | //! Name resolution algorithm. The end result of the algorithm is `ItemMap`: a | 1 | //! Name resolution algorithm. The end result of the algorithm is an `ItemMap`: |
2 | //! map with maps each module to it's scope: the set of items, visible in the | 2 | //! a map which maps each module to its scope: the set of items visible in the |
3 | //! module. That is, we only resolve imports here, name resolution of item | 3 | //! module. That is, we only resolve imports here, name resolution of item |
4 | //! bodies will be done in a separate step. | 4 | //! bodies will be done in a separate step. |
5 | //! | 5 | //! |
6 | //! Like Rustc, we use an interative per-crate algorithm: we start with scopes | 6 | //! Like Rustc, we use an interactive per-crate algorithm: we start with scopes |
7 | //! containing only directly defined items, and then iteratively resolve | 7 | //! containing only directly defined items, and then iteratively resolve |
8 | //! imports. | 8 | //! imports. |
9 | //! | 9 | //! |
10 | //! To make this work nicely in the IDE scenarios, we place `InputModuleItems` | 10 | //! To make this work nicely in the IDE scenario, we place `InputModuleItems` |
11 | //! in between raw syntax and name resolution. `InputModuleItems` are computed | 11 | //! in between raw syntax and name resolution. `InputModuleItems` are computed |
12 | //! using only the module's syntax, and it is all directly defined items plus | 12 | //! using only the module's syntax, and it is all directly defined items plus |
13 | //! imports. The plain is to make `InputModuleItems` independent of local | 13 | //! imports. The plan is to make `InputModuleItems` independent of local |
14 | //! modifications (that is, typing inside a function shold not change IMIs), | 14 | //! modifications (that is, typing inside a function should not change IMIs), |
15 | //! such that the results of name resolution can be preserved unless the module | 15 | //! so that the results of name resolution can be preserved unless the module |
16 | //! structure itself is modified. | 16 | //! structure itself is modified. |
17 | use std::sync::Arc; | 17 | use std::sync::Arc; |
18 | 18 | ||
@@ -34,7 +34,7 @@ use crate::{ | |||
34 | module_tree::{ModuleId, ModuleTree}, | 34 | module_tree::{ModuleId, ModuleTree}, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | /// Item map is the result of the name resolution. Item map contains, for each | 37 | /// `ItemMap` is the result of name resolution. It contains, for each |
38 | /// module, the set of visible items. | 38 | /// module, the set of visible items. |
39 | // FIXME: currenty we compute item map per source-root. We should do it per crate instead. | 39 | // FIXME: currenty we compute item map per source-root. We should do it per crate instead. |
40 | #[derive(Default, Debug, PartialEq, Eq)] | 40 | #[derive(Default, Debug, PartialEq, Eq)] |
@@ -59,9 +59,9 @@ impl ModuleScope { | |||
59 | /// A set of items and imports declared inside a module, without relation to | 59 | /// A set of items and imports declared inside a module, without relation to |
60 | /// other modules. | 60 | /// other modules. |
61 | /// | 61 | /// |
62 | /// This stands in-between raw syntax and name resolution and alow us to avoid | 62 | /// This sits in-between raw syntax and name resolution and allows us to avoid |
63 | /// recomputing name res: if `InputModuleItems` are the same, we can avoid | 63 | /// recomputing name res: if two instance of `InputModuleItems` are the same, we |
64 | /// running name resolution. | 64 | /// can avoid redoing name resolution. |
65 | #[derive(Debug, Default, PartialEq, Eq)] | 65 | #[derive(Debug, Default, PartialEq, Eq)] |
66 | pub struct InputModuleItems { | 66 | pub struct InputModuleItems { |
67 | pub(crate) items: Vec<ModuleItem>, | 67 | pub(crate) items: Vec<ModuleItem>, |
@@ -114,7 +114,7 @@ enum ImportKind { | |||
114 | Named(NamedImport), | 114 | Named(NamedImport), |
115 | } | 115 | } |
116 | 116 | ||
117 | /// Resolution is basically `DefId` atm, but it should account for stuff like | 117 | /// `Resolution` is basically `DefId` atm, but it should account for stuff like |
118 | /// multiple namespaces, ambiguity and errors. | 118 | /// multiple namespaces, ambiguity and errors. |
119 | #[derive(Debug, Clone, PartialEq, Eq)] | 119 | #[derive(Debug, Clone, PartialEq, Eq)] |
120 | pub struct Resolution { | 120 | pub struct Resolution { |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 4b0400cd0..1f149a366 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | /// Lookup hir elements using position in the source code. This is a lossy | 1 | /// Lookup hir elements using positions in the source code. This is a lossy |
2 | /// transformation: in general, a single source might correspond to several | 2 | /// transformation: in general, a single source might correspond to several |
3 | /// modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on | 3 | /// modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on |
4 | /// modules. | 4 | /// modules. |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 90ba393ce..3b2bfd67a 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -144,7 +144,7 @@ pub enum Ty { | |||
144 | Bool, | 144 | Bool, |
145 | 145 | ||
146 | /// The primitive character type; holds a Unicode scalar value | 146 | /// The primitive character type; holds a Unicode scalar value |
147 | /// (a non-surrogate code point). Written as `char`. | 147 | /// (a non-surrogate code point). Written as `char`. |
148 | Char, | 148 | Char, |
149 | 149 | ||
150 | /// A primitive signed integer type. For example, `i32`. | 150 | /// A primitive signed integer type. For example, `i32`. |
@@ -204,7 +204,7 @@ pub enum Ty { | |||
204 | // `|a| yield a`. | 204 | // `|a| yield a`. |
205 | // Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), | 205 | // Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), |
206 | 206 | ||
207 | // A type representin the types stored inside a generator. | 207 | // A type representing the types stored inside a generator. |
208 | // This should only appear in GeneratorInteriors. | 208 | // This should only appear in GeneratorInteriors. |
209 | // GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>), | 209 | // GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>), |
210 | /// The never type `!`. | 210 | /// The never type `!`. |
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 24a386558..d95879e46 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! In certain situations, rust automatically inserts derefs as necessary: For | 1 | //! In certain situations, rust automatically inserts derefs as necessary: for |
2 | //! example, field accesses `foo.bar` still work when `foo` is actually a | 2 | //! example, field accesses `foo.bar` still work when `foo` is actually a |
3 | //! reference to a type with the field `bar`. This is an approximation of the | 3 | //! reference to a type with the field `bar`. This is an approximation of the |
4 | //! logic in rustc (which lives in librustc_typeck/check/autoderef.rs). | 4 | //! logic in rustc (which lives in librustc_typeck/check/autoderef.rs). |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 2749d740c..ba2a44474 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | }; | 15 | }; |
16 | 16 | ||
17 | // These tests compare the inference results for all expressions in a file | 17 | // These tests compare the inference results for all expressions in a file |
18 | // against snapshots of the current results. If you change something and these | 18 | // against snapshots of the expected results. If you change something and these |
19 | // tests fail expectedly, you can update the comparison files by deleting them | 19 | // tests fail expectedly, you can update the comparison files by deleting them |
20 | // and running the tests again. Similarly, to add a new test, just write the | 20 | // and running the tests again. Similarly, to add a new test, just write the |
21 | // test here in the same pattern and it will automatically write the snapshot. | 21 | // test here in the same pattern and it will automatically write the snapshot. |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index ee9052d3d..770a0fdf2 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -20,7 +20,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) -> | |||
20 | } | 20 | } |
21 | 21 | ||
22 | let module_scope = module.scope(ctx.db)?; | 22 | let module_scope = module.scope(ctx.db)?; |
23 | let (file_id, _) = module.defenition_source(ctx.db)?; | 23 | let (file_id, _) = module.definition_source(ctx.db)?; |
24 | module_scope | 24 | module_scope |
25 | .entries() | 25 | .entries() |
26 | .filter(|(_name, res)| { | 26 | .filter(|(_name, res)| { |
diff --git a/crates/ra_ide_api/src/goto_defenition.rs b/crates/ra_ide_api/src/goto_definition.rs index fcd8d315e..0d524b6f1 100644 --- a/crates/ra_ide_api/src/goto_defenition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -6,22 +6,22 @@ use ra_syntax::{ | |||
6 | 6 | ||
7 | use crate::{FilePosition, NavigationTarget, db::RootDatabase}; | 7 | use crate::{FilePosition, NavigationTarget, db::RootDatabase}; |
8 | 8 | ||
9 | pub(crate) fn goto_defenition( | 9 | pub(crate) fn goto_definition( |
10 | db: &RootDatabase, | 10 | db: &RootDatabase, |
11 | position: FilePosition, | 11 | position: FilePosition, |
12 | ) -> Cancelable<Option<Vec<NavigationTarget>>> { | 12 | ) -> Cancelable<Option<Vec<NavigationTarget>>> { |
13 | let file = db.source_file(position.file_id); | 13 | let file = db.source_file(position.file_id); |
14 | let syntax = file.syntax(); | 14 | let syntax = file.syntax(); |
15 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { | 15 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { |
16 | return Ok(Some(reference_defenition(db, position.file_id, name_ref)?)); | 16 | return Ok(Some(reference_definition(db, position.file_id, name_ref)?)); |
17 | } | 17 | } |
18 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { | 18 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { |
19 | return name_defenition(db, position.file_id, name); | 19 | return name_definition(db, position.file_id, name); |
20 | } | 20 | } |
21 | Ok(None) | 21 | Ok(None) |
22 | } | 22 | } |
23 | 23 | ||
24 | pub(crate) fn reference_defenition( | 24 | pub(crate) fn reference_definition( |
25 | db: &RootDatabase, | 25 | db: &RootDatabase, |
26 | file_id: FileId, | 26 | file_id: FileId, |
27 | name_ref: &ast::NameRef, | 27 | name_ref: &ast::NameRef, |
@@ -51,7 +51,7 @@ pub(crate) fn reference_defenition( | |||
51 | Ok(navs) | 51 | Ok(navs) |
52 | } | 52 | } |
53 | 53 | ||
54 | fn name_defenition( | 54 | fn name_definition( |
55 | db: &RootDatabase, | 55 | db: &RootDatabase, |
56 | file_id: FileId, | 56 | file_id: FileId, |
57 | name: &ast::Name, | 57 | name: &ast::Name, |
@@ -61,7 +61,7 @@ fn name_defenition( | |||
61 | if let Some(child_module) = | 61 | if let Some(child_module) = |
62 | hir::source_binder::module_from_declaration(db, file_id, module)? | 62 | hir::source_binder::module_from_declaration(db, file_id, module)? |
63 | { | 63 | { |
64 | let (file_id, _) = child_module.defenition_source(db)?; | 64 | let (file_id, _) = child_module.definition_source(db)?; |
65 | let name = match child_module.name(db)? { | 65 | let name = match child_module.name(db)? { |
66 | Some(name) => name.to_string().into(), | 66 | Some(name) => name.to_string().into(), |
67 | None => "".into(), | 67 | None => "".into(), |
@@ -86,7 +86,7 @@ mod tests { | |||
86 | use crate::mock_analysis::analysis_and_position; | 86 | use crate::mock_analysis::analysis_and_position; |
87 | 87 | ||
88 | #[test] | 88 | #[test] |
89 | fn goto_defenition_works_in_items() { | 89 | fn goto_definition_works_in_items() { |
90 | let (analysis, pos) = analysis_and_position( | 90 | let (analysis, pos) = analysis_and_position( |
91 | " | 91 | " |
92 | //- /lib.rs | 92 | //- /lib.rs |
@@ -95,7 +95,7 @@ mod tests { | |||
95 | ", | 95 | ", |
96 | ); | 96 | ); |
97 | 97 | ||
98 | let symbols = analysis.goto_defenition(pos).unwrap().unwrap(); | 98 | let symbols = analysis.goto_definition(pos).unwrap().unwrap(); |
99 | assert_eq_dbg( | 99 | assert_eq_dbg( |
100 | r#"[NavigationTarget { file_id: FileId(1), name: "Foo", | 100 | r#"[NavigationTarget { file_id: FileId(1), name: "Foo", |
101 | kind: STRUCT_DEF, range: [0; 11), | 101 | kind: STRUCT_DEF, range: [0; 11), |
@@ -105,7 +105,7 @@ mod tests { | |||
105 | } | 105 | } |
106 | 106 | ||
107 | #[test] | 107 | #[test] |
108 | fn goto_defenition_works_for_module_declaration() { | 108 | fn goto_definition_works_for_module_declaration() { |
109 | let (analysis, pos) = analysis_and_position( | 109 | let (analysis, pos) = analysis_and_position( |
110 | " | 110 | " |
111 | //- /lib.rs | 111 | //- /lib.rs |
@@ -115,7 +115,7 @@ mod tests { | |||
115 | ", | 115 | ", |
116 | ); | 116 | ); |
117 | 117 | ||
118 | let symbols = analysis.goto_defenition(pos).unwrap().unwrap(); | 118 | let symbols = analysis.goto_definition(pos).unwrap().unwrap(); |
119 | assert_eq_dbg( | 119 | assert_eq_dbg( |
120 | r#"[NavigationTarget { file_id: FileId(2), name: "foo", kind: MODULE, range: [0; 0), ptr: None }]"#, | 120 | r#"[NavigationTarget { file_id: FileId(2), name: "foo", kind: MODULE, range: [0; 0), ptr: None }]"#, |
121 | &symbols, | 121 | &symbols, |
@@ -130,7 +130,7 @@ mod tests { | |||
130 | ", | 130 | ", |
131 | ); | 131 | ); |
132 | 132 | ||
133 | let symbols = analysis.goto_defenition(pos).unwrap().unwrap(); | 133 | let symbols = analysis.goto_definition(pos).unwrap().unwrap(); |
134 | assert_eq_dbg( | 134 | assert_eq_dbg( |
135 | r#"[NavigationTarget { file_id: FileId(2), name: "foo", kind: MODULE, range: [0; 0), ptr: None }]"#, | 135 | r#"[NavigationTarget { file_id: FileId(2), name: "foo", kind: MODULE, range: [0; 0), ptr: None }]"#, |
136 | &symbols, | 136 | &symbols, |
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 475524ee1..41309e756 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -16,7 +16,7 @@ pub(crate) fn hover( | |||
16 | 16 | ||
17 | let mut range = None; | 17 | let mut range = None; |
18 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { | 18 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { |
19 | let navs = crate::goto_defenition::reference_defenition(db, position.file_id, name_ref)?; | 19 | let navs = crate::goto_definition::reference_definition(db, position.file_id, name_ref)?; |
20 | for nav in navs { | 20 | for nav in navs { |
21 | res.extend(doc_text_for(db, nav)?) | 21 | res.extend(doc_text_for(db, nav)?) |
22 | } | 22 | } |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 7e9ca2034..fbe1421a4 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -20,7 +20,7 @@ macro_rules! ctry { | |||
20 | 20 | ||
21 | mod completion; | 21 | mod completion; |
22 | mod db; | 22 | mod db; |
23 | mod goto_defenition; | 23 | mod goto_definition; |
24 | mod imp; | 24 | mod imp; |
25 | pub mod mock_analysis; | 25 | pub mod mock_analysis; |
26 | mod runnables; | 26 | mod runnables; |
@@ -121,9 +121,11 @@ impl AnalysisChange { | |||
121 | pub fn new() -> AnalysisChange { | 121 | pub fn new() -> AnalysisChange { |
122 | AnalysisChange::default() | 122 | AnalysisChange::default() |
123 | } | 123 | } |
124 | |||
124 | pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) { | 125 | pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) { |
125 | self.new_roots.push((root_id, is_local)); | 126 | self.new_roots.push((root_id, is_local)); |
126 | } | 127 | } |
128 | |||
127 | pub fn add_file( | 129 | pub fn add_file( |
128 | &mut self, | 130 | &mut self, |
129 | root_id: SourceRootId, | 131 | root_id: SourceRootId, |
@@ -142,9 +144,11 @@ impl AnalysisChange { | |||
142 | .added | 144 | .added |
143 | .push(file); | 145 | .push(file); |
144 | } | 146 | } |
147 | |||
145 | pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) { | 148 | pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) { |
146 | self.files_changed.push((file_id, new_text)) | 149 | self.files_changed.push((file_id, new_text)) |
147 | } | 150 | } |
151 | |||
148 | pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) { | 152 | pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) { |
149 | let file = RemoveFile { file_id, path }; | 153 | let file = RemoveFile { file_id, path }; |
150 | self.roots_changed | 154 | self.roots_changed |
@@ -153,9 +157,11 @@ impl AnalysisChange { | |||
153 | .removed | 157 | .removed |
154 | .push(file); | 158 | .push(file); |
155 | } | 159 | } |
160 | |||
156 | pub fn add_library(&mut self, data: LibraryData) { | 161 | pub fn add_library(&mut self, data: LibraryData) { |
157 | self.libraries_added.push(data) | 162 | self.libraries_added.push(data) |
158 | } | 163 | } |
164 | |||
159 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | 165 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { |
160 | self.crate_graph = Some(graph); | 166 | self.crate_graph = Some(graph); |
161 | } | 167 | } |
@@ -218,15 +224,19 @@ impl Query { | |||
218 | limit: usize::max_value(), | 224 | limit: usize::max_value(), |
219 | } | 225 | } |
220 | } | 226 | } |
227 | |||
221 | pub fn only_types(&mut self) { | 228 | pub fn only_types(&mut self) { |
222 | self.only_types = true; | 229 | self.only_types = true; |
223 | } | 230 | } |
231 | |||
224 | pub fn libs(&mut self) { | 232 | pub fn libs(&mut self) { |
225 | self.libs = true; | 233 | self.libs = true; |
226 | } | 234 | } |
235 | |||
227 | pub fn exact(&mut self) { | 236 | pub fn exact(&mut self) { |
228 | self.exact = true; | 237 | self.exact = true; |
229 | } | 238 | } |
239 | |||
230 | pub fn limit(&mut self, limit: usize) { | 240 | pub fn limit(&mut self, limit: usize) { |
231 | self.limit = limit | 241 | self.limit = limit |
232 | } | 242 | } |
@@ -257,15 +267,19 @@ impl NavigationTarget { | |||
257 | ptr: Some(symbol.ptr.clone()), | 267 | ptr: Some(symbol.ptr.clone()), |
258 | } | 268 | } |
259 | } | 269 | } |
270 | |||
260 | pub fn name(&self) -> &SmolStr { | 271 | pub fn name(&self) -> &SmolStr { |
261 | &self.name | 272 | &self.name |
262 | } | 273 | } |
274 | |||
263 | pub fn kind(&self) -> SyntaxKind { | 275 | pub fn kind(&self) -> SyntaxKind { |
264 | self.kind | 276 | self.kind |
265 | } | 277 | } |
278 | |||
266 | pub fn file_id(&self) -> FileId { | 279 | pub fn file_id(&self) -> FileId { |
267 | self.file_id | 280 | self.file_id |
268 | } | 281 | } |
282 | |||
269 | pub fn range(&self) -> TextRange { | 283 | pub fn range(&self) -> TextRange { |
270 | self.range | 284 | self.range |
271 | } | 285 | } |
@@ -305,6 +319,7 @@ impl AnalysisHost { | |||
305 | db: self.db.snapshot(), | 319 | db: self.db.snapshot(), |
306 | } | 320 | } |
307 | } | 321 | } |
322 | |||
308 | /// Applies changes to the current state of the world. If there are | 323 | /// Applies changes to the current state of the world. If there are |
309 | /// outstanding snapshots, they will be canceled. | 324 | /// outstanding snapshots, they will be canceled. |
310 | pub fn apply_change(&mut self, change: AnalysisChange) { | 325 | pub fn apply_change(&mut self, change: AnalysisChange) { |
@@ -326,30 +341,36 @@ impl Analysis { | |||
326 | pub fn file_text(&self, file_id: FileId) -> Arc<String> { | 341 | pub fn file_text(&self, file_id: FileId) -> Arc<String> { |
327 | self.db.file_text(file_id) | 342 | self.db.file_text(file_id) |
328 | } | 343 | } |
344 | |||
329 | /// Gets the syntax tree of the file. | 345 | /// Gets the syntax tree of the file. |
330 | pub fn file_syntax(&self, file_id: FileId) -> TreePtr<SourceFile> { | 346 | pub fn file_syntax(&self, file_id: FileId) -> TreePtr<SourceFile> { |
331 | self.db.source_file(file_id).clone() | 347 | self.db.source_file(file_id).clone() |
332 | } | 348 | } |
349 | |||
333 | /// Gets the file's `LineIndex`: data structure to convert between absolute | 350 | /// Gets the file's `LineIndex`: data structure to convert between absolute |
334 | /// offsets and line/column representation. | 351 | /// offsets and line/column representation. |
335 | pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { | 352 | pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { |
336 | self.db.line_index(file_id) | 353 | self.db.line_index(file_id) |
337 | } | 354 | } |
355 | |||
338 | /// Selects the next syntactic nodes encopasing the range. | 356 | /// Selects the next syntactic nodes encopasing the range. |
339 | pub fn extend_selection(&self, frange: FileRange) -> TextRange { | 357 | pub fn extend_selection(&self, frange: FileRange) -> TextRange { |
340 | extend_selection::extend_selection(&self.db, frange) | 358 | extend_selection::extend_selection(&self.db, frange) |
341 | } | 359 | } |
360 | |||
342 | /// Returns position of the mathcing brace (all types of braces are | 361 | /// Returns position of the mathcing brace (all types of braces are |
343 | /// supported). | 362 | /// supported). |
344 | pub fn matching_brace(&self, file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { | 363 | pub fn matching_brace(&self, file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { |
345 | ra_ide_api_light::matching_brace(file, offset) | 364 | ra_ide_api_light::matching_brace(file, offset) |
346 | } | 365 | } |
366 | |||
347 | /// Returns a syntax tree represented as `String`, for debug purposes. | 367 | /// Returns a syntax tree represented as `String`, for debug purposes. |
348 | // FIXME: use a better name here. | 368 | // FIXME: use a better name here. |
349 | pub fn syntax_tree(&self, file_id: FileId) -> String { | 369 | pub fn syntax_tree(&self, file_id: FileId) -> String { |
350 | let file = self.db.source_file(file_id); | 370 | let file = self.db.source_file(file_id); |
351 | ra_ide_api_light::syntax_tree(&file) | 371 | ra_ide_api_light::syntax_tree(&file) |
352 | } | 372 | } |
373 | |||
353 | /// Returns an edit to remove all newlines in the range, cleaning up minor | 374 | /// Returns an edit to remove all newlines in the range, cleaning up minor |
354 | /// stuff like trailing commas. | 375 | /// stuff like trailing commas. |
355 | pub fn join_lines(&self, frange: FileRange) -> SourceChange { | 376 | pub fn join_lines(&self, frange: FileRange) -> SourceChange { |
@@ -359,6 +380,7 @@ impl Analysis { | |||
359 | ra_ide_api_light::join_lines(&file, frange.range), | 380 | ra_ide_api_light::join_lines(&file, frange.range), |
360 | ) | 381 | ) |
361 | } | 382 | } |
383 | |||
362 | /// Returns an edit which should be applied when opening a new line, fixing | 384 | /// Returns an edit which should be applied when opening a new line, fixing |
363 | /// up minor stuff like continuing the comment. | 385 | /// up minor stuff like continuing the comment. |
364 | pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> { | 386 | pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> { |
@@ -366,6 +388,7 @@ impl Analysis { | |||
366 | let edit = ra_ide_api_light::on_enter(&file, position.offset)?; | 388 | let edit = ra_ide_api_light::on_enter(&file, position.offset)?; |
367 | Some(SourceChange::from_local_edit(position.file_id, edit)) | 389 | Some(SourceChange::from_local_edit(position.file_id, edit)) |
368 | } | 390 | } |
391 | |||
369 | /// Returns an edit which should be applied after `=` was typed. Primarily, | 392 | /// Returns an edit which should be applied after `=` was typed. Primarily, |
370 | /// this works when adding `let =`. | 393 | /// this works when adding `let =`. |
371 | // FIXME: use a snippet completion instead of this hack here. | 394 | // FIXME: use a snippet completion instead of this hack here. |
@@ -374,23 +397,27 @@ impl Analysis { | |||
374 | let edit = ra_ide_api_light::on_eq_typed(&file, position.offset)?; | 397 | let edit = ra_ide_api_light::on_eq_typed(&file, position.offset)?; |
375 | Some(SourceChange::from_local_edit(position.file_id, edit)) | 398 | Some(SourceChange::from_local_edit(position.file_id, edit)) |
376 | } | 399 | } |
400 | |||
377 | /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. | 401 | /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. |
378 | pub fn on_dot_typed(&self, position: FilePosition) -> Option<SourceChange> { | 402 | pub fn on_dot_typed(&self, position: FilePosition) -> Option<SourceChange> { |
379 | let file = self.db.source_file(position.file_id); | 403 | let file = self.db.source_file(position.file_id); |
380 | let edit = ra_ide_api_light::on_dot_typed(&file, position.offset)?; | 404 | let edit = ra_ide_api_light::on_dot_typed(&file, position.offset)?; |
381 | Some(SourceChange::from_local_edit(position.file_id, edit)) | 405 | Some(SourceChange::from_local_edit(position.file_id, edit)) |
382 | } | 406 | } |
407 | |||
383 | /// Returns a tree representation of symbols in the file. Useful to draw a | 408 | /// Returns a tree representation of symbols in the file. Useful to draw a |
384 | /// file outline. | 409 | /// file outline. |
385 | pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { | 410 | pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { |
386 | let file = self.db.source_file(file_id); | 411 | let file = self.db.source_file(file_id); |
387 | ra_ide_api_light::file_structure(&file) | 412 | ra_ide_api_light::file_structure(&file) |
388 | } | 413 | } |
414 | |||
389 | /// Returns the set of folding ranges. | 415 | /// Returns the set of folding ranges. |
390 | pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { | 416 | pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { |
391 | let file = self.db.source_file(file_id); | 417 | let file = self.db.source_file(file_id); |
392 | ra_ide_api_light::folding_ranges(&file) | 418 | ra_ide_api_light::folding_ranges(&file) |
393 | } | 419 | } |
420 | |||
394 | /// Fuzzy searches for a symbol. | 421 | /// Fuzzy searches for a symbol. |
395 | pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { | 422 | pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { |
396 | let res = symbol_index::world_symbols(&*self.db, query)? | 423 | let res = symbol_index::world_symbols(&*self.db, query)? |
@@ -399,62 +426,76 @@ impl Analysis { | |||
399 | .collect(); | 426 | .collect(); |
400 | Ok(res) | 427 | Ok(res) |
401 | } | 428 | } |
402 | pub fn goto_defenition( | 429 | |
430 | pub fn goto_definition( | ||
403 | &self, | 431 | &self, |
404 | position: FilePosition, | 432 | position: FilePosition, |
405 | ) -> Cancelable<Option<Vec<NavigationTarget>>> { | 433 | ) -> Cancelable<Option<Vec<NavigationTarget>>> { |
406 | goto_defenition::goto_defenition(&*self.db, position) | 434 | goto_definition::goto_definition(&*self.db, position) |
407 | } | 435 | } |
436 | |||
408 | /// Finds all usages of the reference at point. | 437 | /// Finds all usages of the reference at point. |
409 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { | 438 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { |
410 | self.db.find_all_refs(position) | 439 | self.db.find_all_refs(position) |
411 | } | 440 | } |
441 | |||
412 | /// Returns a short text descrbing element at position. | 442 | /// Returns a short text descrbing element at position. |
413 | pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> { | 443 | pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> { |
414 | hover::hover(&*self.db, position) | 444 | hover::hover(&*self.db, position) |
415 | } | 445 | } |
446 | |||
416 | /// Computes parameter information for the given call expression. | 447 | /// Computes parameter information for the given call expression. |
417 | pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> { | 448 | pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> { |
418 | call_info::call_info(&*self.db, position) | 449 | call_info::call_info(&*self.db, position) |
419 | } | 450 | } |
451 | |||
420 | /// Returns a `mod name;` declaration which created the current module. | 452 | /// Returns a `mod name;` declaration which created the current module. |
421 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { | 453 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { |
422 | self.db.parent_module(position) | 454 | self.db.parent_module(position) |
423 | } | 455 | } |
456 | |||
424 | /// Returns crates this file belongs too. | 457 | /// Returns crates this file belongs too. |
425 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { | 458 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
426 | self.db.crate_for(file_id) | 459 | self.db.crate_for(file_id) |
427 | } | 460 | } |
461 | |||
428 | /// Returns the root file of the given crate. | 462 | /// Returns the root file of the given crate. |
429 | pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { | 463 | pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { |
430 | Ok(self.db.crate_graph().crate_root(crate_id)) | 464 | Ok(self.db.crate_graph().crate_root(crate_id)) |
431 | } | 465 | } |
466 | |||
432 | /// Returns the set of possible targets to run for the current file. | 467 | /// Returns the set of possible targets to run for the current file. |
433 | pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { | 468 | pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { |
434 | runnables::runnables(&*self.db, file_id) | 469 | runnables::runnables(&*self.db, file_id) |
435 | } | 470 | } |
471 | |||
436 | /// Computes syntax highlighting for the given file. | 472 | /// Computes syntax highlighting for the given file. |
437 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { | 473 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { |
438 | syntax_highlighting::highlight(&*self.db, file_id) | 474 | syntax_highlighting::highlight(&*self.db, file_id) |
439 | } | 475 | } |
476 | |||
440 | /// Computes completions at the given position. | 477 | /// Computes completions at the given position. |
441 | pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { | 478 | pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { |
442 | let completions = completion::completions(&self.db, position)?; | 479 | let completions = completion::completions(&self.db, position)?; |
443 | Ok(completions.map(|it| it.into())) | 480 | Ok(completions.map(|it| it.into())) |
444 | } | 481 | } |
482 | |||
445 | /// Computes assists (aks code actons aka intentions) for the given | 483 | /// Computes assists (aks code actons aka intentions) for the given |
446 | /// position. | 484 | /// position. |
447 | pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> { | 485 | pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> { |
448 | Ok(self.db.assists(frange)) | 486 | Ok(self.db.assists(frange)) |
449 | } | 487 | } |
488 | |||
450 | /// Computes the set of diagnostics for the given file. | 489 | /// Computes the set of diagnostics for the given file. |
451 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 490 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
452 | self.db.diagnostics(file_id) | 491 | self.db.diagnostics(file_id) |
453 | } | 492 | } |
493 | |||
454 | /// Computes the type of the expression at the given position. | 494 | /// Computes the type of the expression at the given position. |
455 | pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> { | 495 | pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> { |
456 | hover::type_of(&*self.db, frange) | 496 | hover::type_of(&*self.db, frange) |
457 | } | 497 | } |
498 | |||
458 | /// Returns the edit required to rename reference at the position to the new | 499 | /// Returns the edit required to rename reference at the position to the new |
459 | /// name. | 500 | /// name. |
460 | pub fn rename( | 501 | pub fn rename( |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 96923fac7..7fc0b8f50 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -326,7 +326,7 @@ fn on_notification( | |||
326 | if pending_requests.remove(&id) { | 326 | if pending_requests.remove(&id) { |
327 | let response = RawResponse::err( | 327 | let response = RawResponse::err( |
328 | id, | 328 | id, |
329 | ErrorCode::RequestCancelled as i32, | 329 | ErrorCode::RequestCanceled as i32, |
330 | "canceled by client".to_string(), | 330 | "canceled by client".to_string(), |
331 | ); | 331 | ); |
332 | msg_sender.send(RawMessage::Response(response)).unwrap() | 332 | msg_sender.send(RawMessage::Response(response)).unwrap() |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index a653c5ada..069e7f932 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -213,7 +213,7 @@ pub fn handle_goto_definition( | |||
213 | params: req::TextDocumentPositionParams, | 213 | params: req::TextDocumentPositionParams, |
214 | ) -> Result<Option<req::GotoDefinitionResponse>> { | 214 | ) -> Result<Option<req::GotoDefinitionResponse>> { |
215 | let position = params.try_conv_with(&world)?; | 215 | let position = params.try_conv_with(&world)?; |
216 | let navs = match world.analysis().goto_defenition(position)? { | 216 | let navs = match world.analysis().goto_definition(position)? { |
217 | None => return Ok(None), | 217 | None => return Ok(None), |
218 | Some(it) => it, | 218 | Some(it) => it, |
219 | }; | 219 | }; |