From 3ad0037f907778d20ce6cfd9bf676a467b5734ad Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 5 Jan 2019 17:22:41 +0300 Subject: move hover implementation to ra_analysis --- crates/ra_analysis/src/hover.rs | 57 ++++++++++++++++++++++++++ crates/ra_analysis/src/imp.rs | 26 ------------ crates/ra_analysis/src/lib.rs | 17 ++++++++ crates/ra_lsp_server/src/main_loop/handlers.rs | 50 ++++------------------ 4 files changed, 83 insertions(+), 67 deletions(-) create mode 100644 crates/ra_analysis/src/hover.rs diff --git a/crates/ra_analysis/src/hover.rs b/crates/ra_analysis/src/hover.rs new file mode 100644 index 000000000..c3825f6ea --- /dev/null +++ b/crates/ra_analysis/src/hover.rs @@ -0,0 +1,57 @@ +use ra_db::{Cancelable, SyntaxDatabase}; +use ra_syntax::{ast, AstNode}; + +use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange}; + +pub(crate) fn hover( + db: &RootDatabase, + position: FilePosition, +) -> Cancelable>> { + let mut res = Vec::new(); + let range = if let Some(rr) = db.approximately_resolve_symbol(position)? { + for nav in rr.resolves_to { + res.extend(db.doc_text_for(nav)?) + } + rr.reference_range + } else { + let file = db.source_file(position.file_id); + let expr: ast::Expr = ctry!(ra_editor::find_node_at_offset( + file.syntax(), + position.offset + )); + let frange = FileRange { + file_id: position.file_id, + range: expr.syntax().range(), + }; + res.extend(db.type_of(frange)?); + expr.syntax().range() + }; + if res.is_empty() { + return Ok(None); + } + let res = RangeInfo::new(range, res.join("\n\n---\n")); + Ok(Some(res)) +} + +#[cfg(test)] +mod tests { + use ra_syntax::TextRange; + + use crate::mock_analysis::single_file_with_position; + + #[test] + fn hover_shows_type_of_an_expression() { + let (analysis, position) = single_file_with_position( + " + pub fn foo() -> u32 { 1 } + + fn main() { + let foo_test = foo()<|>; + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(hover.range, TextRange::from_to(95.into(), 100.into())); + assert_eq!(hover.info, "u32"); + } +} diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 10248013c..eae73c2c4 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -269,32 +269,6 @@ impl db::RootDatabase { Ok(result) } - pub(crate) fn hover(&self, position: FilePosition) -> Cancelable> { - let mut res = Vec::new(); - let range = if let Some(rr) = self.approximately_resolve_symbol(position)? { - for nav in rr.resolves_to { - res.extend(self.doc_text_for(nav)?) - } - rr.reference_range - } else { - let file = self.source_file(position.file_id); - let expr: ast::Expr = ctry!(ra_editor::find_node_at_offset( - file.syntax(), - position.offset - )); - let frange = FileRange { - file_id: position.file_id, - range: expr.syntax().range(), - }; - res.extend(self.type_of(frange)?); - expr.syntax().range() - }; - if res.is_empty() { - return Ok(None); - } - Ok(Some((range, res.join("\n\n---\n")))) - } - pub(crate) fn diagnostics(&self, file_id: FileId) -> Cancelable> { let syntax = self.source_file(file_id); diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 1e26a2889..1904ff884 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -21,6 +21,7 @@ mod runnables; mod extend_selection; mod syntax_highlighting; +mod hover; use std::{fmt, sync::Arc}; @@ -260,6 +261,18 @@ impl NavigationTarget { } } +#[derive(Debug)] +pub struct RangeInfo { + pub range: TextRange, + pub info: T, +} + +impl RangeInfo { + fn new(range: TextRange, info: T) -> RangeInfo { + RangeInfo { range, info } + } +} + /// Result of "goto def" query. #[derive(Debug)] pub struct ReferenceResolution { @@ -394,6 +407,10 @@ impl Analysis { pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable> { self.db.doc_text_for(nav) } + /// Returns a short text descrbing element at position. + pub fn hover(&self, position: FilePosition) -> Cancelable>> { + hover::hover(&*self.db, position) + } /// Returns a `mod name;` declaration which created the current module. pub fn parent_module(&self, position: FilePosition) -> Cancelable> { self.db.parent_module(position) diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 2fc4d3649..ffca3f51c 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -9,7 +9,7 @@ use languageserver_types::{ Range, WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, HoverContents, DocumentFormattingParams, DocumentHighlight, }; -use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FileRange, FilePosition, Severity, NavigationTarget}; +use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FileRange, FilePosition, Severity}; use ra_syntax::{TextUnit, text_utils::intersect}; use ra_text_edit::text_utils::contains_offset_nonstrict; use rustc_hash::FxHashMap; @@ -509,36 +509,18 @@ 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 rr = match world.analysis().approximately_resolve_symbol(position)? { + let info = match world.analysis().hover(position)? { None => return Ok(None), - Some(it) => it, + Some(info) => info, }; - let mut result = Vec::new(); - let file_id = params.text_document.try_conv_with(&world)?; - let file_range = FileRange { - file_id, - range: rr.reference_range, + let line_index = world.analysis.file_line_index(position.file_id); + let range = info.range.conv_with(&line_index); + let res = Hover { + contents: HoverContents::Scalar(MarkedString::String(info.info)), + range: Some(range), }; - if let Some(type_name) = get_type(&world, file_range) { - result.push(type_name); - } - for nav in rr.resolves_to { - if let Some(docs) = get_doc_text(&world, nav) { - result.push(docs); - } - } - - let range = rr.reference_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) + Ok(Some(res)) } /// Test doc comment @@ -762,17 +744,3 @@ fn to_diagnostic_severity(severity: Severity) -> DiagnosticSeverity { WeakWarning => DiagnosticSeverity::Hint, } } - -fn get_type(world: &ServerWorld, file_range: FileRange) -> Option { - match world.analysis().type_of(file_range) { - Ok(result) => result, - _ => None, - } -} - -fn get_doc_text(world: &ServerWorld, nav: NavigationTarget) -> Option { - match world.analysis().doc_text_for(nav) { - Ok(result) => result, - _ => None, - } -} -- cgit v1.2.3