aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-01-24 01:22:29 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-01-24 01:22:29 +0000
commit6a0a4a564accb12b48e703245655e3e3a0637445 (patch)
tree248097d8ceaded63601e3d663ef795e3bae55bfe
parentbf9cd6ee30b3044b61e99e24e82fad56d3965417 (diff)
parentf87ce73579759fdb623f1d8d82880c0d6306746e (diff)
Merge #621
621: Completion docs for code model r=kjeremy a=kjeremy Adds a way to access documentation through the code model and exposes it to completions. Also allows us to document enum variants. Co-authored-by: Jeremy A. Kolb <[email protected]> Co-authored-by: Jeremy Kolb <[email protected]>
-rw-r--r--crates/ra_hir/src/code_model_api.rs61
-rw-r--r--crates/ra_hir/src/docs.rs36
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs13
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs43
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap20
-rw-r--r--crates/ra_syntax/src/ast/generated.rs1
-rw-r--r--crates/ra_syntax/src/grammar.ron2
-rw-r--r--crates/ra_syntax/src/parser_impl/event.rs3
9 files changed, 138 insertions, 43 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 9ae620efd..3ff07bd60 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use ra_db::{CrateId, FileId}; 4use ra_db::{CrateId, FileId};
5use ra_syntax::{ast::{self, AstNode, DocCommentsOwner}, TreeArc, SyntaxNode}; 5use ra_syntax::{ast::self, TreeArc, SyntaxNode};
6 6
7use crate::{ 7use crate::{
8 Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, 8 Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId,
@@ -14,6 +14,7 @@ use crate::{
14 adt::VariantData, 14 adt::VariantData,
15 generics::GenericParams, 15 generics::GenericParams,
16 code_model_impl::def_id_to_ast, 16 code_model_impl::def_id_to_ast,
17 docs::{Documentation, Docs, docs_from_ast}
17}; 18};
18 19
19/// hir::Crate describes a single crate. It's the main interface with which 20/// hir::Crate describes a single crate. It's the main interface with which
@@ -208,6 +209,12 @@ impl Struct {
208 } 209 }
209} 210}
210 211
212impl Docs for Struct {
213 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
214 docs_from_ast(&*self.source(db).1)
215 }
216}
217
211#[derive(Debug, Clone, PartialEq, Eq, Hash)] 218#[derive(Debug, Clone, PartialEq, Eq, Hash)]
212pub struct Enum { 219pub struct Enum {
213 pub(crate) def_id: DefId, 220 pub(crate) def_id: DefId,
@@ -239,6 +246,12 @@ impl Enum {
239 } 246 }
240} 247}
241 248
249impl Docs for Enum {
250 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
251 docs_from_ast(&*self.source(db).1)
252 }
253}
254
242#[derive(Debug, Clone, PartialEq, Eq, Hash)] 255#[derive(Debug, Clone, PartialEq, Eq, Hash)]
243pub struct EnumVariant { 256pub struct EnumVariant {
244 pub(crate) def_id: DefId, 257 pub(crate) def_id: DefId,
@@ -281,6 +294,12 @@ impl EnumVariant {
281 } 294 }
282} 295}
283 296
297impl Docs for EnumVariant {
298 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
299 docs_from_ast(&*self.source(db).1)
300 }
301}
302
284#[derive(Debug, Clone, PartialEq, Eq, Hash)] 303#[derive(Debug, Clone, PartialEq, Eq, Hash)]
285pub struct Function { 304pub struct Function {
286 pub(crate) def_id: DefId, 305 pub(crate) def_id: DefId,
@@ -352,19 +371,11 @@ impl Function {
352 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { 371 pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
353 db.generic_params(self.def_id) 372 db.generic_params(self.def_id)
354 } 373 }
374}
355 375
356 pub fn docs(&self, db: &impl HirDatabase) -> Option<String> { 376impl Docs for Function {
357 let def_loc = self.def_id.loc(db); 377 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
358 let syntax = db.file_item(def_loc.source_item_id); 378 docs_from_ast(&*self.source(db).1)
359 let fn_def = ast::FnDef::cast(&syntax).expect("fn def should point to FnDef node");
360
361 // doc_comment_text unconditionally returns a String
362 let comments = fn_def.doc_comment_text();
363 if comments.is_empty() {
364 None
365 } else {
366 Some(comments)
367 }
368 } 379 }
369} 380}
370 381
@@ -383,6 +394,12 @@ impl Const {
383 } 394 }
384} 395}
385 396
397impl Docs for Const {
398 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
399 docs_from_ast(&*self.source(db).1)
400 }
401}
402
386#[derive(Debug, Clone, PartialEq, Eq, Hash)] 403#[derive(Debug, Clone, PartialEq, Eq, Hash)]
387pub struct Static { 404pub struct Static {
388 pub(crate) def_id: DefId, 405 pub(crate) def_id: DefId,
@@ -398,6 +415,12 @@ impl Static {
398 } 415 }
399} 416}
400 417
418impl Docs for Static {
419 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
420 docs_from_ast(&*self.source(db).1)
421 }
422}
423
401#[derive(Debug, Clone, PartialEq, Eq, Hash)] 424#[derive(Debug, Clone, PartialEq, Eq, Hash)]
402pub struct Trait { 425pub struct Trait {
403 pub(crate) def_id: DefId, 426 pub(crate) def_id: DefId,
@@ -417,6 +440,12 @@ impl Trait {
417 } 440 }
418} 441}
419 442
443impl Docs for Trait {
444 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
445 docs_from_ast(&*self.source(db).1)
446 }
447}
448
420#[derive(Debug, Clone, PartialEq, Eq, Hash)] 449#[derive(Debug, Clone, PartialEq, Eq, Hash)]
421pub struct Type { 450pub struct Type {
422 pub(crate) def_id: DefId, 451 pub(crate) def_id: DefId,
@@ -435,3 +464,9 @@ impl Type {
435 db.generic_params(self.def_id) 464 db.generic_params(self.def_id)
436 } 465 }
437} 466}
467
468impl Docs for Type {
469 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
470 docs_from_ast(&*self.source(db).1)
471 }
472}
diff --git a/crates/ra_hir/src/docs.rs b/crates/ra_hir/src/docs.rs
new file mode 100644
index 000000000..b1b47af9e
--- /dev/null
+++ b/crates/ra_hir/src/docs.rs
@@ -0,0 +1,36 @@
1use ra_syntax::ast;
2
3use crate::HirDatabase;
4
5/// Holds documentation
6#[derive(Debug, Clone)]
7pub struct Documentation(String);
8
9impl Documentation {
10 pub fn new(s: &str) -> Self {
11 Self(s.into())
12 }
13
14 pub fn contents(&self) -> &str {
15 &self.0
16 }
17}
18
19impl Into<String> for Documentation {
20 fn into(self) -> String {
21 self.contents().into()
22 }
23}
24
25pub trait Docs {
26 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
27}
28
29pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
30 let comments = node.doc_comment_text();
31 if comments.is_empty() {
32 None
33 } else {
34 Some(Documentation::new(&comments))
35 }
36}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a861ee88e..f517f71e0 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -23,6 +23,7 @@ mod ty;
23mod impl_block; 23mod impl_block;
24mod expr; 24mod expr;
25mod generics; 25mod generics;
26mod docs;
26 27
27mod code_model_api; 28mod code_model_api;
28mod code_model_impl; 29mod code_model_impl;
@@ -45,6 +46,7 @@ pub use self::{
45 ty::Ty, 46 ty::Ty,
46 impl_block::{ImplBlock, ImplItem}, 47 impl_block::{ImplBlock, ImplItem},
47 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, 48 code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
49 docs::{Docs, Documentation}
48}; 50};
49 51
50pub use self::code_model_api::{ 52pub use self::code_model_api::{
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 6bed299d2..e44b76c4a 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -2,6 +2,8 @@ use crate::{
2 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, 2 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
3}; 3};
4 4
5use hir::Docs;
6
5pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { 7pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
6 let (path, module) = match (&ctx.path_prefix, &ctx.module) { 8 let (path, module) = match (&ctx.path_prefix, &ctx.module) {
7 (Some(path), Some(module)) => (path.clone(), module), 9 (Some(path), Some(module)) => (path.clone(), module),
@@ -27,13 +29,14 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
27 hir::Def::Enum(e) => { 29 hir::Def::Enum(e) => {
28 e.variants(ctx.db) 30 e.variants(ctx.db)
29 .into_iter() 31 .into_iter()
30 .for_each(|(variant_name, _variant)| { 32 .for_each(|(variant_name, variant)| {
31 CompletionItem::new( 33 CompletionItem::new(
32 CompletionKind::Reference, 34 CompletionKind::Reference,
33 ctx.source_range(), 35 ctx.source_range(),
34 variant_name.to_string(), 36 variant_name.to_string(),
35 ) 37 )
36 .kind(CompletionItemKind::EnumVariant) 38 .kind(CompletionItemKind::EnumVariant)
39 .set_documentation(variant.docs(ctx.db))
37 .add_to(acc) 40 .add_to(acc)
38 }); 41 });
39 } 42 }
@@ -116,7 +119,13 @@ mod tests {
116 "reference_completion", 119 "reference_completion",
117 " 120 "
118 //- /lib.rs 121 //- /lib.rs
119 enum E { Foo, Bar(i32) } 122 /// An enum
123 enum E {
124 /// Foo Variant
125 Foo,
126 /// Bar Variant with i32
127 Bar(i32)
128 }
120 fn foo() { let _ = E::<|> } 129 fn foo() { let _ = E::<|> }
121 ", 130 ",
122 ); 131 );
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index e3bf82304..18c151932 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -1,4 +1,4 @@
1use hir::PerNs; 1use hir::{Docs, Documentation, PerNs};
2 2
3use crate::completion::completion_context::CompletionContext; 3use crate::completion::completion_context::CompletionContext;
4use ra_syntax::{ 4use ra_syntax::{
@@ -19,7 +19,7 @@ pub struct CompletionItem {
19 label: String, 19 label: String,
20 kind: Option<CompletionItemKind>, 20 kind: Option<CompletionItemKind>,
21 detail: Option<String>, 21 detail: Option<String>,
22 documentation: Option<String>, 22 documentation: Option<Documentation>,
23 lookup: Option<String>, 23 lookup: Option<String>,
24 insert_text: Option<String>, 24 insert_text: Option<String>,
25 insert_text_format: InsertTextFormat, 25 insert_text_format: InsertTextFormat,
@@ -98,7 +98,7 @@ impl CompletionItem {
98 } 98 }
99 /// A doc-comment 99 /// A doc-comment
100 pub fn documentation(&self) -> Option<&str> { 100 pub fn documentation(&self) -> Option<&str> {
101 self.documentation.as_ref().map(|it| it.as_str()) 101 self.documentation.as_ref().map(|it| it.contents())
102 } 102 }
103 /// What string is used for filtering. 103 /// What string is used for filtering.
104 pub fn lookup(&self) -> &str { 104 pub fn lookup(&self) -> &str {
@@ -137,7 +137,7 @@ pub(crate) struct Builder {
137 insert_text: Option<String>, 137 insert_text: Option<String>,
138 insert_text_format: InsertTextFormat, 138 insert_text_format: InsertTextFormat,
139 detail: Option<String>, 139 detail: Option<String>,
140 documentation: Option<String>, 140 documentation: Option<Documentation>,
141 lookup: Option<String>, 141 lookup: Option<String>,
142 kind: Option<CompletionItemKind>, 142 kind: Option<CompletionItemKind>,
143 text_edit: Option<TextEdit>, 143 text_edit: Option<TextEdit>,
@@ -197,10 +197,10 @@ impl Builder {
197 self 197 self
198 } 198 }
199 #[allow(unused)] 199 #[allow(unused)]
200 pub(crate) fn documentation(self, docs: impl Into<String>) -> Builder { 200 pub(crate) fn documentation(self, docs: Documentation) -> Builder {
201 self.set_documentation(Some(docs)) 201 self.set_documentation(Some(docs))
202 } 202 }
203 pub(crate) fn set_documentation(mut self, docs: Option<impl Into<String>>) -> Builder { 203 pub(crate) fn set_documentation(mut self, docs: Option<Documentation>) -> Builder {
204 self.documentation = docs.map(Into::into); 204 self.documentation = docs.map(Into::into);
205 self 205 self
206 } 206 }
@@ -210,35 +210,35 @@ impl Builder {
210 resolution: &hir::Resolution, 210 resolution: &hir::Resolution,
211 ) -> Builder { 211 ) -> Builder {
212 let resolved = resolution.def_id.map(|d| d.resolve(ctx.db)); 212 let resolved = resolution.def_id.map(|d| d.resolve(ctx.db));
213 let kind = match resolved { 213 let (kind, docs) = match resolved {
214 PerNs { 214 PerNs {
215 types: Some(hir::Def::Module(..)), 215 types: Some(hir::Def::Module(..)),
216 .. 216 ..
217 } => CompletionItemKind::Module, 217 } => (CompletionItemKind::Module, None),
218 PerNs { 218 PerNs {
219 types: Some(hir::Def::Struct(..)), 219 types: Some(hir::Def::Struct(s)),
220 .. 220 ..
221 } => CompletionItemKind::Struct, 221 } => (CompletionItemKind::Struct, s.docs(ctx.db)),
222 PerNs { 222 PerNs {
223 types: Some(hir::Def::Enum(..)), 223 types: Some(hir::Def::Enum(e)),
224 .. 224 ..
225 } => CompletionItemKind::Enum, 225 } => (CompletionItemKind::Enum, e.docs(ctx.db)),
226 PerNs { 226 PerNs {
227 types: Some(hir::Def::Trait(..)), 227 types: Some(hir::Def::Trait(t)),
228 .. 228 ..
229 } => CompletionItemKind::Trait, 229 } => (CompletionItemKind::Trait, t.docs(ctx.db)),
230 PerNs { 230 PerNs {
231 types: Some(hir::Def::Type(..)), 231 types: Some(hir::Def::Type(t)),
232 .. 232 ..
233 } => CompletionItemKind::TypeAlias, 233 } => (CompletionItemKind::TypeAlias, t.docs(ctx.db)),
234 PerNs { 234 PerNs {
235 values: Some(hir::Def::Const(..)), 235 values: Some(hir::Def::Const(c)),
236 .. 236 ..
237 } => CompletionItemKind::Const, 237 } => (CompletionItemKind::Const, c.docs(ctx.db)),
238 PerNs { 238 PerNs {
239 values: Some(hir::Def::Static(..)), 239 values: Some(hir::Def::Static(s)),
240 .. 240 ..
241 } => CompletionItemKind::Static, 241 } => (CompletionItemKind::Static, s.docs(ctx.db)),
242 PerNs { 242 PerNs {
243 values: Some(hir::Def::Function(function)), 243 values: Some(hir::Def::Function(function)),
244 .. 244 ..
@@ -246,6 +246,8 @@ impl Builder {
246 _ => return self, 246 _ => return self,
247 }; 247 };
248 self.kind = Some(kind); 248 self.kind = Some(kind);
249 self.documentation = docs;
250
249 self 251 self
250 } 252 }
251 253
@@ -265,6 +267,7 @@ impl Builder {
265 } 267 }
266 self.insert_text_format = InsertTextFormat::Snippet; 268 self.insert_text_format = InsertTextFormat::Snippet;
267 } 269 }
270
268 if let Some(docs) = function.docs(ctx.db) { 271 if let Some(docs) = function.docs(ctx.db) {
269 self.documentation = Some(docs); 272 self.documentation = Some(docs);
270 } 273 }
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap
index 0180a4f44..e46f7807b 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__reference_completion.snap
@@ -1,6 +1,6 @@
1--- 1---
2created: "2019-01-22T14:45:00.717917+00:00" 2created: "2019-01-23T23:49:43.278245900+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.1
4expression: kind_completions 4expression: kind_completions
5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs" 5source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
6--- 6---
@@ -12,11 +12,15 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
12 EnumVariant 12 EnumVariant
13 ), 13 ),
14 detail: None, 14 detail: None,
15 documentation: None, 15 documentation: Some(
16 Documentation(
17 "Foo Variant"
18 )
19 ),
16 lookup: None, 20 lookup: None,
17 insert_text: None, 21 insert_text: None,
18 insert_text_format: PlainText, 22 insert_text_format: PlainText,
19 source_range: [47; 47), 23 source_range: [116; 116),
20 text_edit: None 24 text_edit: None
21 }, 25 },
22 CompletionItem { 26 CompletionItem {
@@ -26,11 +30,15 @@ source: "crates\\ra_ide_api\\src\\completion\\completion_item.rs"
26 EnumVariant 30 EnumVariant
27 ), 31 ),
28 detail: None, 32 detail: None,
29 documentation: None, 33 documentation: Some(
34 Documentation(
35 "Bar Variant with i32"
36 )
37 ),
30 lookup: None, 38 lookup: None,
31 insert_text: None, 39 insert_text: None,
32 insert_text_format: PlainText, 40 insert_text_format: PlainText,
33 source_range: [47; 47), 41 source_range: [116; 116),
34 text_edit: None 42 text_edit: None
35 } 43 }
36] 44]
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 9fe946172..ac6c8a835 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -632,6 +632,7 @@ impl AstNode for EnumVariant {
632 632
633 633
634impl ast::NameOwner for EnumVariant {} 634impl ast::NameOwner for EnumVariant {}
635impl ast::DocCommentsOwner for EnumVariant {}
635impl EnumVariant { 636impl EnumVariant {
636 pub fn expr(&self) -> Option<&Expr> { 637 pub fn expr(&self) -> Option<&Expr> {
637 super::child_opt(self) 638 super::child_opt(self)
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 0385183fd..c5297e46d 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -279,7 +279,7 @@ Grammar(
279 "DocCommentsOwner" 279 "DocCommentsOwner"
280 ], options: [["variant_list", "EnumVariantList"]] ), 280 ], options: [["variant_list", "EnumVariantList"]] ),
281 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ), 281 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ),
282 "EnumVariant": ( traits: ["NameOwner"], options: ["Expr"] ), 282 "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner"], options: ["Expr"] ),
283 "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner"] ), 283 "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner"] ),
284 "Module": ( 284 "Module": (
285 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ], 285 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ],
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs
index 73dd6e02b..bd77fee89 100644
--- a/crates/ra_syntax/src/parser_impl/event.rs
+++ b/crates/ra_syntax/src/parser_impl/event.rs
@@ -249,7 +249,8 @@ fn n_attached_trivias<'a>(
249 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>, 249 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
250) -> usize { 250) -> usize {
251 match kind { 251 match kind {
252 CONST_DEF | TYPE_DEF | STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => { 252 CONST_DEF | TYPE_DEF | STRUCT_DEF | ENUM_DEF | ENUM_VARIANT | FN_DEF | TRAIT_DEF
253 | MODULE => {
253 let mut res = 0; 254 let mut res = 0;
254 for (i, (kind, text)) in trivias.enumerate() { 255 for (i, (kind, text)) in trivias.enumerate() {
255 match kind { 256 match kind {