From e7c47eb7f599da93f64c5a8d4f8e83ddd3fa1baa Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Thu, 9 Jul 2020 10:19:37 +0200
Subject: [PATCH] Streamline

---
 crates/ra_ide/src/display.rs | 29 -------------------
 crates/ra_ide/src/hover.rs   | 54 ++++++++++++++++++++++--------------
 crates/ra_ide/src/markup.rs  |  3 ++
 3 files changed, 36 insertions(+), 50 deletions(-)

diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs
index 827c094e716..70d2a2dd13c 100644
--- a/crates/ra_ide/src/display.rs
+++ b/crates/ra_ide/src/display.rs
@@ -6,13 +6,10 @@ mod navigation_target;
 mod structure;
 mod short_label;
 
-use std::fmt::Display;
-
 use ra_syntax::{
     ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
     SyntaxKind::{ATTR, COMMENT},
 };
-use stdx::format_to;
 
 pub use function_signature::FunctionSignature;
 pub use navigation_target::NavigationTarget;
@@ -69,29 +66,3 @@ pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
     let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
     format!("{}macro_rules! {}", vis, name)
 }
-
-pub(crate) fn rust_code_markup(code: &impl Display) -> String {
-    rust_code_markup_with_doc(code, None, None)
-}
-
-pub(crate) fn rust_code_markup_with_doc(
-    code: &impl Display,
-    doc: Option<&str>,
-    mod_path: Option<&str>,
-) -> String {
-    let mut buf = String::new();
-
-    if let Some(mod_path) = mod_path {
-        if !mod_path.is_empty() {
-            format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
-        }
-    }
-    format_to!(buf, "```rust\n{}\n```", code);
-
-    if let Some(doc) = doc {
-        format_to!(buf, "\n___");
-        format_to!(buf, "\n\n{}", doc);
-    }
-
-    buf
-}
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 9b480490643..39519df406d 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -9,16 +9,15 @@ use ra_ide_db::{
     RootDatabase,
 };
 use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
+use stdx::format_to;
+use test_utils::mark;
 
 use crate::{
-    display::{
-        macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav,
-    },
+    display::{macro_label, ShortLabel, ToNav, TryToNav},
     markup::Markup,
     runnables::runnable,
     FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
 };
-use test_utils::mark;
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct HoverConfig {
@@ -92,8 +91,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
         }
     };
     if let Some(definition) = definition {
-        if let Some(text) = hover_for_definition(db, definition) {
-            res.markup = text.into();
+        if let Some(markup) = hover_for_definition(db, definition) {
+            res.markup = markup;
             if let Some(action) = show_implementations_action(db, definition) {
                 res.actions.push(action);
             }
@@ -126,7 +125,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
         }
     };
 
-    res.markup = rust_code_markup(&ty.display(db)).into();
+    res.markup = Markup::fenced_block(&ty.display(db));
     let range = sema.original_range(&node).range;
     Some(RangeInfo::new(range, res))
 }
@@ -223,15 +222,28 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
     }
 }
 
-fn hover_text(
+fn hover_markup(
     docs: Option<String>,
     desc: Option<String>,
     mod_path: Option<String>,
-) -> Option<String> {
-    if let Some(desc) = desc {
-        Some(rust_code_markup_with_doc(&desc, docs.as_deref(), mod_path.as_deref()))
-    } else {
-        docs
+) -> Option<Markup> {
+    match desc {
+        Some(desc) => {
+            let mut buf = String::new();
+
+            if let Some(mod_path) = mod_path {
+                if !mod_path.is_empty() {
+                    format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
+                }
+            }
+            format_to!(buf, "```rust\n{}\n```", desc);
+
+            if let Some(doc) = docs {
+                format_to!(buf, "\n___\n\n{}", doc);
+            }
+            Some(buf.into())
+        }
+        None => docs.map(Markup::from),
     }
 }
 
@@ -268,20 +280,20 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
     def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
 }
 
-fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<String> {
+fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
     let mod_path = definition_mod_path(db, &def);
     return match def {
         Definition::Macro(it) => {
             let src = it.source(db);
             let docs = Documentation::from_ast(&src.value).map(Into::into);
-            hover_text(docs, Some(macro_label(&src.value)), mod_path)
+            hover_markup(docs, Some(macro_label(&src.value)), mod_path)
         }
         Definition::Field(it) => {
             let src = it.source(db);
             match src.value {
                 FieldSource::Named(it) => {
                     let docs = Documentation::from_ast(&it).map(Into::into);
-                    hover_text(docs, it.short_label(), mod_path)
+                    hover_markup(docs, it.short_label(), mod_path)
                 }
                 _ => None,
             }
@@ -290,7 +302,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<String> {
             ModuleDef::Module(it) => match it.definition_source(db).value {
                 ModuleSource::Module(it) => {
                     let docs = Documentation::from_ast(&it).map(Into::into);
-                    hover_text(docs, it.short_label(), mod_path)
+                    hover_markup(docs, it.short_label(), mod_path)
                 }
                 _ => None,
             },
@@ -303,23 +315,23 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<String> {
             ModuleDef::Static(it) => from_def_source(db, it, mod_path),
             ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
             ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
-            ModuleDef::BuiltinType(it) => Some(it.to_string()),
+            ModuleDef::BuiltinType(it) => return Some(it.to_string().into()),
         },
-        Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display(db))),
+        Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))),
         Definition::TypeParam(_) | Definition::SelfType(_) => {
             // FIXME: Hover for generic param
             None
         }
     };
 
-    fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<String>
+    fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
     where
         D: HasSource<Ast = A>,
         A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner,
     {
         let src = def.source(db);
         let docs = Documentation::from_ast(&src.value).map(Into::into);
-        hover_text(docs, src.value.short_label(), mod_path)
+        hover_markup(docs, src.value.short_label(), mod_path)
     }
 }
 
diff --git a/crates/ra_ide/src/markup.rs b/crates/ra_ide/src/markup.rs
index 212ca80b7ba..60c193c40ab 100644
--- a/crates/ra_ide/src/markup.rs
+++ b/crates/ra_ide/src/markup.rs
@@ -32,4 +32,7 @@ impl Markup {
     pub fn as_str(&self) -> &str {
         self.text.as_str()
     }
+    pub fn fenced_block(contents: &impl fmt::Display) -> Markup {
+        format!("```rust\n{}\n```", contents).into()
+    }
 }