From f88e0700e6c4a9b195739154f8683704762df1bd Mon Sep 17 00:00:00 2001 From: DJMcNab <36049421+DJMcNab@users.noreply.github.com> Date: Sat, 8 Dec 2018 16:02:23 +0000 Subject: [PATCH] Add a better text for hover and stop duplicating work done in approximatelly_resolve_symbol --- crates/ra_analysis/src/imp.rs | 11 ++++ crates/ra_analysis/src/lib.rs | 5 +- crates/ra_analysis/tests/tests.rs | 12 ++-- crates/ra_editor/src/symbols.rs | 55 +++++++++++++++++++ .../ra_lsp_server/src/main_loop/handlers.rs | 43 ++++++++------- .../ra_syntax/src/syntax_kinds/generated.rs | 1 - .../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 e9af98474b2..07357fc84f8 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -323,6 +323,17 @@ pub fn doc_comment_for( Ok(symbol.docs(&file)) } + pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable> { + let file = self.db.source_file(file_id); + let result = match (symbol.description(&file), symbol.docs(&file)) { + (Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs), + (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"), + (None, Some(docs)) => Some(docs), + _ => None, + }; + + Ok(result) + } pub fn diagnostics(&self, file_id: FileId) -> Cancelable> { 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 4b8b1081679..d33f3e4ca89 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -236,7 +236,7 @@ pub fn symbol_search(&self, query: Query) -> Cancelable Cancelable> { + ) -> Cancelable)>> { self.imp.approximately_resolve_symbol(position) } pub fn find_all_refs(&self, position: FilePosition) -> Cancelable> { @@ -249,6 +249,9 @@ pub fn doc_comment_for( ) -> Cancelable> { self.imp.doc_comment_for(file_id, symbol) } + pub fn doc_text_for(&self, file_id: FileId, symbol: FileSymbol) -> Cancelable> { + self.imp.doc_text_for(file_id, symbol) + } pub fn parent_module(&self, position: FilePosition) -> Cancelable> { self.imp.parent_module(position) } diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 4ce2c5c85d9..05ad687aeb6 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs @@ -21,9 +21,9 @@ enum E { X(Foo<|>) } ", ); - let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); + let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); assert_eq_dbg( - r#"[(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })]"#, + r#"([23; 26), [(FileId(1), FileSymbol { name: "Foo", node_range: [0; 11), kind: STRUCT_DEF })])"#, &symbols, ); } @@ -39,9 +39,9 @@ fn test_resolve_module() { ", ); - let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); + let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); assert_eq_dbg( - r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, + r#"([4; 7), [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })])"#, &symbols, ); @@ -54,9 +54,9 @@ fn test_resolve_module() { ", ); - let symbols = analysis.approximately_resolve_symbol(pos).unwrap(); + let symbols = analysis.approximately_resolve_symbol(pos).unwrap().unwrap(); assert_eq_dbg( - r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, + r#"([4; 7), [(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })])"#, &symbols, ); } diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs index 6d3b0514a23..9e25decfbc3 100644 --- a/crates/ra_editor/src/symbols.rs +++ b/crates/ra_editor/src/symbols.rs @@ -50,6 +50,61 @@ fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option { }) .nth(0) } + /// Get a description of this node. + /// + /// e.g. `struct Name`, `enum Name`, `fn Name` + pub fn description(&self, file: &SourceFileNode) -> Option { + // TODO: After type inference is done, add type information to improve the output + file.syntax() + .descendants() + .filter(|node| node.kind() == self.kind && node.range() == self.node_range) + .filter_map(|node: SyntaxNodeRef| { + // TODO: Refactor to be have less repetition + visitor() + .visit(|node: ast::FnDef| { + let mut string = "fn ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::StructDef| { + let mut string = "struct ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::EnumDef| { + let mut string = "enum ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::TraitDef| { + let mut string = "trait ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::Module| { + let mut string = "mod ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::TypeDef| { + let mut string = "type ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::ConstDef| { + let mut string = "const ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .visit(|node: ast::StaticDef| { + let mut string = "static ".to_string(); + node.name()?.syntax().text().push_to(&mut string); + Some(string) + }) + .accept(node)? + }) + .nth(0) + } } pub fn file_symbols(file: &SourceFileNode) -> Vec { diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 013345acb87..7d923404569 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( ) -> Result> { let position = params.try_conv_with(&world)?; let mut res = Vec::new(); - for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? { + for (file_id, symbol) in match world.analysis().approximately_resolve_symbol(position)? { + None => return Ok(None), + Some(it) => it.1, + } { let line_index = world.analysis().file_line_index(file_id); let location = to_location(file_id, symbol.node_range, &world, &line_index)?; res.push(location) @@ -504,33 +507,31 @@ pub fn handle_hover( world: ServerWorld, params: req::TextDocumentPositionParams, ) -> Result> { + // TODO: Cut down on number of allocations let position = params.try_conv_with(&world)?; let line_index = world.analysis().file_line_index(position.file_id); - let file = world.analysis().file_syntax(position.file_id); - - for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? { - let comment = world.analysis.doc_comment_for(file_id, symbol)?; - - if comment.is_some() { - let range = match ra_syntax::algo::find_leaf_at_offset(file.syntax(), position.offset) - .left_biased() - { - None => return Ok(None), - Some(it) => it.range(), - }; - let range = range.conv_with(&line_index); - let contents = HoverContents::Scalar(MarkedString::String(comment.unwrap())); - - return Ok(Some(Hover { - contents, - range: Some(range), - })); + let (range, resolved) = match world.analysis().approximately_resolve_symbol(position)? { + None => return Ok(None), + Some(it) => it, + }; + let mut result = Vec::new(); + for (file_id, symbol) in resolved { + if let Some(docs) = world.analysis().doc_text_for(file_id, symbol)? { + result.push(docs); } } - + let range = range.conv_with(&line_index); + if result.len() > 0 { + return Ok(Some(Hover { + contents: HoverContents::Scalar(MarkedString::String(result.join("\n\n---\n"))), + range: Some(range), + })); + } Ok(None) } + +/// Test doc comment pub fn handle_prepare_rename( world: ServerWorld, params: req::TextDocumentPositionParams, diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs index c43a8bf6538..3a869ad34b3 100644 --- a/crates/ra_syntax/src/syntax_kinds/generated.rs +++ b/crates/ra_syntax/src/syntax_kinds/generated.rs @@ -560,4 +560,3 @@ pub(crate) fn from_char(c: char) -> Option { Some(tok) } } - diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera index c37e5770220..21f9444b1e7 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 { Some(tok) } } -