diff options
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 11 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ra_analysis/tests/tests.rs | 12 | ||||
-rw-r--r-- | crates/ra_editor/src/symbols.rs | 55 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 43 | ||||
-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 |
7 files changed, 98 insertions, 30 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index e9af98474..07357fc84 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -323,6 +323,17 @@ impl AnalysisImpl { | |||
323 | 323 | ||
324 | Ok(symbol.docs(&file)) | 324 | Ok(symbol.docs(&file)) |
325 | } | 325 | } |
326 | pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> { | ||
327 | let file = self.db.source_file(file_id); | ||
328 | let result = match (symbol.description(&file), symbol.docs(&file)) { | ||
329 | (Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs), | ||
330 | (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"), | ||
331 | (None, Some(docs)) => Some(docs), | ||
332 | _ => None, | ||
333 | }; | ||
334 | |||
335 | Ok(result) | ||
336 | } | ||
326 | 337 | ||
327 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 338 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
328 | let syntax = self.db.source_file(file_id); | 339 | 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..d33f3e4ca 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -236,7 +236,7 @@ impl Analysis { | |||
236 | pub fn approximately_resolve_symbol( | 236 | pub fn approximately_resolve_symbol( |
237 | &self, | 237 | &self, |
238 | position: FilePosition, | 238 | position: FilePosition, |
239 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 239 | ) -> Cancelable<Option<(TextRange, Vec<(FileId, FileSymbol)>)>> { |
240 | self.imp.approximately_resolve_symbol(position) | 240 | self.imp.approximately_resolve_symbol(position) |
241 | } | 241 | } |
242 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { | 242 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { |
@@ -249,6 +249,9 @@ impl Analysis { | |||
249 | ) -> Cancelable<Option<String>> { | 249 | ) -> Cancelable<Option<String>> { |
250 | self.imp.doc_comment_for(file_id, symbol) | 250 | self.imp.doc_comment_for(file_id, symbol) |
251 | } | 251 | } |
252 | pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable<Option<String>> { | ||
253 | self.imp.doc_text_for(file_id, symbol) | ||
254 | } | ||
252 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 255 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
253 | self.imp.parent_module(position) | 256 | self.imp.parent_module(position) |
254 | } | 257 | } |
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 4ce2c5c85..05ad687ae 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -21,9 +21,9 @@ 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#"([23; 26), [(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })])"#, |
27 | &symbols, | 27 | &symbols, |
28 | ); | 28 | ); |
29 | } | 29 | } |
@@ -39,9 +39,9 @@ fn test_resolve_module() { | |||
39 | ", | 39 | ", |
40 | ); | 40 | ); |
41 | 41 | ||
42 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); | 42 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); |
43 | assert_eq_dbg( | 43 | assert_eq_dbg( |
44 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 44 | r#"([4; 7), [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })])"#, |
45 | &symbols, | 45 | &symbols, |
46 | ); | 46 | ); |
47 | 47 | ||
@@ -54,9 +54,9 @@ fn test_resolve_module() { | |||
54 | ", | 54 | ", |
55 | ); | 55 | ); |
56 | 56 | ||
57 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); | 57 | let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); |
58 | assert_eq_dbg( | 58 | assert_eq_dbg( |
59 | r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, | 59 | r#"([4; 7), [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })])"#, |
60 | &symbols, | 60 | &symbols, |
61 | ); | 61 | ); |
62 | } | 62 | } |
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_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 013345acb..7d9234045 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -204,7 +204,10 @@ pub fn handle_goto_definition( | |||
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 mut res = Vec::new(); | 206 | let mut res = Vec::new(); |
207 | for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? { | 207 | for (file_id, symbol) in match world.analysis().approximately_resolve_symbol(position)? { |
208 | None => return Ok(None), | ||
209 | Some(it) => it.1, | ||
210 | } { | ||
208 | let line_index = world.analysis().file_line_index(file_id); | 211 | let line_index = world.analysis().file_line_index(file_id); |
209 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; | 212 | let location = to_location(file_id, symbol.node_range, &world, &line_index)?; |
210 | res.push(location) | 213 | res.push(location) |
@@ -504,33 +507,31 @@ pub fn handle_hover( | |||
504 | world: ServerWorld, | 507 | world: ServerWorld, |
505 | params: req::TextDocumentPositionParams, | 508 | params: req::TextDocumentPositionParams, |
506 | ) -> Result<Option<Hover>> { | 509 | ) -> Result<Option<Hover>> { |
510 | // TODO: Cut down on number of allocations | ||
507 | let position = params.try_conv_with(&world)?; | 511 | let position = params.try_conv_with(&world)?; |
508 | let line_index = world.analysis().file_line_index(position.file_id); | 512 | let line_index = world.analysis().file_line_index(position.file_id); |
509 | let file = world.analysis().file_syntax(position.file_id); | 513 | let (range, resolved) = match world.analysis().approximately_resolve_symbol(position)? { |
510 | 514 | None => return Ok(None), | |
511 | for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? { | 515 | Some(it) => it, |
512 | let comment = world.analysis.doc_comment_for(file_id, symbol)?; | 516 | }; |
513 | 517 | let mut result = Vec::new(); | |
514 | if comment.is_some() { | 518 | for (file_id, symbol) in resolved { |
515 | let range = match ra_syntax::algo::find_leaf_at_offset(file.syntax(), position.offset) | 519 | if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? { |
516 | .left_biased() | 520 | result.push(docs); |
517 | { | ||
518 | None => return Ok(None), | ||
519 | Some(it) => it.range(), | ||
520 | }; | ||
521 | let range = range.conv_with(&line_index); | ||
522 | let contents = HoverContents::Scalar(MarkedString::String(comment.unwrap())); | ||
523 | |||
524 | return Ok(Some(Hover { | ||
525 | contents, | ||
526 | range: Some(range), | ||
527 | })); | ||
528 | } | 521 | } |
529 | } | 522 | } |
530 | 523 | let range = range.conv_with(&line_index); | |
524 | if result.len() > 0 { | ||
525 | return Ok(Some(Hover { | ||
526 | contents: HoverContents::Scalar(MarkedString::String(result.join("\n\n---\n"))), | ||
527 | range: Some(range), | ||
528 | })); | ||
529 | } | ||
531 | Ok(None) | 530 | Ok(None) |
532 | } | 531 | } |
533 | 532 | ||
533 | |||
534 | /// Test doc comment | ||
534 | pub fn handle_prepare_rename( | 535 | pub fn handle_prepare_rename( |
535 | world: ServerWorld, | 536 | world: ServerWorld, |
536 | params: req::TextDocumentPositionParams, | 537 | params: req::TextDocumentPositionParams, |
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 | |||