}
}
+ 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),
+use crate::token::CommentKind;
use rustc_span::source_map::SourceMap;
use rustc_span::{BytePos, CharPos, FileName, Pos, Symbol};
/// 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();
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) {
} 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 {
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");
})
}
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");
})
}
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");
})
}
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');
}
}
) -> 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 {