diff options
-rw-r--r-- | crates/ra_analysis/src/completion.rs (renamed from crates/ra_analysis/src/completion/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 39 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 29 | ||||
-rw-r--r-- | crates/ra_analysis/tests/tests.rs | 21 | ||||
-rw-r--r-- | crates/ra_editor/src/extend_selection.rs | 27 | ||||
-rw-r--r-- | crates/ra_editor/src/symbols.rs | 55 | ||||
-rw-r--r-- | crates/ra_hir/src/function.rs (renamed from crates/ra_hir/src/function/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_hir/src/module.rs (renamed from crates/ra_hir/src/module/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_hir/src/module/imp.rs | 40 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs (renamed from crates/ra_lsp_server/src/main_loop/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 36 | ||||
-rw-r--r-- | crates/ra_syntax/src/algo.rs (renamed from crates/ra_syntax/src/algo/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs (renamed from crates/ra_syntax/src/ast/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.rs (renamed from crates/ra_syntax/src/grammar/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions.rs (renamed from crates/ra_syntax/src/grammar/expressions/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/items.rs (renamed from crates/ra_syntax/src/grammar/items/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/lexer.rs (renamed from crates/ra_syntax/src/lexer/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/parser_impl.rs (renamed from crates/ra_syntax/src/parser_impl/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/string_lexing.rs (renamed from crates/ra_syntax/src/string_lexing/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/syntax_kinds.rs (renamed from crates/ra_syntax/src/syntax_kinds/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/syntax_kinds/generated.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/syntax_kinds/generated.rs.tera | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs (renamed from crates/ra_syntax/src/validation/mod.rs) | 0 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow.rs (renamed from crates/ra_syntax/src/yellow/mod.rs) | 0 | ||||
-rw-r--r-- | crates/tools/src/main.rs | 10 |
26 files changed, 202 insertions, 61 deletions
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion.rs index 0f154112a..0f154112a 100644 --- a/crates/ra_analysis/src/completion/mod.rs +++ b/crates/ra_analysis/src/completion.rs | |||
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 975afc145..03d17de0d 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -27,6 +27,7 @@ use crate::{ | |||
27 | symbol_index::{SymbolIndex, SymbolsDatabase}, | 27 | symbol_index::{SymbolIndex, SymbolsDatabase}, |
28 | AnalysisChange, Cancelable, CrateId, Diagnostic, FileId, | 28 | AnalysisChange, Cancelable, CrateId, Diagnostic, FileId, |
29 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, | 29 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, |
30 | ReferenceResolution, | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | #[derive(Debug, Default)] | 33 | #[derive(Debug, Default)] |
@@ -144,7 +145,7 @@ impl AnalysisImpl { | |||
144 | } else { | 145 | } else { |
145 | let files = &self.db.source_root(WORKSPACE).files; | 146 | let files = &self.db.source_root(WORKSPACE).files; |
146 | 147 | ||
147 | /// Need to wrap Snapshot to provide `Clon` impl for `map_with` | 148 | /// Need to wrap Snapshot to provide `Clone` impl for `map_with` |
148 | struct Snap(salsa::Snapshot<db::RootDatabase>); | 149 | struct Snap(salsa::Snapshot<db::RootDatabase>); |
149 | impl Clone for Snap { | 150 | impl Clone for Snap { |
150 | fn clone(&self) -> Snap { | 151 | fn clone(&self) -> Snap { |
@@ -164,7 +165,7 @@ impl AnalysisImpl { | |||
164 | .sweep(salsa::SweepStrategy::default().discard_values()); | 165 | .sweep(salsa::SweepStrategy::default().discard_values()); |
165 | Ok(query.search(&buf)) | 166 | Ok(query.search(&buf)) |
166 | } | 167 | } |
167 | /// This return `Vec`: a module may be included from several places. We | 168 | /// This returns `Vec` because a module may be included from several places. We |
168 | /// don't handle this case yet though, so the Vec has length at most one. | 169 | /// don't handle this case yet though, so the Vec has length at most one. |
169 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 170 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
170 | let descr = match source_binder::module_from_position(&*self.db, position)? { | 171 | let descr = match source_binder::module_from_position(&*self.db, position)? { |
@@ -206,10 +207,11 @@ impl AnalysisImpl { | |||
206 | pub fn approximately_resolve_symbol( | 207 | pub fn approximately_resolve_symbol( |
207 | &self, | 208 | &self, |
208 | position: FilePosition, | 209 | position: FilePosition, |
209 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 210 | ) -> Cancelable<Option<ReferenceResolution>> { |
210 | let file = self.db.source_file(position.file_id); | 211 | let file = self.db.source_file(position.file_id); |
211 | let syntax = file.syntax(); | 212 | let syntax = file.syntax(); |
212 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { | 213 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { |
214 | let mut rr = ReferenceResolution::new(name_ref.syntax().range()); | ||
213 | if let Some(fn_descr) = source_binder::function_from_child_node( | 215 | if let Some(fn_descr) = source_binder::function_from_child_node( |
214 | &*self.db, | 216 | &*self.db, |
215 | position.file_id, | 217 | position.file_id, |
@@ -218,22 +220,25 @@ impl AnalysisImpl { | |||
218 | let scope = fn_descr.scope(&*self.db); | 220 | let scope = fn_descr.scope(&*self.db); |
219 | // First try to resolve the symbol locally | 221 | // First try to resolve the symbol locally |
220 | if let Some(entry) = scope.resolve_local_name(name_ref) { | 222 | if let Some(entry) = scope.resolve_local_name(name_ref) { |
221 | let mut vec = vec![]; | 223 | rr.add_resolution( |
222 | vec.push(( | ||
223 | position.file_id, | 224 | position.file_id, |
224 | FileSymbol { | 225 | FileSymbol { |
225 | name: entry.name().clone(), | 226 | name: entry.name().clone(), |
226 | node_range: entry.ptr().range(), | 227 | node_range: entry.ptr().range(), |
227 | kind: NAME, | 228 | kind: NAME, |
228 | }, | 229 | }, |
229 | )); | 230 | ); |
230 | return Ok(vec); | 231 | return Ok(Some(rr)); |
231 | }; | 232 | }; |
232 | } | 233 | } |
233 | // If that fails try the index based approach. | 234 | // If that fails try the index based approach. |
234 | return self.index_resolve(name_ref); | 235 | for (file_id, symbol) in self.index_resolve(name_ref)? { |
236 | rr.add_resolution(file_id, symbol); | ||
237 | } | ||
238 | return Ok(Some(rr)); | ||
235 | } | 239 | } |
236 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { | 240 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { |
241 | let mut rr = ReferenceResolution::new(name.syntax().range()); | ||
237 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { | 242 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { |
238 | if module.has_semi() { | 243 | if module.has_semi() { |
239 | let parent_module = | 244 | let parent_module = |
@@ -248,7 +253,8 @@ impl AnalysisImpl { | |||
248 | node_range: TextRange::offset_len(0.into(), 0.into()), | 253 | node_range: TextRange::offset_len(0.into(), 0.into()), |
249 | kind: MODULE, | 254 | kind: MODULE, |
250 | }; | 255 | }; |
251 | return Ok(vec![(file_id, symbol)]); | 256 | rr.add_resolution(file_id, symbol); |
257 | return Ok(Some(rr)); | ||
252 | } | 258 | } |
253 | } | 259 | } |
254 | _ => (), | 260 | _ => (), |
@@ -256,7 +262,7 @@ impl AnalysisImpl { | |||
256 | } | 262 | } |
257 | } | 263 | } |
258 | } | 264 | } |
259 | Ok(vec![]) | 265 | Ok(None) |
260 | } | 266 | } |
261 | 267 | ||
262 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { | 268 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { |
@@ -318,6 +324,19 @@ impl AnalysisImpl { | |||
318 | 324 | ||
319 | Ok(symbol.docs(&file)) | 325 | Ok(symbol.docs(&file)) |
320 | } | 326 | } |
327 | pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> { | ||
328 | let file = self.db.source_file(file_id); | ||
329 | let result = match (symbol.description(&file), symbol.docs(&file)) { | ||
330 | (Some(desc), Some(docs)) => { | ||
331 | Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs) | ||
332 | } | ||
333 | (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"), | ||
334 | (None, Some(docs)) => Some(docs), | ||
335 | _ => None, | ||
336 | }; | ||
337 | |||
338 | Ok(result) | ||
339 | } | ||
321 | 340 | ||
322 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 341 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
323 | let syntax = self.db.source_file(file_id); | 342 | let syntax = self.db.source_file(file_id); |
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 4b8b10816..eaf24cb36 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -178,6 +178,30 @@ impl Query { | |||
178 | } | 178 | } |
179 | } | 179 | } |
180 | 180 | ||
181 | /// Result of "goto def" query. | ||
182 | #[derive(Debug)] | ||
183 | pub struct ReferenceResolution { | ||
184 | /// The range of the reference itself. Client does not know what constitutes | ||
185 | /// a reference, it handles us only the offset. It's helpful to tell the | ||
186 | /// client where the reference was. | ||
187 | pub reference_range: TextRange, | ||
188 | /// What this reference resolves to. | ||
189 | pub resolves_to: Vec<(FileId, FileSymbol)>, | ||
190 | } | ||
191 | |||
192 | impl ReferenceResolution { | ||
193 | fn new(reference_range: TextRange) -> ReferenceResolution { | ||
194 | ReferenceResolution { | ||
195 | reference_range, | ||
196 | resolves_to: Vec::new(), | ||
197 | } | ||
198 | } | ||
199 | |||
200 | fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) { | ||
201 | self.resolves_to.push((file_id, symbol)) | ||
202 | } | ||
203 | } | ||
204 | |||
181 | /// Analysis is a snapshot of a world state at a moment in time. It is the main | 205 | /// Analysis is a snapshot of a world state at a moment in time. It is the main |
182 | /// entry point for asking semantic information about the world. When the world | 206 | /// entry point for asking semantic information about the world. When the world |
183 | /// state is advanced using `AnalysisHost::apply_change` method, all existing | 207 | /// state is advanced using `AnalysisHost::apply_change` method, all existing |
@@ -236,7 +260,7 @@ impl Analysis { | |||
236 | pub fn approximately_resolve_symbol( | 260 | pub fn approximately_resolve_symbol( |
237 | &self, | 261 | &self, |
238 | position: FilePosition, | 262 | position: FilePosition, |
239 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 263 | ) -> Cancelable<Option<ReferenceResolution>> { |
240 | self.imp.approximately_resolve_symbol(position) | 264 | self.imp.approximately_resolve_symbol(position) |
241 | } | 265 | } |
242 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { | 266 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { |
@@ -249,6 +273,9 @@ impl Analysis { | |||
249 | ) -> Cancelable<Option<String>> { | 273 | ) -> Cancelable<Option<String>> { |
250 | self.imp.doc_comment_for(file_id, symbol) | 274 | self.imp.doc_comment_for(file_id, symbol) |
251 | } | 275 | } |
276 | pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> { | ||
277 | self.imp.doc_text_for(file_id, symbol) | ||
278 | } | ||
252 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 279 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
253 | self.imp.parent_module(position) | 280 | self.imp.parent_module(position) |
254 | } | 281 | } |
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 4ce2c5c85..889b568b9 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -21,9 +21,12 @@ fn approximate_resolve_works_in_items() { | |||
21 | ", | 21 | ", |
22 | ); | 22 | ); |
23 | 23 | ||
24 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); | 24 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); |
25 | assert_eq_dbg( | 25 | assert_eq_dbg( |
26 | r#"[(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })]"#, | 26 | r#"ReferenceResolution { |
27 | reference_range: [23; 26), | ||
28 | resolves_to: [(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })] | ||
29 | }"#, | ||
27 | &symbols, | 30 | &symbols, |
28 | ); | 31 | ); |
29 | } | 32 | } |
@@ -39,9 +42,12 @@ fn test_resolve_module() { | |||
39 | ", | 42 | ", |
40 | ); | 43 | ); |
41 | 44 | ||
42 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); | 45 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); |
43 | assert_eq_dbg( | 46 | assert_eq_dbg( |
44 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 47 | r#"ReferenceResolution { |
48 | reference_range: [4; 7), | ||
49 | resolves_to: [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })] | ||
50 | }"#, | ||
45 | &symbols, | 51 | &symbols, |
46 | ); | 52 | ); |
47 | 53 | ||
@@ -54,9 +60,12 @@ fn test_resolve_module() { | |||
54 | ", | 60 | ", |
55 | ); | 61 | ); |
56 | 62 | ||
57 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); | 63 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); |
58 | assert_eq_dbg( | 64 | assert_eq_dbg( |
59 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 65 | r#"ReferenceResolution { |
66 | reference_range: [4; 7), | ||
67 | resolves_to: [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })] | ||
68 | }"#, | ||
60 | &symbols, | 69 | &symbols, |
61 | ); | 70 | ); |
62 | } | 71 | } |
diff --git a/crates/ra_editor/src/extend_selection.rs b/crates/ra_editor/src/extend_selection.rs index 8f11d5364..a2aa02149 100644 --- a/crates/ra_editor/src/extend_selection.rs +++ b/crates/ra_editor/src/extend_selection.rs | |||
@@ -48,13 +48,18 @@ fn extend_single_word_in_comment(leaf: SyntaxNodeRef, offset: TextUnit) -> Optio | |||
48 | let cursor_position: u32 = (offset - leaf.range().start()).into(); | 48 | let cursor_position: u32 = (offset - leaf.range().start()).into(); |
49 | 49 | ||
50 | let (before, after) = text.split_at(cursor_position as usize); | 50 | let (before, after) = text.split_at(cursor_position as usize); |
51 | let start_idx = before.rfind(char::is_whitespace)? as u32; | 51 | let start_idx = before.rfind(char::is_whitespace).unwrap_or(0) as u32; |
52 | let end_idx = after.find(char::is_whitespace)? as u32; | 52 | let end_idx = after.find(char::is_whitespace).unwrap_or(after.len()) as u32; |
53 | 53 | ||
54 | let from: TextUnit = (start_idx + 1).into(); | 54 | let from: TextUnit = (start_idx + 1).into(); |
55 | let to: TextUnit = (cursor_position + end_idx).into(); | 55 | let to: TextUnit = (cursor_position + end_idx).into(); |
56 | 56 | ||
57 | Some(TextRange::from_to(from, to) + leaf.range().start()) | 57 | let range = TextRange::from_to(from, to); |
58 | if range.is_empty() { | ||
59 | None | ||
60 | } else { | ||
61 | Some(range + leaf.range().start()) | ||
62 | } | ||
58 | } | 63 | } |
59 | 64 | ||
60 | fn extend_ws(root: SyntaxNodeRef, ws: SyntaxNodeRef, offset: TextUnit) -> TextRange { | 65 | fn extend_ws(root: SyntaxNodeRef, ws: SyntaxNodeRef, offset: TextUnit) -> TextRange { |
@@ -179,7 +184,21 @@ fn bar(){} | |||
179 | 184 | ||
180 | // fn foo(){} | 185 | // fn foo(){} |
181 | "#, | 186 | "#, |
182 | &["// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"], | 187 | &["1", "// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"], |
188 | ); | ||
189 | |||
190 | do_check( | ||
191 | r#" | ||
192 | // #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
193 | // pub enum Direction { | ||
194 | // <|> Next, | ||
195 | // Prev | ||
196 | // } | ||
197 | "#, | ||
198 | &[ | ||
199 | "// Next,", | ||
200 | "// #[derive(Debug, Clone, Copy, PartialEq, Eq)]\n// pub enum Direction {\n// Next,\n// Prev\n// }", | ||
201 | ], | ||
183 | ); | 202 | ); |
184 | } | 203 | } |
185 | 204 | ||
diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs index 6d3b0514a..9e25decfb 100644 --- a/crates/ra_editor/src/symbols.rs +++ b/crates/ra_editor/src/symbols.rs | |||
@@ -50,6 +50,61 @@ impl FileSymbol { | |||
50 | }) | 50 | }) |
51 | .nth(0) | 51 | .nth(0) |
52 | } | 52 | } |
53 | /// Get a description of this node. | ||
54 | /// | ||
55 | /// e.g. `struct Name`, `enum Name`, `fn Name` | ||
56 | pub fn description(&self, file: &SourceFileNode) -> Option<String> { | ||
57 | // TODO: After type inference is done, add type information to improve the output | ||
58 | file.syntax() | ||
59 | .descendants() | ||
60 | .filter(|node| node.kind() == self.kind && node.range() == self.node_range) | ||
61 | .filter_map(|node: SyntaxNodeRef| { | ||
62 | // TODO: Refactor to be have less repetition | ||
63 | visitor() | ||
64 | .visit(|node: ast::FnDef| { | ||
65 | let mut string = "fn ".to_string(); | ||
66 | node.name()?.syntax().text().push_to(&mut string); | ||
67 | Some(string) | ||
68 | }) | ||
69 | .visit(|node: ast::StructDef| { | ||
70 | let mut string = "struct ".to_string(); | ||
71 | node.name()?.syntax().text().push_to(&mut string); | ||
72 | Some(string) | ||
73 | }) | ||
74 | .visit(|node: ast::EnumDef| { | ||
75 | let mut string = "enum ".to_string(); | ||
76 | node.name()?.syntax().text().push_to(&mut string); | ||
77 | Some(string) | ||
78 | }) | ||
79 | .visit(|node: ast::TraitDef| { | ||
80 | let mut string = "trait ".to_string(); | ||
81 | node.name()?.syntax().text().push_to(&mut string); | ||
82 | Some(string) | ||
83 | }) | ||
84 | .visit(|node: ast::Module| { | ||
85 | let mut string = "mod ".to_string(); | ||
86 | node.name()?.syntax().text().push_to(&mut string); | ||
87 | Some(string) | ||
88 | }) | ||
89 | .visit(|node: ast::TypeDef| { | ||
90 | let mut string = "type ".to_string(); | ||
91 | node.name()?.syntax().text().push_to(&mut string); | ||
92 | Some(string) | ||
93 | }) | ||
94 | .visit(|node: ast::ConstDef| { | ||
95 | let mut string = "const ".to_string(); | ||
96 | node.name()?.syntax().text().push_to(&mut string); | ||
97 | Some(string) | ||
98 | }) | ||
99 | .visit(|node: ast::StaticDef| { | ||
100 | let mut string = "static ".to_string(); | ||
101 | node.name()?.syntax().text().push_to(&mut string); | ||
102 | Some(string) | ||
103 | }) | ||
104 | .accept(node)? | ||
105 | }) | ||
106 | .nth(0) | ||
107 | } | ||
53 | } | 108 | } |
54 | 109 | ||
55 | pub fn file_symbols(file: &SourceFileNode) -> Vec<FileSymbol> { | 110 | pub fn file_symbols(file: &SourceFileNode) -> Vec<FileSymbol> { |
diff --git a/crates/ra_hir/src/function/mod.rs b/crates/ra_hir/src/function.rs index 5187dc051..5187dc051 100644 --- a/crates/ra_hir/src/function/mod.rs +++ b/crates/ra_hir/src/function.rs | |||
diff --git a/crates/ra_hir/src/module/mod.rs b/crates/ra_hir/src/module.rs index 580c737c3..580c737c3 100644 --- a/crates/ra_hir/src/module/mod.rs +++ b/crates/ra_hir/src/module.rs | |||
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs index 0eec38797..9f144e139 100644 --- a/crates/ra_hir/src/module/imp.rs +++ b/crates/ra_hir/src/module/imp.rs | |||
@@ -164,26 +164,26 @@ fn resolve_submodule( | |||
164 | 164 | ||
165 | let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); | 165 | let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); |
166 | let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); | 166 | let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); |
167 | let points_to: Vec<FileId>; | 167 | let file_dir_mod = RelativePathBuf::from(format!("../{}/{}.rs", mod_name, name)); |
168 | let problem: Option<Problem>; | 168 | let tmp1; |
169 | if is_dir_owner { | 169 | let tmp2; |
170 | points_to = [&file_mod, &dir_mod] | 170 | let candidates = if is_dir_owner { |
171 | .iter() | 171 | tmp1 = [&file_mod, &dir_mod]; |
172 | .filter_map(|path| file_resolver.resolve(file_id, path)) | 172 | tmp1.iter() |
173 | .collect(); | ||
174 | problem = if points_to.is_empty() { | ||
175 | Some(Problem::UnresolvedModule { | ||
176 | candidate: file_mod, | ||
177 | }) | ||
178 | } else { | ||
179 | None | ||
180 | } | ||
181 | } else { | 173 | } else { |
182 | points_to = Vec::new(); | 174 | tmp2 = [&file_dir_mod]; |
183 | problem = Some(Problem::NotDirOwner { | 175 | tmp2.iter() |
184 | move_to: RelativePathBuf::from(format!("../{}/mod.rs", mod_name)), | 176 | }; |
185 | candidate: file_mod, | 177 | |
186 | }); | 178 | let points_to = candidates |
187 | } | 179 | .filter_map(|path| file_resolver.resolve(file_id, path)) |
180 | .collect::<Vec<_>>(); | ||
181 | let problem = if points_to.is_empty() { | ||
182 | Some(Problem::UnresolvedModule { | ||
183 | candidate: if is_dir_owner { file_mod } else { file_dir_mod }, | ||
184 | }) | ||
185 | } else { | ||
186 | None | ||
187 | }; | ||
188 | (points_to, problem) | 188 | (points_to, problem) |
189 | } | 189 | } |
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop.rs index 0e1878906..0e1878906 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index af21254e4..92e92f836 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -203,8 +203,12 @@ pub fn handle_goto_definition( | |||
203 | params: req::TextDocumentPositionParams, | 203 | params: req::TextDocumentPositionParams, |
204 | ) -> Result<Option<req::GotoDefinitionResponse>> { | 204 | ) -> Result<Option<req::GotoDefinitionResponse>> { |
205 | let position = params.try_conv_with(&world)?; | 205 | let position = params.try_conv_with(&world)?; |
206 | let rr = match world.analysis().approximately_resolve_symbol(position)? { | ||
207 | None => return Ok(None), | ||
208 | Some(it) => it, | ||
209 | }; | ||
206 | let mut res = Vec::new(); | 210 | let mut res = Vec::new(); |
207 | for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? { | 211 | for (file_id, symbol) in rr.resolves_to { |
208 | let line_index = world.analysis().file_line_index(file_id); | 212 | let line_index = world.analysis().file_line_index(file_id); |
209 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; | 213 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; |
210 | res.push(location) | 214 | res.push(location) |
@@ -504,26 +508,30 @@ pub fn handle_hover( | |||
504 | world: ServerWorld, | 508 | world: ServerWorld, |
505 | params: req::TextDocumentPositionParams, | 509 | params: req::TextDocumentPositionParams, |
506 | ) -> Result<Option<Hover>> { | 510 | ) -> Result<Option<Hover>> { |
511 | // TODO: Cut down on number of allocations | ||
507 | let position = params.try_conv_with(&world)?; | 512 | let position = params.try_conv_with(&world)?; |
508 | let line_index = world.analysis().file_line_index(position.file_id); | 513 | let line_index = world.analysis().file_line_index(position.file_id); |
509 | 514 | let rr = match world.analysis().approximately_resolve_symbol(position)? { | |
510 | for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? { | 515 | None => return Ok(None), |
511 | let range = symbol.node_range.conv_with(&line_index); | 516 | Some(it) => it, |
512 | let comment = world.analysis.doc_comment_for(file_id, symbol)?; | 517 | }; |
513 | 518 | let mut result = Vec::new(); | |
514 | if comment.is_some() { | 519 | for (file_id, symbol) in rr.resolves_to { |
515 | let contents = HoverContents::Scalar(MarkedString::String(comment.unwrap())); | 520 | if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? { |
516 | 521 | result.push(docs); | |
517 | return Ok(Some(Hover { | ||
518 | contents, | ||
519 | range: Some(range), | ||
520 | })); | ||
521 | } | 522 | } |
522 | } | 523 | } |
523 | 524 | let range = rr.reference_range.conv_with(&line_index); | |
525 | if result.len() > 0 { | ||
526 | return Ok(Some(Hover { | ||
527 | contents: HoverContents::Scalar(MarkedString::String(result.join("\n\n---\n"))), | ||
528 | range: Some(range), | ||
529 | })); | ||
530 | } | ||
524 | Ok(None) | 531 | Ok(None) |
525 | } | 532 | } |
526 | 533 | ||
534 | /// Test doc comment | ||
527 | pub fn handle_prepare_rename( | 535 | pub fn handle_prepare_rename( |
528 | world: ServerWorld, | 536 | world: ServerWorld, |
529 | params: req::TextDocumentPositionParams, | 537 | params: req::TextDocumentPositionParams, |
diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo.rs index 4b3548ea9..4b3548ea9 100644 --- a/crates/ra_syntax/src/algo/mod.rs +++ b/crates/ra_syntax/src/algo.rs | |||
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast.rs index 91c67119f..91c67119f 100644 --- a/crates/ra_syntax/src/ast/mod.rs +++ b/crates/ra_syntax/src/ast.rs | |||
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 53cd2118f..eed67637e 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -25,9 +25,9 @@ Grammar( | |||
25 | ["^", "CARET"], | 25 | ["^", "CARET"], |
26 | ["%", "PERCENT"], | 26 | ["%", "PERCENT"], |
27 | ], | 27 | ], |
28 | // TODO: Confirm surmision: the tokens which cannot be recorded in a single UTF-8 byte | 28 | // Tokens for which the longest match must be chosen (e.g. `..` is a DOTDOT, but `.` is a DOT) |
29 | multi_byte_tokens: [ | 29 | multi_byte_tokens: [ |
30 | [".", "DOT"], // Note: DOT is here because <TODO: REASON> | 30 | [".", "DOT"], |
31 | ["..", "DOTDOT"], | 31 | ["..", "DOTDOT"], |
32 | ["...", "DOTDOTDOT"], | 32 | ["...", "DOTDOTDOT"], |
33 | ["..=", "DOTDOTEQ"], | 33 | ["..=", "DOTDOTEQ"], |
diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar.rs index 06a37d648..06a37d648 100644 --- a/crates/ra_syntax/src/grammar/mod.rs +++ b/crates/ra_syntax/src/grammar.rs | |||
diff --git a/crates/ra_syntax/src/grammar/expressions/mod.rs b/crates/ra_syntax/src/grammar/expressions.rs index 60c8602f9..60c8602f9 100644 --- a/crates/ra_syntax/src/grammar/expressions/mod.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
diff --git a/crates/ra_syntax/src/grammar/items/mod.rs b/crates/ra_syntax/src/grammar/items.rs index 4473c2fab..4473c2fab 100644 --- a/crates/ra_syntax/src/grammar/items/mod.rs +++ b/crates/ra_syntax/src/grammar/items.rs | |||
diff --git a/crates/ra_syntax/src/lexer/mod.rs b/crates/ra_syntax/src/lexer.rs index f388da273..f388da273 100644 --- a/crates/ra_syntax/src/lexer/mod.rs +++ b/crates/ra_syntax/src/lexer.rs | |||
diff --git a/crates/ra_syntax/src/parser_impl/mod.rs b/crates/ra_syntax/src/parser_impl.rs index cb6e370ac..cb6e370ac 100644 --- a/crates/ra_syntax/src/parser_impl/mod.rs +++ b/crates/ra_syntax/src/parser_impl.rs | |||
diff --git a/crates/ra_syntax/src/string_lexing/mod.rs b/crates/ra_syntax/src/string_lexing.rs index 94853331f..94853331f 100644 --- a/crates/ra_syntax/src/string_lexing/mod.rs +++ b/crates/ra_syntax/src/string_lexing.rs | |||
diff --git a/crates/ra_syntax/src/syntax_kinds/mod.rs b/crates/ra_syntax/src/syntax_kinds.rs index d53886676..d53886676 100644 --- a/crates/ra_syntax/src/syntax_kinds/mod.rs +++ b/crates/ra_syntax/src/syntax_kinds.rs | |||
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs index c43a8bf65..3a869ad34 100644 --- a/crates/ra_syntax/src/syntax_kinds/generated.rs +++ b/crates/ra_syntax/src/syntax_kinds/generated.rs | |||
@@ -560,4 +560,3 @@ impl SyntaxKind { | |||
560 | Some(tok) | 560 | Some(tok) |
561 | } | 561 | } |
562 | } | 562 | } |
563 | |||
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera index c37e57702..21f9444b1 100644 --- a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera +++ b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera | |||
@@ -75,4 +75,3 @@ impl SyntaxKind { | |||
75 | Some(tok) | 75 | Some(tok) |
76 | } | 76 | } |
77 | } | 77 | } |
78 | |||
diff --git a/crates/ra_syntax/src/validation/mod.rs b/crates/ra_syntax/src/validation.rs index bdee8120c..bdee8120c 100644 --- a/crates/ra_syntax/src/validation/mod.rs +++ b/crates/ra_syntax/src/validation.rs | |||
diff --git a/crates/ra_syntax/src/yellow/mod.rs b/crates/ra_syntax/src/yellow.rs index cacd89dc8..cacd89dc8 100644 --- a/crates/ra_syntax/src/yellow/mod.rs +++ b/crates/ra_syntax/src/yellow.rs | |||
diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs index e312df537..36a7c83e2 100644 --- a/crates/tools/src/main.rs +++ b/crates/tools/src/main.rs | |||
@@ -79,15 +79,21 @@ fn tests_from_dir(dir: &Path) -> Result<HashMap<String, Test>> { | |||
79 | if entry.path().extension().unwrap_or_default() != "rs" { | 79 | if entry.path().extension().unwrap_or_default() != "rs" { |
80 | continue; | 80 | continue; |
81 | } | 81 | } |
82 | let text = fs::read_to_string(entry.path())?; | 82 | process_file(&mut res, entry.path())?; |
83 | } | ||
84 | let grammar_rs = dir.parent().unwrap().join("grammar.rs"); | ||
85 | process_file(&mut res, &grammar_rs)?; | ||
86 | return Ok(res); | ||
87 | fn process_file(res: &mut HashMap<String, Test>, path: &Path) -> Result<()> { | ||
88 | let text = fs::read_to_string(path)?; | ||
83 | 89 | ||
84 | for (_, test) in collect_tests(&text) { | 90 | for (_, test) in collect_tests(&text) { |
85 | if let Some(old_test) = res.insert(test.name.clone(), test) { | 91 | if let Some(old_test) = res.insert(test.name.clone(), test) { |
86 | bail!("Duplicate test: {}", old_test.name) | 92 | bail!("Duplicate test: {}", old_test.name) |
87 | } | 93 | } |
88 | } | 94 | } |
95 | Ok(()) | ||
89 | } | 96 | } |
90 | Ok(res) | ||
91 | } | 97 | } |
92 | 98 | ||
93 | fn existing_tests(dir: &Path) -> Result<HashMap<String, (PathBuf, Test)>> { | 99 | fn existing_tests(dir: &Path) -> Result<HashMap<String, (PathBuf, Test)>> { |