diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 819827b95b..166f1484f3 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -364,6 +364,16 @@ impl AnalysisImpl { ret } + pub fn doc_comment_for( + &self, + file_id: FileId, + symbol: FileSymbol, + ) -> Cancelable> { + let file = self.db.file_syntax(file_id); + + Ok(symbol.docs(&file)) + } + pub fn diagnostics(&self, file_id: FileId) -> Cancelable> { let module_tree = self.module_tree(file_id)?; let syntax = self.db.file_syntax(file_id); diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 0ea9ebee7b..db4e1ba867 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -258,6 +258,13 @@ impl Analysis { pub fn find_all_refs(&self, position: FilePosition) -> Cancelable> { Ok(self.imp.find_all_refs(position)) } + pub fn doc_comment_for( + &self, + file_id: FileId, + symbol: FileSymbol + ) -> Cancelable> { + self.imp.doc_comment_for(file_id, symbol) + } pub fn parent_module(&self, position: FilePosition) -> Cancelable> { self.imp.parent_module(position) } diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs index 4e602d0e31..bf3ac6ff22 100644 --- a/crates/ra_editor/src/symbols.rs +++ b/crates/ra_editor/src/symbols.rs @@ -2,7 +2,7 @@ use crate::TextRange; use ra_syntax::{ algo::visit::{visitor, Visitor}, - ast::{self, NameOwner}, + ast::{self, DocCommentsOwner, NameOwner}, AstNode, File, SmolStr, SyntaxKind, SyntaxNodeRef, WalkEvent, }; @@ -22,6 +22,30 @@ pub struct FileSymbol { pub kind: SyntaxKind, } +impl FileSymbol { + pub fn docs(&self, file: &File) -> Option { + file.syntax().descendants() + .filter(|node| node.kind() == self.kind && node.range() == self.node_range) + .filter_map(|node: SyntaxNodeRef| { + fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option { + let comments = node.doc_comment_text(); + if comments.is_empty() { None } else { Some(comments) } + } + + visitor() + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .visit(doc_comments::) + .accept(node)? + }).nth(0) + } +} + pub fn file_symbols(file: &File) -> Vec { file.syntax().descendants().filter_map(to_symbol).collect() } diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 0d02c80731..bcf857fce8 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -16,7 +16,7 @@ pub fn server_capabilities() -> ServerCapabilities { save: None, }, )), - hover_provider: None, + hover_provider: Some(true), completion_provider: Some(CompletionOptions { resolve_provider: None, trigger_characters: None, diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5314a333e8..97ab53f91e 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -4,9 +4,9 @@ use gen_lsp_server::ErrorCode; use languageserver_types::{ CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, - FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, Position, + FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, MarkedString, Position, PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, - WorkspaceEdit, ParameterInformation, SignatureInformation, + WorkspaceEdit, ParameterInformation, SignatureInformation, Hover, HoverContents, }; use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; use ra_syntax::text_utils::contains_offset_nonstrict; @@ -478,6 +478,31 @@ pub fn handle_signature_help( } } +pub fn handle_hover( + world: ServerWorld, + params: req::TextDocumentPositionParams, +) -> Result> { + let position = params.try_conv_with(&world)?; + let line_index = world.analysis().file_line_index(position.file_id); + + for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? { + let range = symbol.node_range.conv_with(&line_index); + let name = symbol.name.to_string(); + let comment = world.analysis.doc_comment_for(file_id, symbol)?; + + if comment.is_some() { + let contents = HoverContents::Scalar(MarkedString::String(comment.unwrap())); + + return Ok(Some(Hover { + contents, + range: Some(range) + })) + } + } + + Ok(None) +} + pub fn handle_prepare_rename( world: ServerWorld, params: req::TextDocumentPositionParams, diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index 229d1b0f70..db878e0aad 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs @@ -259,6 +259,7 @@ fn on_request( .on::(handlers::handle_code_action)? .on::(handlers::handle_folding_range)? .on::(handlers::handle_signature_help)? + .on::(handlers::handle_hover)? .on::(handlers::handle_prepare_rename)? .on::(handlers::handle_rename)? .on::(handlers::handle_references)?