aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/hover.rs57
-rw-r--r--crates/ra_analysis/src/imp.rs26
-rw-r--r--crates/ra_analysis/src/lib.rs17
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs50
4 files changed, 83 insertions, 67 deletions
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 @@
1use ra_db::{Cancelable, SyntaxDatabase};
2use ra_syntax::{ast, AstNode};
3
4use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange};
5
6pub(crate) fn hover(
7 db: &RootDatabase,
8 position: FilePosition,
9) -> Cancelable<Option<RangeInfo<String>>> {
10 let mut res = Vec::new();
11 let range = if let Some(rr) = db.approximately_resolve_symbol(position)? {
12 for nav in rr.resolves_to {
13 res.extend(db.doc_text_for(nav)?)
14 }
15 rr.reference_range
16 } else {
17 let file = db.source_file(position.file_id);
18 let expr: ast::Expr = ctry!(ra_editor::find_node_at_offset(
19 file.syntax(),
20 position.offset
21 ));
22 let frange = FileRange {
23 file_id: position.file_id,
24 range: expr.syntax().range(),
25 };
26 res.extend(db.type_of(frange)?);
27 expr.syntax().range()
28 };
29 if res.is_empty() {
30 return Ok(None);
31 }
32 let res = RangeInfo::new(range, res.join("\n\n---\n"));
33 Ok(Some(res))
34}
35
36#[cfg(test)]
37mod tests {
38 use ra_syntax::TextRange;
39
40 use crate::mock_analysis::single_file_with_position;
41
42 #[test]
43 fn hover_shows_type_of_an_expression() {
44 let (analysis, position) = single_file_with_position(
45 "
46 pub fn foo() -> u32 { 1 }
47
48 fn main() {
49 let foo_test = foo()<|>;
50 }
51 ",
52 );
53 let hover = analysis.hover(position).unwrap().unwrap();
54 assert_eq!(hover.range, TextRange::from_to(95.into(), 100.into()));
55 assert_eq!(hover.info, "u32");
56 }
57}
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 {
269 Ok(result) 269 Ok(result)
270 } 270 }
271 271
272 pub(crate) fn hover(&self, position: FilePosition) -> Cancelable<Option<(TextRange, String)>> {
273 let mut res = Vec::new();
274 let range = if let Some(rr) = self.approximately_resolve_symbol(position)? {
275 for nav in rr.resolves_to {
276 res.extend(self.doc_text_for(nav)?)
277 }
278 rr.reference_range
279 } else {
280 let file = self.source_file(position.file_id);
281 let expr: ast::Expr = ctry!(ra_editor::find_node_at_offset(
282 file.syntax(),
283 position.offset
284 ));
285 let frange = FileRange {
286 file_id: position.file_id,
287 range: expr.syntax().range(),
288 };
289 res.extend(self.type_of(frange)?);
290 expr.syntax().range()
291 };
292 if res.is_empty() {
293 return Ok(None);
294 }
295 Ok(Some((range, res.join("\n\n---\n"))))
296 }
297
298 pub(crate) fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { 272 pub(crate) fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
299 let syntax = self.source_file(file_id); 273 let syntax = self.source_file(file_id);
300 274
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;
21 21
22mod extend_selection; 22mod extend_selection;
23mod syntax_highlighting; 23mod syntax_highlighting;
24mod hover;
24 25
25use std::{fmt, sync::Arc}; 26use std::{fmt, sync::Arc};
26 27
@@ -260,6 +261,18 @@ impl NavigationTarget {
260 } 261 }
261} 262}
262 263
264#[derive(Debug)]
265pub struct RangeInfo<T> {
266 pub range: TextRange,
267 pub info: T,
268}
269
270impl<T> RangeInfo<T> {
271 fn new(range: TextRange, info: T) -> RangeInfo<T> {
272 RangeInfo { range, info }
273 }
274}
275
263/// Result of "goto def" query. 276/// Result of "goto def" query.
264#[derive(Debug)] 277#[derive(Debug)]
265pub struct ReferenceResolution { 278pub struct ReferenceResolution {
@@ -394,6 +407,10 @@ impl Analysis {
394 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> { 407 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
395 self.db.doc_text_for(nav) 408 self.db.doc_text_for(nav)
396 } 409 }
410 /// Returns a short text descrbing element at position.
411 pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> {
412 hover::hover(&*self.db, position)
413 }
397 /// Returns a `mod name;` declaration which created the current module. 414 /// Returns a `mod name;` declaration which created the current module.
398 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { 415 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
399 self.db.parent_module(position) 416 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::{
9 Range, WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, 9 Range, WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover,
10 HoverContents, DocumentFormattingParams, DocumentHighlight, 10 HoverContents, DocumentFormattingParams, DocumentHighlight,
11}; 11};
12use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FileRange, FilePosition, Severity, NavigationTarget}; 12use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FileRange, FilePosition, Severity};
13use ra_syntax::{TextUnit, text_utils::intersect}; 13use ra_syntax::{TextUnit, text_utils::intersect};
14use ra_text_edit::text_utils::contains_offset_nonstrict; 14use ra_text_edit::text_utils::contains_offset_nonstrict;
15use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
@@ -509,36 +509,18 @@ pub fn handle_hover(
509 world: ServerWorld, 509 world: ServerWorld,
510 params: req::TextDocumentPositionParams, 510 params: req::TextDocumentPositionParams,
511) -> Result<Option<Hover>> { 511) -> Result<Option<Hover>> {
512 // TODO: Cut down on number of allocations
513 let position = params.try_conv_with(&world)?; 512 let position = params.try_conv_with(&world)?;
514 let line_index = world.analysis().file_line_index(position.file_id); 513 let info = match world.analysis().hover(position)? {
515 let rr = match world.analysis().approximately_resolve_symbol(position)? {
516 None => return Ok(None), 514 None => return Ok(None),
517 Some(it) => it, 515 Some(info) => info,
518 }; 516 };
519 let mut result = Vec::new(); 517 let line_index = world.analysis.file_line_index(position.file_id);
520 let file_id = params.text_document.try_conv_with(&world)?; 518 let range = info.range.conv_with(&line_index);
521 let file_range = FileRange { 519 let res = Hover {
522 file_id, 520 contents: HoverContents::Scalar(MarkedString::String(info.info)),
523 range: rr.reference_range, 521 range: Some(range),
524 }; 522 };
525 if let Some(type_name) = get_type(&world, file_range) { 523 Ok(Some(res))
526 result.push(type_name);
527 }
528 for nav in rr.resolves_to {
529 if let Some(docs) = get_doc_text(&world, nav) {
530 result.push(docs);
531 }
532 }
533
534 let range = rr.reference_range.conv_with(&line_index);
535 if result.len() > 0 {
536 return Ok(Some(Hover {
537 contents: HoverContents::Scalar(MarkedString::String(result.join("\n\n---\n"))),
538 range: Some(range),
539 }));
540 }
541 Ok(None)
542} 524}
543 525
544/// Test doc comment 526/// Test doc comment
@@ -762,17 +744,3 @@ fn to_diagnostic_severity(severity: Severity) -> DiagnosticSeverity {
762 WeakWarning => DiagnosticSeverity::Hint, 744 WeakWarning => DiagnosticSeverity::Hint,
763 } 745 }
764} 746}
765
766fn get_type(world: &ServerWorld, file_range: FileRange) -> Option<String> {
767 match world.analysis().type_of(file_range) {
768 Ok(result) => result,
769 _ => None,
770 }
771}
772
773fn get_doc_text(world: &ServerWorld, nav: NavigationTarget) -> Option<String> {
774 match world.analysis().doc_text_for(nav) {
775 Ok(result) => result,
776 _ => None,
777 }
778}