From 07f0069f342afa17536aa4b9db4250f4d6c83954 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Tue, 9 Apr 2019 14:43:11 +0300 Subject: Move display related things from hover to display --- crates/ra_ide_api/src/display.rs | 27 +++++ crates/ra_ide_api/src/display/navigation_target.rs | 82 ++++++++++++++- crates/ra_ide_api/src/hover.rs | 110 +-------------------- 3 files changed, 110 insertions(+), 109 deletions(-) (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/display.rs b/crates/ra_ide_api/src/display.rs index f1717b008..b68b3a719 100644 --- a/crates/ra_ide_api/src/display.rs +++ b/crates/ra_ide_api/src/display.rs @@ -5,6 +5,7 @@ mod function_signature; mod navigation_target; mod structure; +use crate::db::RootDatabase; use ra_syntax::{ast::{self, AstNode, TypeParamsOwner}, SyntaxKind::{ATTR, COMMENT}}; pub use navigation_target::NavigationTarget; @@ -53,3 +54,29 @@ pub(crate) fn where_predicates(node: &N) -> Vec { } res } + +pub(crate) fn rust_code_markup>(val: CODE) -> String { + rust_code_markup_with_doc::<_, &str>(val, None) +} + +pub(crate) fn rust_code_markup_with_doc(val: CODE, doc: Option) -> String +where + CODE: AsRef, + DOC: AsRef, +{ + if let Some(doc) = doc { + format!("```rust\n{}\n```\n\n{}", val.as_ref(), doc.as_ref()) + } else { + format!("```rust\n{}\n```", val.as_ref()) + } +} + +// FIXME: this should not really use navigation target. Rather, approximately +// resolved symbol should return a `DefId`. +pub(crate) fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option { + match (nav.description(db), nav.docs(db)) { + (Some(desc), docs) => Some(rust_code_markup_with_doc(desc, docs)), + (None, Some(docs)) => Some(docs), + _ => None, + } +} diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index f6d7f3192..3c518faf5 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -1,7 +1,9 @@ -use ra_db::FileId; +use ra_db::{FileId, SourceDatabase}; use ra_syntax::{ - SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast, + SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, TreeArc, SyntaxKind::{self, NAME}, + ast::{self, NameOwner, VisibilityOwner, TypeAscriptionOwner}, + algo::visit::{visitor, Visitor}, }; use hir::{ModuleSource, FieldSource, Name, ImplItem}; @@ -248,4 +250,80 @@ impl NavigationTarget { container_name: None, } } + + pub(crate) fn node(&self, db: &RootDatabase) -> Option> { + let source_file = db.parse(self.file_id()); + let source_file = source_file.syntax(); + let node = source_file + .descendants() + .find(|node| node.kind() == self.kind() && node.range() == self.full_range())? + .to_owned(); + Some(node) + } + + pub(crate) fn docs(&self, db: &RootDatabase) -> Option { + let node = self.node(db)?; + fn doc_comments(node: &N) -> Option { + node.doc_comment_text() + } + + 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::) + .visit(doc_comments::) + .visit(doc_comments::) + .accept(&node)? + } + + /// Get a description of this node. + /// + /// e.g. `struct Name`, `enum Name`, `fn Name` + pub(crate) fn description(&self, db: &RootDatabase) -> Option { + // FIXME: After type inference is done, add type information to improve the output + let node = self.node(db)?; + + fn visit_ascribed_node(node: &T, prefix: &str) -> Option + where + T: NameOwner + VisibilityOwner + TypeAscriptionOwner, + { + let mut string = visit_node(node, prefix)?; + + if let Some(type_ref) = node.ascribed_type() { + string.push_str(": "); + type_ref.syntax().text().push_to(&mut string); + } + + Some(string) + } + + fn visit_node(node: &T, label: &str) -> Option + where + T: NameOwner + VisibilityOwner, + { + let mut string = + node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default(); + string.push_str(label); + string.push_str(node.name()?.text().as_str()); + Some(string) + } + + visitor() + .visit(|node: &ast::FnDef| Some(crate::display::function_label(node))) + .visit(|node: &ast::StructDef| visit_node(node, "struct ")) + .visit(|node: &ast::EnumDef| visit_node(node, "enum ")) + .visit(|node: &ast::TraitDef| visit_node(node, "trait ")) + .visit(|node: &ast::Module| visit_node(node, "mod ")) + .visit(|node: &ast::TypeAliasDef| visit_node(node, "type ")) + .visit(|node: &ast::ConstDef| visit_ascribed_node(node, "const ")) + .visit(|node: &ast::StaticDef| visit_ascribed_node(node, "static ")) + .visit(|node: &ast::NamedFieldDef| visit_ascribed_node(node, "")) + .visit(|node: &ast::EnumVariant| Some(node.name()?.text().to_string())) + .accept(&node)? + } } diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 7d2c57f82..3a8c93b99 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -1,11 +1,11 @@ use ra_db::SourceDatabase; use ra_syntax::{ - AstNode, SyntaxNode, TreeArc, ast::{self, NameOwner, VisibilityOwner, TypeAscriptionOwner}, - algo::{find_covering_element, find_node_at_offset, find_token_at_offset, visit::{visitor, Visitor}}, + AstNode, ast, + algo::{find_covering_element, find_node_at_offset, find_token_at_offset}, }; use hir::HirDisplay; -use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; +use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, display::{rust_code_markup, doc_text_for}}; /// Contains the results when hovering over an item #[derive(Debug, Clone)] @@ -145,110 +145,6 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option { } } -fn rust_code_markup>(val: CODE) -> String { - rust_code_markup_with_doc::<_, &str>(val, None) -} - -fn rust_code_markup_with_doc(val: CODE, doc: Option) -> String -where - CODE: AsRef, - DOC: AsRef, -{ - if let Some(doc) = doc { - format!("```rust\n{}\n```\n\n{}", val.as_ref(), doc.as_ref()) - } else { - format!("```rust\n{}\n```", val.as_ref()) - } -} - -// FIXME: this should not really use navigation target. Rather, approximately -// resolved symbol should return a `DefId`. -fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option { - match (nav.description(db), nav.docs(db)) { - (Some(desc), docs) => Some(rust_code_markup_with_doc(desc, docs)), - (None, Some(docs)) => Some(docs), - _ => None, - } -} - -impl NavigationTarget { - fn node(&self, db: &RootDatabase) -> Option> { - let source_file = db.parse(self.file_id()); - let source_file = source_file.syntax(); - let node = source_file - .descendants() - .find(|node| node.kind() == self.kind() && node.range() == self.full_range())? - .to_owned(); - Some(node) - } - - fn docs(&self, db: &RootDatabase) -> Option { - let node = self.node(db)?; - fn doc_comments(node: &N) -> Option { - node.doc_comment_text() - } - - 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::) - .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 { - // FIXME: After type inference is done, add type information to improve the output - let node = self.node(db)?; - - fn visit_ascribed_node(node: &T, prefix: &str) -> Option - where - T: NameOwner + VisibilityOwner + TypeAscriptionOwner, - { - let mut string = visit_node(node, prefix)?; - - if let Some(type_ref) = node.ascribed_type() { - string.push_str(": "); - type_ref.syntax().text().push_to(&mut string); - } - - Some(string) - } - - fn visit_node(node: &T, label: &str) -> Option - where - T: NameOwner + VisibilityOwner, - { - let mut string = - node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default(); - string.push_str(label); - string.push_str(node.name()?.text().as_str()); - Some(string) - } - - visitor() - .visit(|node: &ast::FnDef| Some(crate::display::function_label(node))) - .visit(|node: &ast::StructDef| visit_node(node, "struct ")) - .visit(|node: &ast::EnumDef| visit_node(node, "enum ")) - .visit(|node: &ast::TraitDef| visit_node(node, "trait ")) - .visit(|node: &ast::Module| visit_node(node, "mod ")) - .visit(|node: &ast::TypeAliasDef| visit_node(node, "type ")) - .visit(|node: &ast::ConstDef| visit_ascribed_node(node, "const ")) - .visit(|node: &ast::StaticDef| visit_ascribed_node(node, "static ")) - .visit(|node: &ast::NamedFieldDef| visit_ascribed_node(node, "")) - .visit(|node: &ast::EnumVariant| Some(node.name()?.text().to_string())) - .accept(&node)? - } -} - #[cfg(test)] mod tests { use ra_syntax::TextRange; -- cgit v1.2.3