aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/docs.rs7
-rw-r--r--crates/ra_ide/src/hover.rs60
2 files changed, 14 insertions, 53 deletions
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index ab43cd3d3..2630b3d89 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -29,6 +29,13 @@ impl Documentation {
29 Documentation(s.into()) 29 Documentation(s.into())
30 } 30 }
31 31
32 pub fn from_ast<N>(node: &N) -> Option<Documentation>
33 where
34 N: ast::DocCommentsOwner + ast::AttrsOwner,
35 {
36 docs_from_ast(node)
37 }
38
32 pub fn as_str(&self) -> &str { 39 pub fn as_str(&self) -> &str {
33 &*self.0 40 &*self.0
34 } 41 }
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 731fc3673..9636cd0d6 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -1,8 +1,8 @@
1use std::iter::once; 1use std::iter::once;
2 2
3use hir::{ 3use hir::{
4 Adt, AsAssocItem, AssocItemContainer, FieldSource, HasSource, HirDisplay, ModuleDef, 4 Adt, AsAssocItem, AssocItemContainer, Documentation, FieldSource, HasSource, HirDisplay,
5 ModuleSource, Semantics, 5 ModuleDef, ModuleSource, Semantics,
6}; 6};
7use itertools::Itertools; 7use itertools::Itertools;
8use ra_db::SourceDatabase; 8use ra_db::SourceDatabase;
@@ -10,12 +10,7 @@ use ra_ide_db::{
10 defs::{classify_name, classify_name_ref, Definition}, 10 defs::{classify_name, classify_name_ref, Definition},
11 RootDatabase, 11 RootDatabase,
12}; 12};
13use ra_syntax::{ 13use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset};
14 ast::{self, DocCommentsOwner},
15 match_ast, AstNode,
16 SyntaxKind::*,
17 SyntaxToken, TokenAtOffset,
18};
19 14
20use crate::{ 15use crate::{
21 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, 16 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel},
@@ -169,18 +164,14 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
169 return match def { 164 return match def {
170 Definition::Macro(it) => { 165 Definition::Macro(it) => {
171 let src = it.source(db); 166 let src = it.source(db);
172 let doc_comment_text = src.value.doc_comment_text(); 167 let docs = Documentation::from_ast(&src.value).map(Into::into);
173 let doc_attr_text = expand_doc_attrs(&src.value);
174 let docs = merge_doc_comments_and_attrs(doc_comment_text, doc_attr_text);
175 hover_text(docs, Some(macro_label(&src.value)), mod_path) 168 hover_text(docs, Some(macro_label(&src.value)), mod_path)
176 } 169 }
177 Definition::Field(it) => { 170 Definition::Field(it) => {
178 let src = it.source(db); 171 let src = it.source(db);
179 match src.value { 172 match src.value {
180 FieldSource::Named(it) => { 173 FieldSource::Named(it) => {
181 let doc_comment_text = it.doc_comment_text(); 174 let docs = Documentation::from_ast(&it).map(Into::into);
182 let doc_attr_text = expand_doc_attrs(&it);
183 let docs = merge_doc_comments_and_attrs(doc_comment_text, doc_attr_text);
184 hover_text(docs, it.short_label(), mod_path) 175 hover_text(docs, it.short_label(), mod_path)
185 } 176 }
186 _ => None, 177 _ => None,
@@ -189,9 +180,7 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
189 Definition::ModuleDef(it) => match it { 180 Definition::ModuleDef(it) => match it {
190 ModuleDef::Module(it) => match it.definition_source(db).value { 181 ModuleDef::Module(it) => match it.definition_source(db).value {
191 ModuleSource::Module(it) => { 182 ModuleSource::Module(it) => {
192 let doc_comment_text = it.doc_comment_text(); 183 let docs = Documentation::from_ast(&it).map(Into::into);
193 let doc_attr_text = expand_doc_attrs(&it);
194 let docs = merge_doc_comments_and_attrs(doc_comment_text, doc_attr_text);
195 hover_text(docs, it.short_label(), mod_path) 184 hover_text(docs, it.short_label(), mod_path)
196 } 185 }
197 _ => None, 186 _ => None,
@@ -220,46 +209,11 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
220 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner, 209 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner,
221 { 210 {
222 let src = def.source(db); 211 let src = def.source(db);
223 let doc_comment_text = src.value.doc_comment_text(); 212 let docs = Documentation::from_ast(&src.value).map(Into::into);
224 let doc_attr_text = expand_doc_attrs(&src.value);
225 let docs = merge_doc_comments_and_attrs(doc_comment_text, doc_attr_text);
226 hover_text(docs, src.value.short_label(), mod_path) 213 hover_text(docs, src.value.short_label(), mod_path)
227 } 214 }
228} 215}
229 216
230fn merge_doc_comments_and_attrs(
231 doc_comment_text: Option<String>,
232 doc_attr_text: Option<String>,
233) -> Option<String> {
234 match (doc_comment_text, doc_attr_text) {
235 (Some(mut comment_text), Some(attr_text)) => {
236 comment_text.push_str("\n\n");
237 comment_text.push_str(&attr_text);
238 Some(comment_text)
239 }
240 (Some(comment_text), None) => Some(comment_text),
241 (None, Some(attr_text)) => Some(attr_text),
242 (None, None) => None,
243 }
244}
245
246fn expand_doc_attrs(owner: &dyn ast::AttrsOwner) -> Option<String> {
247 let mut docs = String::new();
248 for attr in owner.attrs() {
249 if let Some(("doc", value)) =
250 attr.as_simple_key_value().as_ref().map(|(k, v)| (k.as_str(), v.as_str()))
251 {
252 docs.push_str(value);
253 docs.push_str("\n\n");
254 }
255 }
256 if docs.is_empty() {
257 None
258 } else {
259 Some(docs.trim_end_matches("\n\n").to_owned())
260 }
261}
262
263fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { 217fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
264 return tokens.max_by_key(priority); 218 return tokens.max_by_key(priority);
265 fn priority(n: &SyntaxToken) -> usize { 219 fn priority(n: &SyntaxToken) -> usize {