Skip to content

Commit

Permalink
Rollup merge of rust-lang#93038 - GuillaumeGomez:block-doc-comments, …
Browse files Browse the repository at this point in the history
…r=notriddle

Fix star handling in block doc comments

Fixes rust-lang#92872.

Some extra explanation about this PR and why rust-lang#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``
  • Loading branch information
matthiaskrgr authored Jan 20, 2022
2 parents 530c884 + 06b00ad commit aa7f452
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 15 deletions.
11 changes: 11 additions & 0 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
29 changes: 25 additions & 4 deletions compiler/rustc_ast/src/util/comments.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::token::CommentKind;
use rustc_span::source_map::SourceMap;
use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol};

Expand Down Expand Up @@ -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();
Expand All @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_ast/src/util/comments/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
})
}
Expand All @@ -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");
})
}
Expand All @@ -23,21 +23,21 @@ 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;");
})
}

#[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");
})
}
4 changes: 2 additions & 2 deletions compiler/rustc_save_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1041,9 +1041,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 {
Expand Down
2 changes: 2 additions & 0 deletions src/test/rustdoc/strip-block-doc-comments-stars.docblock.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div class="docblock"><p>a</p>
</div>
11 changes: 11 additions & 0 deletions src/test/rustdoc/strip-block-doc-comments-stars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![crate_name = "foo"]

// The goal of this test is to answer that it won't be generated as a list because
// block doc comments can have their lines starting with a star.

// @has foo/fn.foo.html
// @snapshot docblock - '//*[@class="rustdoc-toggle top-doc"]//*[@class="docblock"]'
/**
* a
*/
pub fn foo() {}

0 comments on commit aa7f452

Please sign in to comment.