about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2022-01-18 16:56:16 +0100
committerGuillaume Gomez <guillaume.gomez@huawei.com>2022-01-19 11:18:17 +0100
commit2938be612dce1d2976bebf80812d713257a3b501 (patch)
tree5233b516f4b68779c110c4d9dcb7538d39e5b7fe
parent7531d2fdd49966d83830a7b4596c95587b1e9573 (diff)
downloadrust-2938be612dce1d2976bebf80812d713257a3b501.tar.gz
rust-2938be612dce1d2976bebf80812d713257a3b501.zip
Correctly handle starts in block doc comments
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs11
-rw-r--r--compiler/rustc_ast/src/util/comments.rs29
-rw-r--r--compiler/rustc_ast/src/util/comments/tests.rs14
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs4
-rw-r--r--src/librustdoc/clean/types.rs4
5 files changed, 47 insertions, 15 deletions
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index d66774040f7..6a0ace04d4b 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -242,6 +242,17 @@ impl Attribute {
         }
     }
 
+    pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
+        match self.kind {
+            AttrKind::DocComment(kind, data) => Some((data, kind)),
+            AttrKind::Normal(ref item, _) if item.path == sym::doc => item
+                .meta_kind()
+                .and_then(|kind| kind.value_str())
+                .map(|data| (data, CommentKind::Line)),
+            _ => None,
+        }
+    }
+
     pub fn doc_str(&self) -> Option<Symbol> {
         match self.kind {
             AttrKind::DocComment(.., data) => Some(data),
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index 0a391123dd3..612ee71f350 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -1,3 +1,4 @@
+use crate::token::CommentKind;
 use rustc_span::source_map::SourceMap;
 use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol};
 
@@ -25,7 +26,7 @@ pub struct Comment {
 
 /// Makes a doc string more presentable to users.
 /// Used by rustdoc and perhaps other tools, but not by rustc.
-pub fn beautify_doc_string(data: Symbol) -> Symbol {
+pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
     fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
         let mut i = 0;
         let mut j = lines.len();
@@ -42,10 +43,28 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol {
         if i != 0 || j != lines.len() { Some((i, j)) } else { None }
     }
 
-    fn get_horizontal_trim(lines: &[&str]) -> Option<usize> {
+    fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> {
         let mut i = usize::MAX;
         let mut first = true;
 
+        // In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are
+        // present. However, we first need to strip the empty lines so they don't get in the middle
+        // when we try to compute the "horizontal trim".
+        let lines = if kind == CommentKind::Block {
+            let mut i = 0;
+            let mut j = lines.len();
+
+            while i < j && lines[i].trim().is_empty() {
+                i += 1;
+            }
+            while j > i && lines[j - 1].trim().is_empty() {
+                j -= 1;
+            }
+            &lines[i..j]
+        } else {
+            lines
+        };
+
         for line in lines {
             for (j, c) in line.chars().enumerate() {
                 if j > i || !"* \t".contains(c) {
@@ -79,11 +98,13 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol {
         } else {
             &mut lines
         };
-        if let Some(horizontal) = get_horizontal_trim(&lines) {
+        if let Some(horizontal) = get_horizontal_trim(&lines, kind) {
             changes = true;
             // remove a "[ \t]*\*" block from each line, if possible
             for line in lines.iter_mut() {
-                *line = &line[horizontal + 1..];
+                if horizontal + 1 < line.len() {
+                    *line = &line[horizontal + 1..];
+                }
             }
         }
         if changes {
diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs
index 6d137f3774f..98f692a7724 100644
--- a/compiler/rustc_ast/src/util/comments/tests.rs
+++ b/compiler/rustc_ast/src/util/comments/tests.rs
@@ -5,7 +5,7 @@ use rustc_span::create_default_session_globals_then;
 fn test_block_doc_comment_1() {
     create_default_session_globals_then(|| {
         let comment = "\n * Test \n **  Test\n *   Test\n";
-        let stripped = beautify_doc_string(Symbol::intern(comment));
+        let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
         assert_eq!(stripped.as_str(), " Test \n*  Test\n   Test");
     })
 }
@@ -14,7 +14,7 @@ fn test_block_doc_comment_1() {
 fn test_block_doc_comment_2() {
     create_default_session_globals_then(|| {
         let comment = "\n * Test\n *  Test\n";
-        let stripped = beautify_doc_string(Symbol::intern(comment));
+        let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
         assert_eq!(stripped.as_str(), " Test\n  Test");
     })
 }
@@ -23,7 +23,7 @@ fn test_block_doc_comment_2() {
 fn test_block_doc_comment_3() {
     create_default_session_globals_then(|| {
         let comment = "\n let a: *i32;\n *a = 5;\n";
-        let stripped = beautify_doc_string(Symbol::intern(comment));
+        let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
         assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;");
     })
 }
@@ -31,13 +31,13 @@ fn test_block_doc_comment_3() {
 #[test]
 fn test_line_doc_comment() {
     create_default_session_globals_then(|| {
-        let stripped = beautify_doc_string(Symbol::intern(" test"));
+        let stripped = beautify_doc_string(Symbol::intern(" test"), CommentKind::Line);
         assert_eq!(stripped.as_str(), " test");
-        let stripped = beautify_doc_string(Symbol::intern("! test"));
+        let stripped = beautify_doc_string(Symbol::intern("! test"), CommentKind::Line);
         assert_eq!(stripped.as_str(), "! test");
-        let stripped = beautify_doc_string(Symbol::intern("test"));
+        let stripped = beautify_doc_string(Symbol::intern("test"), CommentKind::Line);
         assert_eq!(stripped.as_str(), "test");
-        let stripped = beautify_doc_string(Symbol::intern("!test"));
+        let stripped = beautify_doc_string(Symbol::intern("!test"), CommentKind::Line);
         assert_eq!(stripped.as_str(), "!test");
     })
 }
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 21cb93cc5f4..b95fe1b0549 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -821,9 +821,9 @@ impl<'tcx> SaveContext<'tcx> {
         let mut result = String::new();
 
         for attr in attrs {
-            if let Some(val) = attr.doc_str() {
+            if let Some((val, kind)) = attr.doc_str_and_comment_kind() {
                 // FIXME: Should save-analysis beautify doc strings itself or leave it to users?
-                result.push_str(beautify_doc_string(val).as_str());
+                result.push_str(beautify_doc_string(val, kind).as_str());
                 result.push('\n');
             }
         }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 00c6e38839f..8e60473140a 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1040,9 +1040,9 @@ impl Attributes {
     ) -> Attributes {
         let mut doc_strings: Vec<DocFragment> = vec![];
         let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
-            if let Some(value) = attr.doc_str() {
+            if let Some((value, kind)) = attr.doc_str_and_comment_kind() {
                 trace!("got doc_str={:?}", value);
-                let value = beautify_doc_string(value);
+                let value = beautify_doc_string(value, kind);
                 let kind = if attr.is_doc_comment() {
                     DocFragmentKind::SugaredDoc
                 } else {