aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/display.rs29
-rw-r--r--crates/ra_ide/src/hover.rs54
-rw-r--r--crates/ra_ide/src/markup.rs3
3 files changed, 36 insertions, 50 deletions
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs
index 827c094e7..70d2a2dd1 100644
--- a/crates/ra_ide/src/display.rs
+++ b/crates/ra_ide/src/display.rs
@@ -6,13 +6,10 @@ mod navigation_target;
6mod structure; 6mod structure;
7mod short_label; 7mod short_label;
8 8
9use std::fmt::Display;
10
11use ra_syntax::{ 9use ra_syntax::{
12 ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, 10 ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
13 SyntaxKind::{ATTR, COMMENT}, 11 SyntaxKind::{ATTR, COMMENT},
14}; 12};
15use stdx::format_to;
16 13
17pub use function_signature::FunctionSignature; 14pub use function_signature::FunctionSignature;
18pub use navigation_target::NavigationTarget; 15pub use navigation_target::NavigationTarget;
@@ -69,29 +66,3 @@ pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
69 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; 66 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
70 format!("{}macro_rules! {}", vis, name) 67 format!("{}macro_rules! {}", vis, name)
71} 68}
72
73pub(crate) fn rust_code_markup(code: &impl Display) -> String {
74 rust_code_markup_with_doc(code, None, None)
75}
76
77pub(crate) fn rust_code_markup_with_doc(
78 code: &impl Display,
79 doc: Option<&str>,
80 mod_path: Option<&str>,
81) -> String {
82 let mut buf = String::new();
83
84 if let Some(mod_path) = mod_path {
85 if !mod_path.is_empty() {
86 format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
87 }
88 }
89 format_to!(buf, "```rust\n{}\n```", code);
90
91 if let Some(doc) = doc {
92 format_to!(buf, "\n___");
93 format_to!(buf, "\n\n{}", doc);
94 }
95
96 buf
97}
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 9b4804906..39519df40 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -9,16 +9,15 @@ use ra_ide_db::{
9 RootDatabase, 9 RootDatabase,
10}; 10};
11use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; 11use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
12use stdx::format_to;
13use test_utils::mark;
12 14
13use crate::{ 15use crate::{
14 display::{ 16 display::{macro_label, ShortLabel, ToNav, TryToNav},
15 macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav,
16 },
17 markup::Markup, 17 markup::Markup,
18 runnables::runnable, 18 runnables::runnable,
19 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, 19 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
20}; 20};
21use test_utils::mark;
22 21
23#[derive(Clone, Debug, PartialEq, Eq)] 22#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct HoverConfig { 23pub struct HoverConfig {
@@ -92,8 +91,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
92 } 91 }
93 }; 92 };
94 if let Some(definition) = definition { 93 if let Some(definition) = definition {
95 if let Some(text) = hover_for_definition(db, definition) { 94 if let Some(markup) = hover_for_definition(db, definition) {
96 res.markup = text.into(); 95 res.markup = markup;
97 if let Some(action) = show_implementations_action(db, definition) { 96 if let Some(action) = show_implementations_action(db, definition) {
98 res.actions.push(action); 97 res.actions.push(action);
99 } 98 }
@@ -126,7 +125,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
126 } 125 }
127 }; 126 };
128 127
129 res.markup = rust_code_markup(&ty.display(db)).into(); 128 res.markup = Markup::fenced_block(&ty.display(db));
130 let range = sema.original_range(&node).range; 129 let range = sema.original_range(&node).range;
131 Some(RangeInfo::new(range, res)) 130 Some(RangeInfo::new(range, res))
132} 131}
@@ -223,15 +222,28 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
223 } 222 }
224} 223}
225 224
226fn hover_text( 225fn hover_markup(
227 docs: Option<String>, 226 docs: Option<String>,
228 desc: Option<String>, 227 desc: Option<String>,
229 mod_path: Option<String>, 228 mod_path: Option<String>,
230) -> Option<String> { 229) -> Option<Markup> {
231 if let Some(desc) = desc { 230 match desc {
232 Some(rust_code_markup_with_doc(&desc, docs.as_deref(), mod_path.as_deref())) 231 Some(desc) => {
233 } else { 232 let mut buf = String::new();
234 docs 233
234 if let Some(mod_path) = mod_path {
235 if !mod_path.is_empty() {
236 format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
237 }
238 }
239 format_to!(buf, "```rust\n{}\n```", desc);
240
241 if let Some(doc) = docs {
242 format_to!(buf, "\n___\n\n{}", doc);
243 }
244 Some(buf.into())
245 }
246 None => docs.map(Markup::from),
235 } 247 }
236} 248}
237 249
@@ -268,20 +280,20 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
268 def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def))) 280 def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
269} 281}
270 282
271fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<String> { 283fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
272 let mod_path = definition_mod_path(db, &def); 284 let mod_path = definition_mod_path(db, &def);
273 return match def { 285 return match def {
274 Definition::Macro(it) => { 286 Definition::Macro(it) => {
275 let src = it.source(db); 287 let src = it.source(db);
276 let docs = Documentation::from_ast(&src.value).map(Into::into); 288 let docs = Documentation::from_ast(&src.value).map(Into::into);
277 hover_text(docs, Some(macro_label(&src.value)), mod_path) 289 hover_markup(docs, Some(macro_label(&src.value)), mod_path)
278 } 290 }
279 Definition::Field(it) => { 291 Definition::Field(it) => {
280 let src = it.source(db); 292 let src = it.source(db);
281 match src.value { 293 match src.value {
282 FieldSource::Named(it) => { 294 FieldSource::Named(it) => {
283 let docs = Documentation::from_ast(&it).map(Into::into); 295 let docs = Documentation::from_ast(&it).map(Into::into);
284 hover_text(docs, it.short_label(), mod_path) 296 hover_markup(docs, it.short_label(), mod_path)
285 } 297 }
286 _ => None, 298 _ => None,
287 } 299 }
@@ -290,7 +302,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<String> {
290 ModuleDef::Module(it) => match it.definition_source(db).value { 302 ModuleDef::Module(it) => match it.definition_source(db).value {
291 ModuleSource::Module(it) => { 303 ModuleSource::Module(it) => {
292 let docs = Documentation::from_ast(&it).map(Into::into); 304 let docs = Documentation::from_ast(&it).map(Into::into);
293 hover_text(docs, it.short_label(), mod_path) 305 hover_markup(docs, it.short_label(), mod_path)
294 } 306 }
295 _ => None, 307 _ => None,
296 }, 308 },
@@ -303,23 +315,23 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<String> {
303 ModuleDef::Static(it) => from_def_source(db, it, mod_path), 315 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
304 ModuleDef::Trait(it) => from_def_source(db, it, mod_path), 316 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
305 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), 317 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
306 ModuleDef::BuiltinType(it) => Some(it.to_string()), 318 ModuleDef::BuiltinType(it) => return Some(it.to_string().into()),
307 }, 319 },
308 Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display(db))), 320 Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))),
309 Definition::TypeParam(_) | Definition::SelfType(_) => { 321 Definition::TypeParam(_) | Definition::SelfType(_) => {
310 // FIXME: Hover for generic param 322 // FIXME: Hover for generic param
311 None 323 None
312 } 324 }
313 }; 325 };
314 326
315 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<String> 327 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
316 where 328 where
317 D: HasSource<Ast = A>, 329 D: HasSource<Ast = A>,
318 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner, 330 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner,
319 { 331 {
320 let src = def.source(db); 332 let src = def.source(db);
321 let docs = Documentation::from_ast(&src.value).map(Into::into); 333 let docs = Documentation::from_ast(&src.value).map(Into::into);
322 hover_text(docs, src.value.short_label(), mod_path) 334 hover_markup(docs, src.value.short_label(), mod_path)
323 } 335 }
324} 336}
325 337
diff --git a/crates/ra_ide/src/markup.rs b/crates/ra_ide/src/markup.rs
index 212ca80b7..60c193c40 100644
--- a/crates/ra_ide/src/markup.rs
+++ b/crates/ra_ide/src/markup.rs
@@ -32,4 +32,7 @@ impl Markup {
32 pub fn as_str(&self) -> &str { 32 pub fn as_str(&self) -> &str {
33 self.text.as_str() 33 self.text.as_str()
34 } 34 }
35 pub fn fenced_block(contents: &impl fmt::Display) -> Markup {
36 format!("```rust\n{}\n```", contents).into()
37 }
35} 38}