diff options
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 00c60ebf3..74a45f52f 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -115,19 +115,30 @@ 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 | /// and joins lines. | ||
119 | fn doc_comment_text(&self) -> std::string::String { | 120 | fn doc_comment_text(&self) -> std::string::String { |
120 | self.doc_comments() | 121 | self.doc_comments() |
121 | .filter(|comment| comment.is_doc_comment()) | 122 | .filter(|comment| comment.is_doc_comment()) |
122 | .map(|comment| { | 123 | .map(|comment| { |
123 | let prefix = comment.prefix(); | 124 | let prefix_len = comment.prefix().len(); |
124 | let trimmed = comment | 125 | |
125 | .text() | 126 | // Strip leading and trailing whitespace |
126 | .as_str() | 127 | let line = comment.text().as_str().trim(); |
127 | .trim() | 128 | |
128 | .trim_start_matches(prefix) | 129 | // Determine if the prefix or prefix + 1 char is stripped |
129 | .trim_start(); | 130 | let pos = if line |
130 | trimmed.to_owned() | 131 | .chars() |
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") |
133 | } | 144 | } |
@@ -701,3 +712,23 @@ fn test_doc_comment_of_items() { | |||
701 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); | 712 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); |
702 | assert_eq!("doc", module.doc_comment_text()); | 713 | assert_eq!("doc", module.doc_comment_text()); |
703 | } | 714 | } |
715 | |||
716 | #[test] | ||
717 | fn test_doc_comment_preserves_indents() { | ||
718 | let file = SourceFile::parse( | ||
719 | r#" | ||
720 | /// doc1 | ||
721 | /// ``` | ||
722 | /// fn foo() { | ||
723 | /// // ... | ||
724 | /// } | ||
725 | /// ``` | ||
726 | mod foo {} | ||
727 | "#, | ||
728 | ); | ||
729 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); | ||
730 | assert_eq!( | ||
731 | "doc1\n```\nfn foo() {\n // ...\n}\n```", | ||
732 | module.doc_comment_text() | ||
733 | ); | ||
734 | } | ||