aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-01-27 08:21:04 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-01-27 08:21:04 +0000
commitffcf61884245ca515f08f8685dc324b9db727e53 (patch)
tree99fe4420fe14a036323efe553e609268929df599 /crates/ra_syntax/src
parent2577a65684a61fe8ef9159809ca5352c9ac2e61d (diff)
parenta89206795140209b816eb8e91fa3f1e1d6509269 (diff)
Merge #662
662: Preserve indentation in doc comments r=matklad a=kjeremy Fixes #502 Co-authored-by: Jeremy Kolb <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/ast.rs75
1 files changed, 62 insertions, 13 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index ab3dd1b84..3d22a88f3 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -115,21 +115,38 @@ pub trait DocCommentsOwner: AstNode {
115 } 115 }
116 116
117 /// Returns the textual content of a doc comment block as a single string. 117 /// Returns the textual content of a doc comment block as a single string.
118 /// That is, strips leading `///` and joins lines 118 /// That is, strips leading `///` (+ optional 1 character of whitespace)
119 fn doc_comment_text(&self) -> std::string::String { 119 /// and joins lines.
120 self.doc_comments() 120 fn doc_comment_text(&self) -> Option<std::string::String> {
121 let docs = self
122 .doc_comments()
121 .filter(|comment| comment.is_doc_comment()) 123 .filter(|comment| comment.is_doc_comment())
122 .map(|comment| { 124 .map(|comment| {
123 let prefix = comment.prefix(); 125 let prefix_len = comment.prefix().len();
124 let trimmed = comment 126
125 .text() 127 let line = comment.text().as_str();
126 .as_str() 128
127 .trim() 129 // Determine if the prefix or prefix + 1 char is stripped
128 .trim_start_matches(prefix) 130 let pos = if line
129 .trim_start(); 131 .chars()
130 trimmed.to_owned() 132 .nth(prefix_len)
133 .map(|c| c.is_whitespace())
134 .unwrap_or(false)
135 {
136 prefix_len + 1
137 } else {
138 prefix_len
139 };
140
141 line[pos..].to_owned()
131 }) 142 })
132 .join("\n") 143 .join("\n");
144
145 if docs.is_empty() {
146 None
147 } else {
148 Some(docs)
149 }
133 } 150 }
134} 151}
135 152
@@ -704,6 +721,18 @@ impl BindPat {
704} 721}
705 722
706#[test] 723#[test]
724fn test_doc_comment_none() {
725 let file = SourceFile::parse(
726 r#"
727 // non-doc
728 mod foo {}
729 "#,
730 );
731 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
732 assert!(module.doc_comment_text().is_none());
733}
734
735#[test]
707fn test_doc_comment_of_items() { 736fn test_doc_comment_of_items() {
708 let file = SourceFile::parse( 737 let file = SourceFile::parse(
709 r#" 738 r#"
@@ -713,5 +742,25 @@ fn test_doc_comment_of_items() {
713 "#, 742 "#,
714 ); 743 );
715 let module = file.syntax().descendants().find_map(Module::cast).unwrap(); 744 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
716 assert_eq!("doc", module.doc_comment_text()); 745 assert_eq!("doc", module.doc_comment_text().unwrap());
746}
747
748#[test]
749fn test_doc_comment_preserves_indents() {
750 let file = SourceFile::parse(
751 r#"
752 /// doc1
753 /// ```
754 /// fn foo() {
755 /// // ...
756 /// }
757 /// ```
758 mod foo {}
759 "#,
760 );
761 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
762 assert_eq!(
763 "doc1\n```\nfn foo() {\n // ...\n}\n```",
764 module.doc_comment_text().unwrap()
765 );
717} 766}