about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Loucks <aloucks@cofront.net>2020-05-31 11:33:48 -0400
committerAaron Loucks <aloucks@cofront.net>2020-06-03 06:46:07 -0400
commit5837acce532e0cd65a1c0cb8c03cc18a4c22f327 (patch)
treefa162f2dc57a53be9a6090fb3776cc9586332551
parent4c655c01f31ceffae4f8219f9706992e0e7f188a (diff)
downloadrust-5837acce532e0cd65a1c0cb8c03cc18a4c22f327.tar.gz
rust-5837acce532e0cd65a1c0cb8c03cc18a4c22f327.zip
Add basic hover and completion doc tests for macro generated items
-rw-r--r--crates/ra_hir_def/src/docs.rs2
-rw-r--r--crates/ra_ide/src/completion.rs78
-rw-r--r--crates/ra_ide/src/hover.rs104
3 files changed, 182 insertions, 2 deletions
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 74b9f8199c1..ab43cd3d339 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -109,6 +109,6 @@ fn expand_doc_attrs(owner: &dyn ast::AttrsOwner) -> Option<String> {
     if docs.is_empty() {
         None
     } else {
-        Some(docs)
+        Some(docs.trim_end_matches("\n\n").to_owned())
     }
 }
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index d890b69d26f..a721e23c693 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -125,3 +125,81 @@ pub(crate) fn completions(
 
     Some(acc)
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::completion::completion_config::CompletionConfig;
+    use crate::mock_analysis::analysis_and_position;
+
+    struct DetailAndDocumentation<'a> {
+        detail: &'a str,
+        documentation: &'a str,
+    }
+
+    fn check_detail_and_documentation(fixture: &str, expected: DetailAndDocumentation) {
+        let (analysis, position) = analysis_and_position(fixture);
+        let config = CompletionConfig::default();
+        let completions = analysis.completions(&config, position).unwrap().unwrap();
+        for item in completions {
+            if item.detail() == Some(expected.detail) {
+                let opt = item.documentation();
+                let doc = opt.as_ref().map(|it| it.as_str());
+                assert_eq!(doc, Some(expected.documentation));
+                return;
+            }
+        }
+        panic!("completion detail not found: {}", expected.detail)
+    }
+
+    #[test]
+    fn test_completion_detail_from_macro_generated_struct_fn_doc_attr() {
+        check_detail_and_documentation(
+            r#"
+            //- /lib.rs
+            macro_rules! bar {
+                () => {
+                    struct Bar;
+                    impl Bar {
+                        #[doc = "Do the foo"]
+                        fn foo(&self) {}
+                    }
+                }
+            }
+
+            bar!();
+
+            fn foo() {
+                let bar = Bar;
+                bar.fo<|>;
+            }
+            "#,
+            DetailAndDocumentation { detail: "fn foo(&self)", documentation: "Do the foo" },
+        );
+    }
+
+    #[test]
+    fn test_completion_detail_from_macro_generated_struct_fn_doc_comment() {
+        check_detail_and_documentation(
+            r#"
+            //- /lib.rs
+            macro_rules! bar {
+                () => {
+                    struct Bar;
+                    impl Bar {
+                        /// Do the foo
+                        fn foo(&self) {}
+                    }
+                }
+            }
+
+            bar!();
+
+            fn foo() {
+                let bar = Bar;
+                bar.fo<|>;
+            }
+            "#,
+            DetailAndDocumentation { detail: "fn foo(&self)", documentation: " Do the foo" },
+        );
+    }
+}
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index e25a7dacf01..731fc367353 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -256,7 +256,7 @@ fn expand_doc_attrs(owner: &dyn ast::AttrsOwner) -> Option<String> {
     if docs.is_empty() {
         None
     } else {
-        Some(docs)
+        Some(docs.trim_end_matches("\n\n").to_owned())
     }
 }
 
@@ -996,4 +996,106 @@ fn func(foo: i32) { if true { <|>foo; }; }
             &["mod my"],
         );
     }
+
+    #[test]
+    fn test_hover_struct_doc_comment() {
+        check_hover_result(
+            r#"
+            //- /lib.rs
+            /// bar docs
+            struct Bar;
+
+            fn foo() {
+                let bar = Ba<|>r;
+            }
+            "#,
+            &["struct Bar\n```\n___\n\nbar docs"],
+        );
+    }
+
+    #[test]
+    fn test_hover_struct_doc_attr() {
+        check_hover_result(
+            r#"
+            //- /lib.rs
+            #[doc = "bar docs"]
+            struct Bar;
+
+            fn foo() {
+                let bar = Ba<|>r;
+            }
+            "#,
+            &["struct Bar\n```\n___\n\nbar docs"],
+        );
+    }
+
+    #[test]
+    fn test_hover_struct_doc_attr_multiple_and_mixed() {
+        check_hover_result(
+            r#"
+            //- /lib.rs
+            /// bar docs 0
+            #[doc = "bar docs 1"]
+            #[doc = "bar docs 2"]
+            struct Bar;
+
+            fn foo() {
+                let bar = Ba<|>r;
+            }
+            "#,
+            &["struct Bar\n```\n___\n\nbar docs 0\n\nbar docs 1\n\nbar docs 2"],
+        );
+    }
+
+    #[test]
+    fn test_hover_macro_generated_struct_fn_doc_comment() {
+        check_hover_result(
+            r#"
+            //- /lib.rs
+            macro_rules! bar {
+                () => {
+                    struct Bar;
+                    impl Bar {
+                        /// Do the foo
+                        fn foo(&self) {}
+                    }
+                }
+            }
+
+            bar!();
+
+            fn foo() {
+                let bar = Bar;
+                bar.fo<|>o();
+            }
+            "#,
+            &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\n Do the foo"],
+        );
+    }
+
+    #[test]
+    fn test_hover_macro_generated_struct_fn_doc_attr() {
+        check_hover_result(
+            r#"
+            //- /lib.rs
+            macro_rules! bar {
+                () => {
+                    struct Bar;
+                    impl Bar {
+                        #[doc = "Do the foo"]
+                        fn foo(&self) {}
+                    }
+                }
+            }
+
+            bar!();
+
+            fn foo() {
+                let bar = Bar;
+                bar.fo<|>o();
+            }
+            "#,
+            &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo"],
+        );
+    }
 }