From 9f44d4c56d51fdae1ff073df261b8c897b27c824 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 5 Jan 2019 17:33:31 +0300 Subject: fold doc_comment into hover --- crates/ra_analysis/src/hover.rs | 111 ++++++++++++++++++++++++++++++++++++++-- crates/ra_analysis/src/imp.rs | 104 +------------------------------------ crates/ra_analysis/src/lib.rs | 4 -- 3 files changed, 110 insertions(+), 109 deletions(-) diff --git a/crates/ra_analysis/src/hover.rs b/crates/ra_analysis/src/hover.rs index c3825f6ea..c99d87da6 100644 --- a/crates/ra_analysis/src/hover.rs +++ b/crates/ra_analysis/src/hover.rs @@ -1,7 +1,11 @@ use ra_db::{Cancelable, SyntaxDatabase}; -use ra_syntax::{ast, AstNode}; +use ra_syntax::{ + AstNode, SyntaxNode, + ast::{self, NameOwner}, + algo::visit::{visitor, Visitor}, +}; -use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange}; +use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; pub(crate) fn hover( db: &RootDatabase, @@ -10,7 +14,7 @@ pub(crate) fn hover( 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)?) + res.extend(doc_text_for(db, nav)?) } rr.reference_range } else { @@ -33,6 +37,107 @@ pub(crate) fn hover( Ok(Some(res)) } +// FIXME: this should not really use navigation target. Rather, approximatelly +// resovled symbol should return a `DefId`. +fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Cancelable> { + let result = match (nav.description(db), nav.docs(db)) { + (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) +} + +impl NavigationTarget { + fn node(&self, db: &RootDatabase) -> Option { + let source_file = db.source_file(self.file_id); + let source_file = source_file.syntax(); + let node = source_file + .descendants() + .find(|node| node.kind() == self.kind && node.range() == self.range)? + .owned(); + Some(node) + } + + fn docs(&self, db: &RootDatabase) -> Option { + let node = self.node(db)?; + let node = node.borrowed(); + fn doc_comments<'a, N: ast::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)? + } + + /// Get a description of this node. + /// + /// e.g. `struct Name`, `enum Name`, `fn Name` + fn description(&self, db: &RootDatabase) -> Option { + // TODO: After type inference is done, add type information to improve the output + let node = self.node(db)?; + let node = node.borrowed(); + // 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)? + } +} + #[cfg(test)] mod tests { use ra_syntax::TextRange; diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index eae73c2c4..1e9129c4f 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -8,11 +8,11 @@ use hir::{ use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity}; use ra_syntax::{ - algo::{find_covering_node, visit::{visitor, Visitor}}, + algo::find_covering_node, ast::{self, ArgListOwner, Expr, FnDef, NameOwner}, AstNode, SourceFileNode, SyntaxKind::*, - SyntaxNode, SyntaxNodeRef, TextRange, TextUnit, + SyntaxNodeRef, TextRange, TextUnit, }; use crate::{ @@ -256,18 +256,6 @@ impl db::RootDatabase { Ok(Some((binding, descr))) } } - pub(crate) fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable> { - let result = match (nav.description(self), nav.docs(self)) { - (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(crate) fn diagnostics(&self, file_id: FileId) -> Cancelable> { let syntax = self.source_file(file_id); @@ -506,91 +494,3 @@ impl<'a> FnCallNode<'a> { } } } - -impl NavigationTarget { - fn node(&self, db: &db::RootDatabase) -> Option { - let source_file = db.source_file(self.file_id); - let source_file = source_file.syntax(); - let node = source_file - .descendants() - .find(|node| node.kind() == self.kind && node.range() == self.range)? - .owned(); - Some(node) - } - - fn docs(&self, db: &db::RootDatabase) -> Option { - let node = self.node(db)?; - let node = node.borrowed(); - fn doc_comments<'a, N: ast::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)? - } - - /// Get a description of this node. - /// - /// e.g. `struct Name`, `enum Name`, `fn Name` - fn description(&self, db: &db::RootDatabase) -> Option { - // TODO: After type inference is done, add type information to improve the output - let node = self.node(db)?; - let node = node.borrowed(); - // 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)? - } -} diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 1904ff884..0e32a15f8 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -403,10 +403,6 @@ impl Analysis { pub fn find_all_refs(&self, position: FilePosition) -> Cancelable> { self.db.find_all_refs(position) } - /// Returns documentation string for a given target. - 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) -- cgit v1.2.3