]> git.lizzy.rs Git - rust.git/commitdiff
Add way of getting docs from the code model and use for completion
authorJeremy A. Kolb <jkolb@ara.com>
Wed, 23 Jan 2019 21:22:10 +0000 (16:22 -0500)
committerJeremy A. Kolb <jkolb@ara.com>
Wed, 23 Jan 2019 21:32:04 +0000 (16:32 -0500)
crates/ra_hir/src/code_model_api.rs
crates/ra_hir/src/docs.rs [new file with mode: 0644]
crates/ra_hir/src/lib.rs
crates/ra_ide_api/src/completion/complete_path.rs
crates/ra_ide_api/src/completion/completion_item.rs

index 9ae620efd4c0647cb40ec277b07d34d0cb4de181..333d117f13da74680ad4f7eef4f2fed030cb0656 100644 (file)
@@ -2,7 +2,7 @@
 
 use relative_path::RelativePathBuf;
 use ra_db::{CrateId, FileId};
-use ra_syntax::{ast::{self, AstNode, DocCommentsOwner}, TreeArc, SyntaxNode};
+use ra_syntax::{ast::self, TreeArc, SyntaxNode};
 
 use crate::{
     Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId,
@@ -14,6 +14,7 @@
     adt::VariantData,
     generics::GenericParams,
     code_model_impl::def_id_to_ast,
+    docs::{Documentation, Docs, docs_from_ast}
 };
 
 /// hir::Crate describes a single crate. It's the main interface with which
@@ -208,6 +209,12 @@ pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
     }
 }
 
+impl Docs for Struct {
+    fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
+        docs_from_ast(&*self.source(db).1)
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Enum {
     pub(crate) def_id: DefId,
@@ -239,6 +246,12 @@ pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
     }
 }
 
+impl Docs for Enum {
+    fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
+        docs_from_ast(&*self.source(db).1)
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct EnumVariant {
     pub(crate) def_id: DefId,
@@ -281,6 +294,12 @@ pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVari
     }
 }
 
+impl Docs for EnumVariant {
+    fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
+        docs_from_ast(&*self.source(db).1)
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Function {
     pub(crate) def_id: DefId,
@@ -352,19 +371,11 @@ pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
     pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
         db.generic_params(self.def_id)
     }
+}
 
-    pub fn docs(&self, db: &impl HirDatabase) -> Option<String> {
-        let def_loc = self.def_id.loc(db);
-        let syntax = db.file_item(def_loc.source_item_id);
-        let fn_def = ast::FnDef::cast(&syntax).expect("fn def should point to FnDef node");
-
-        // doc_comment_text unconditionally returns a String
-        let comments = fn_def.doc_comment_text();
-        if comments.is_empty() {
-            None
-        } else {
-            Some(comments)
-        }
+impl Docs for Function {
+    fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
+        docs_from_ast(&*self.source(db).1)
     }
 }
 
diff --git a/crates/ra_hir/src/docs.rs b/crates/ra_hir/src/docs.rs
new file mode 100644 (file)
index 0000000..330d8f8
--- /dev/null
@@ -0,0 +1,35 @@
+use ra_syntax::ast;
+
+use crate::HirDatabase;
+
+#[derive(Debug, Clone)]
+pub struct Documentation(String);
+
+impl Documentation {
+    pub fn new(s: &str) -> Self {
+        Self(s.into())
+    }
+
+    pub fn contents(&self) -> &str {
+        &self.0
+    }
+}
+
+impl Into<String> for Documentation {
+    fn into(self) -> String {
+        self.contents().into()
+    }
+}
+
+pub trait Docs {
+    fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
+}
+
+pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
+    let comments = node.doc_comment_text();
+    if comments.is_empty() {
+        None
+    } else {
+        Some(Documentation::new(&comments))
+    }
+}
index a861ee88e6d272ee2babf7b1656dcc0915eeba27..f517f71e0c3938c61667d04e2becb20884c34be7 100644 (file)
@@ -23,6 +23,7 @@
 mod impl_block;
 mod expr;
 mod generics;
+mod docs;
 
 mod code_model_api;
 mod code_model_impl;
@@ -45,6 +46,7 @@
     ty::Ty,
     impl_block::{ImplBlock, ImplItem},
     code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
+    docs::{Docs, Documentation}
 };
 
 pub use self::code_model_api::{
index 6bed299d2f4012ab26b010e5610e4b5eff8934ac..aeb226847fb5b9ed559c55eb4a70dd6c11cf50c4 100644 (file)
@@ -2,6 +2,8 @@
     completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
 };
 
+use hir::Docs;
+
 pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
     let (path, module) = match (&ctx.path_prefix, &ctx.module) {
         (Some(path), Some(module)) => (path.clone(), module),
@@ -27,13 +29,14 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
         hir::Def::Enum(e) => {
             e.variants(ctx.db)
                 .into_iter()
-                .for_each(|(variant_name, _variant)| {
+                .for_each(|(variant_name, variant)| {
                     CompletionItem::new(
                         CompletionKind::Reference,
                         ctx.source_range(),
                         variant_name.to_string(),
                     )
                     .kind(CompletionItemKind::EnumVariant)
+                    .set_documentation(variant.docs(ctx.db))
                     .add_to(acc)
                 });
         }
index e3bf82304e0174039eaa38a919c6e4132f973cc1..8e0be4c4b0079659da0df77cca16be91b8fee0e2 100644 (file)
@@ -1,4 +1,4 @@
-use hir::PerNs;
+use hir::{Docs, Documentation, PerNs};
 
 use crate::completion::completion_context::CompletionContext;
 use ra_syntax::{
@@ -19,7 +19,7 @@ pub struct CompletionItem {
     label: String,
     kind: Option<CompletionItemKind>,
     detail: Option<String>,
-    documentation: Option<String>,
+    documentation: Option<Documentation>,
     lookup: Option<String>,
     insert_text: Option<String>,
     insert_text_format: InsertTextFormat,
@@ -98,7 +98,7 @@ pub fn detail(&self) -> Option<&str> {
     }
     /// A doc-comment
     pub fn documentation(&self) -> Option<&str> {
-        self.documentation.as_ref().map(|it| it.as_str())
+        self.documentation.as_ref().map(|it| it.contents())
     }
     /// What string is used for filtering.
     pub fn lookup(&self) -> &str {
@@ -137,7 +137,7 @@ pub(crate) struct Builder {
     insert_text: Option<String>,
     insert_text_format: InsertTextFormat,
     detail: Option<String>,
-    documentation: Option<String>,
+    documentation: Option<Documentation>,
     lookup: Option<String>,
     kind: Option<CompletionItemKind>,
     text_edit: Option<TextEdit>,
@@ -197,10 +197,10 @@ pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder
         self
     }
     #[allow(unused)]
-    pub(crate) fn documentation(self, docs: impl Into<String>) -> Builder {
+    pub(crate) fn documentation(self, docs: Documentation) -> Builder {
         self.set_documentation(Some(docs))
     }
-    pub(crate) fn set_documentation(mut self, docs: Option<impl Into<String>>) -> Builder {
+    pub(crate) fn set_documentation(mut self, docs: Option<Documentation>) -> Builder {
         self.documentation = docs.map(Into::into);
         self
     }
@@ -265,6 +265,7 @@ pub(super) fn from_function(
             }
             self.insert_text_format = InsertTextFormat::Snippet;
         }
+
         if let Some(docs) = function.docs(ctx.db) {
             self.documentation = Some(docs);
         }