Skip to content

Commit 6c627d2

Browse files
authored
Rollup merge of #93038 - GuillaumeGomez:block-doc-comments, r=notriddle
Fix star handling in block doc comments Fixes #92872. Some extra explanation about this PR and why #92357 created this regression: when we merge doc comment kinds for example in: ```rust /// he /** * hello */ #[doc = "boom"] ``` We don't want to remove the empty lines between them. However, to correctly compute the "horizontal trim", we still need it, so instead, I put back a part of the "vertical trim" directly in the "horizontal trim" computation so it doesn't impact the output buffer but allows us to correctly handle the stars. r? `@camelid`
2 parents 1cb57e2 + 06b00ad commit 6c627d2

File tree

7 files changed

+60
-15
lines changed

7 files changed

+60
-15
lines changed

compiler/rustc_ast/src/attr/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,17 @@ impl Attribute {
242242
}
243243
}
244244

245+
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
246+
match self.kind {
247+
AttrKind::DocComment(kind, data) => Some((data, kind)),
248+
AttrKind::Normal(ref item, _) if item.path == sym::doc => item
249+
.meta_kind()
250+
.and_then(|kind| kind.value_str())
251+
.map(|data| (data, CommentKind::Line)),
252+
_ => None,
253+
}
254+
}
255+
245256
pub fn doc_str(&self) -> Option<Symbol> {
246257
match self.kind {
247258
AttrKind::DocComment(.., data) => Some(data),

compiler/rustc_ast/src/util/comments.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::token::CommentKind;
12
use rustc_span::source_map::SourceMap;
23
use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol};
34

@@ -25,7 +26,7 @@ pub struct Comment {
2526

2627
/// Makes a doc string more presentable to users.
2728
/// Used by rustdoc and perhaps other tools, but not by rustc.
28-
pub fn beautify_doc_string(data: Symbol) -> Symbol {
29+
pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
2930
fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
3031
let mut i = 0;
3132
let mut j = lines.len();
@@ -42,10 +43,28 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol {
4243
if i != 0 || j != lines.len() { Some((i, j)) } else { None }
4344
}
4445

45-
fn get_horizontal_trim(lines: &[&str]) -> Option<usize> {
46+
fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<usize> {
4647
let mut i = usize::MAX;
4748
let mut first = true;
4849

50+
// In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are
51+
// present. However, we first need to strip the empty lines so they don't get in the middle
52+
// when we try to compute the "horizontal trim".
53+
let lines = if kind == CommentKind::Block {
54+
let mut i = 0;
55+
let mut j = lines.len();
56+
57+
while i < j && lines[i].trim().is_empty() {
58+
i += 1;
59+
}
60+
while j > i && lines[j - 1].trim().is_empty() {
61+
j -= 1;
62+
}
63+
&lines[i..j]
64+
} else {
65+
lines
66+
};
67+
4968
for line in lines {
5069
for (j, c) in line.chars().enumerate() {
5170
if j > i || !"* \t".contains(c) {
@@ -79,11 +98,13 @@ pub fn beautify_doc_string(data: Symbol) -> Symbol {
7998
} else {
8099
&mut lines
81100
};
82-
if let Some(horizontal) = get_horizontal_trim(&lines) {
101+
if let Some(horizontal) = get_horizontal_trim(&lines, kind) {
83102
changes = true;
84103
// remove a "[ \t]*\*" block from each line, if possible
85104
for line in lines.iter_mut() {
86-
*line = &line[horizontal + 1..];
105+
if horizontal + 1 < line.len() {
106+
*line = &line[horizontal + 1..];
107+
}
87108
}
88109
}
89110
if changes {

compiler/rustc_ast/src/util/comments/tests.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_span::create_default_session_globals_then;
55
fn test_block_doc_comment_1() {
66
create_default_session_globals_then(|| {
77
let comment = "\n * Test \n ** Test\n * Test\n";
8-
let stripped = beautify_doc_string(Symbol::intern(comment));
8+
let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
99
assert_eq!(stripped.as_str(), " Test \n* Test\n Test");
1010
})
1111
}
@@ -14,7 +14,7 @@ fn test_block_doc_comment_1() {
1414
fn test_block_doc_comment_2() {
1515
create_default_session_globals_then(|| {
1616
let comment = "\n * Test\n * Test\n";
17-
let stripped = beautify_doc_string(Symbol::intern(comment));
17+
let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
1818
assert_eq!(stripped.as_str(), " Test\n Test");
1919
})
2020
}
@@ -23,21 +23,21 @@ fn test_block_doc_comment_2() {
2323
fn test_block_doc_comment_3() {
2424
create_default_session_globals_then(|| {
2525
let comment = "\n let a: *i32;\n *a = 5;\n";
26-
let stripped = beautify_doc_string(Symbol::intern(comment));
26+
let stripped = beautify_doc_string(Symbol::intern(comment), CommentKind::Block);
2727
assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;");
2828
})
2929
}
3030

3131
#[test]
3232
fn test_line_doc_comment() {
3333
create_default_session_globals_then(|| {
34-
let stripped = beautify_doc_string(Symbol::intern(" test"));
34+
let stripped = beautify_doc_string(Symbol::intern(" test"), CommentKind::Line);
3535
assert_eq!(stripped.as_str(), " test");
36-
let stripped = beautify_doc_string(Symbol::intern("! test"));
36+
let stripped = beautify_doc_string(Symbol::intern("! test"), CommentKind::Line);
3737
assert_eq!(stripped.as_str(), "! test");
38-
let stripped = beautify_doc_string(Symbol::intern("test"));
38+
let stripped = beautify_doc_string(Symbol::intern("test"), CommentKind::Line);
3939
assert_eq!(stripped.as_str(), "test");
40-
let stripped = beautify_doc_string(Symbol::intern("!test"));
40+
let stripped = beautify_doc_string(Symbol::intern("!test"), CommentKind::Line);
4141
assert_eq!(stripped.as_str(), "!test");
4242
})
4343
}

compiler/rustc_save_analysis/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -821,9 +821,9 @@ impl<'tcx> SaveContext<'tcx> {
821821
let mut result = String::new();
822822

823823
for attr in attrs {
824-
if let Some(val) = attr.doc_str() {
824+
if let Some((val, kind)) = attr.doc_str_and_comment_kind() {
825825
// FIXME: Should save-analysis beautify doc strings itself or leave it to users?
826-
result.push_str(beautify_doc_string(val).as_str());
826+
result.push_str(beautify_doc_string(val, kind).as_str());
827827
result.push('\n');
828828
}
829829
}

src/librustdoc/clean/types.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1040,9 +1040,9 @@ impl Attributes {
10401040
) -> Attributes {
10411041
let mut doc_strings: Vec<DocFragment> = vec![];
10421042
let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
1043-
if let Some(value) = attr.doc_str() {
1043+
if let Some((value, kind)) = attr.doc_str_and_comment_kind() {
10441044
trace!("got doc_str={:?}", value);
1045-
let value = beautify_doc_string(value);
1045+
let value = beautify_doc_string(value, kind);
10461046
let kind = if attr.is_doc_comment() {
10471047
DocFragmentKind::SugaredDoc
10481048
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<div class="docblock"><p>a</p>
2+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![crate_name = "foo"]
2+
3+
// The goal of this test is to answer that it won't be generated as a list because
4+
// block doc comments can have their lines starting with a star.
5+
6+
// @has foo/fn.foo.html
7+
// @snapshot docblock - '//*[@class="rustdoc-toggle top-doc"]//*[@class="docblock"]'
8+
/**
9+
* a
10+
*/
11+
pub fn foo() {}

0 commit comments

Comments
 (0)