Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 9b98dd7

Browse files
author
Ruben Schmidmeister
committed
Merge branch 'master' into normalize-multiline-doc-attributes
2 parents 3eb8e4d + 421ed94 commit 9b98dd7

33 files changed

+200
-85
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ matrix:
2626
- env: INTEGRATION=log
2727
- env: INTEGRATION=mdbook
2828
- env: INTEGRATION=packed_simd
29-
- env: INTEGRATION=rand
3029
- env: INTEGRATION=rust-semverver
3130
- env: INTEGRATION=stdsimd TARGET=x86_64-unknown-linux-gnu
3231
- env: INTEGRATION=tempdir
3332
- env: INTEGRATION=futures-rs
3433
allow_failures:
34+
# Using old configuration option
35+
- env: INTEGRATION=rand
3536
# Doesn't build - keep this in allow_failures as it's fragile to breaking changes of rustc.
3637
- env: INTEGRATION=rust-clippy
3738
# Doesn't build - seems to be because of an option

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Change option `format_doc_comment` to `format_code_in_doc_comment`.
56
- `use_small_heuristics` changed to be an enum and stabilised. Configuration
67
options are now ready for 1.0.
78

Configurations.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,9 +1978,9 @@ fn main() {
19781978
}
19791979
```
19801980

1981-
## `format_doc_comments`
1981+
## `format_code_in_doc_comments`
19821982

1983-
Format doc comments.
1983+
Format code snippet included in doc comments.
19841984

19851985
- **Default value**: `false`
19861986
- **Possible values**: `true`, `false`

src/attr.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,11 @@ fn is_derive(attr: &ast::Attribute) -> bool {
5656
}
5757

5858
/// Returns the arguments of `#[derive(...)]`.
59-
fn get_derive_spans(attr: &ast::Attribute) -> Option<Vec<Span>> {
59+
fn get_derive_spans<'a>(attr: &'a ast::Attribute) -> Option<impl Iterator<Item = Span> + 'a> {
6060
attr.meta_item_list().map(|meta_item_list| {
6161
meta_item_list
62-
.iter()
62+
.into_iter()
6363
.map(|nested_meta_item| nested_meta_item.span)
64-
.collect()
6564
})
6665
}
6766

@@ -412,10 +411,11 @@ impl<'a> Rewrite for [ast::Attribute] {
412411
// Handle derives if we will merge them.
413412
if context.config.merge_derives() && is_derive(&attrs[0]) {
414413
let derives = take_while_with_pred(context, attrs, is_derive);
415-
let mut derive_spans = vec![];
416-
for derive in derives {
417-
derive_spans.append(&mut get_derive_spans(derive)?);
418-
}
414+
let derive_spans: Vec<_> = derives
415+
.iter()
416+
.filter_map(get_derive_spans)
417+
.flatten()
418+
.collect();
419419
let derive_str =
420420
format_derive(&derive_spans, attr_prefix(&attrs[0]), shape, context)?;
421421
result.push_str(&derive_str);

src/checkstyle.rs

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::fmt::{self, Display};
12
use std::io::{self, Write};
23
use std::path::Path;
34

@@ -9,9 +10,9 @@ use crate::rustfmt_diff::{DiffLine, Mismatch};
910
/// future version of Rustfmt.
1011
pub(crate) fn header() -> String {
1112
let mut xml_heading = String::new();
12-
xml_heading.push_str("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
13+
xml_heading.push_str(r#"<?xml version="1.0" encoding="utf-8"?>"#);
1314
xml_heading.push_str("\n");
14-
xml_heading.push_str("<checkstyle version=\"4.3\">");
15+
xml_heading.push_str(r#"<checkstyle version="4.3">"#);
1516
xml_heading
1617
}
1718

@@ -31,17 +32,16 @@ pub(crate) fn output_checkstyle_file<T>(
3132
where
3233
T: Write,
3334
{
34-
write!(writer, "<file name=\"{}\">", filename.display())?;
35+
write!(writer, r#"<file name="{}">"#, filename.display())?;
3536
for mismatch in diff {
3637
for line in mismatch.lines {
3738
// Do nothing with `DiffLine::Context` and `DiffLine::Resulting`.
38-
if let DiffLine::Expected(ref str) = line {
39-
let message = xml_escape_str(str);
39+
if let DiffLine::Expected(message) = line {
4040
write!(
4141
writer,
42-
"<error line=\"{}\" severity=\"warning\" message=\"Should be `{}`\" \
43-
/>",
44-
mismatch.line_number, message
42+
r#"<error line="{}" severity="warning" message="Should be `{}`" />"#,
43+
mismatch.line_number,
44+
XmlEscaped(&message)
4545
)?;
4646
}
4747
}
@@ -50,19 +50,53 @@ where
5050
Ok(())
5151
}
5252

53-
// Convert special characters into XML entities.
54-
// This is needed for checkstyle output.
55-
fn xml_escape_str(string: &str) -> String {
56-
let mut out = String::new();
57-
for c in string.chars() {
58-
match c {
59-
'<' => out.push_str("&lt;"),
60-
'>' => out.push_str("&gt;"),
61-
'"' => out.push_str("&quot;"),
62-
'\'' => out.push_str("&apos;"),
63-
'&' => out.push_str("&amp;"),
64-
_ => out.push(c),
53+
/// Convert special characters into XML entities.
54+
/// This is needed for checkstyle output.
55+
struct XmlEscaped<'a>(&'a str);
56+
57+
impl<'a> Display for XmlEscaped<'a> {
58+
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
59+
for char in self.0.chars() {
60+
match char {
61+
'<' => write!(formatter, "&lt;"),
62+
'>' => write!(formatter, "&gt;"),
63+
'"' => write!(formatter, "&quot;"),
64+
'\'' => write!(formatter, "&apos;"),
65+
'&' => write!(formatter, "&amp;"),
66+
_ => write!(formatter, "{}", char),
67+
}?;
6568
}
69+
70+
Ok(())
71+
}
72+
}
73+
74+
#[cfg(test)]
75+
mod tests {
76+
use super::*;
77+
78+
#[test]
79+
fn special_characters_are_escaped() {
80+
assert_eq!(
81+
"&lt;&gt;&quot;&apos;&amp;",
82+
format!("{}", XmlEscaped(r#"<>"'&"#)),
83+
);
84+
}
85+
86+
#[test]
87+
fn special_characters_are_escaped_in_string_with_other_characters() {
88+
assert_eq!(
89+
"The quick brown &quot;🦊&quot; jumps &lt;over&gt; the lazy 🐶",
90+
format!(
91+
"{}",
92+
XmlEscaped(r#"The quick brown "🦊" jumps <over> the lazy 🐶"#)
93+
),
94+
);
95+
}
96+
97+
#[test]
98+
fn other_characters_are_not_escaped() {
99+
let string = "The quick brown 🦊 jumps over the lazy 🐶";
100+
assert_eq!(string, format!("{}", XmlEscaped(string)));
66101
}
67-
out
68102
}

src/comment.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ fn identify_comment(
353353
trim_left_preserve_layout(first_group, shape.indent, config)?
354354
} else if !config.normalize_comments()
355355
&& !config.wrap_comments()
356-
&& !config.format_doc_comments()
356+
&& !config.format_code_in_doc_comments()
357357
{
358358
light_rewrite_comment(first_group, shape.indent, config, is_doc_comment)
359359
} else {
@@ -656,9 +656,16 @@ impl<'a> CommentRewrite<'a> {
656656
_ => {
657657
let mut config = self.fmt.config.clone();
658658
config.set().wrap_comments(false);
659-
match crate::format_code_block(&self.code_block_buffer, &config) {
660-
Some(ref s) => trim_custom_comment_prefix(&s.snippet),
661-
None => trim_custom_comment_prefix(&self.code_block_buffer),
659+
if config.format_code_in_doc_comments() {
660+
if let Some(s) =
661+
crate::format_code_block(&self.code_block_buffer, &config)
662+
{
663+
trim_custom_comment_prefix(&s.snippet)
664+
} else {
665+
trim_custom_comment_prefix(&self.code_block_buffer)
666+
}
667+
} else {
668+
trim_custom_comment_prefix(&self.code_block_buffer)
662669
}
663670
}
664671
};

src/config/config_type.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,6 @@ impl ConfigType for IgnoreList {
5050
}
5151
}
5252

53-
/// Checks if we're in a nightly build.
54-
///
55-
/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap
56-
/// to "stable", "beta", or "nightly" depending on what toolchain is being built.
57-
/// If we are being built as part of the stable or beta toolchains, we want
58-
/// to disable unstable configuration options.
59-
///
60-
/// If we're being built by cargo (e.g., `cargo +nightly install rustfmt-nightly`),
61-
/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the
62-
/// nightly compiler when installed from crates.io, default to nightly mode.
63-
macro_rules! is_nightly_channel {
64-
() => {
65-
option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev")
66-
};
67-
}
68-
6953
macro_rules! create_config {
7054
($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
7155
#[cfg(test)]
@@ -159,7 +143,7 @@ macro_rules! create_config {
159143
self.$i.1 = true;
160144
self.$i.2 = val;
161145
} else {
162-
if is_nightly_channel!() {
146+
if crate::is_nightly_channel!() {
163147
self.$i.1 = true;
164148
self.$i.2 = val;
165149
} else {

src/config/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ create_config! {
4040

4141
// Comments. macros, and strings
4242
wrap_comments: bool, false, false, "Break comments to fit on the line";
43-
format_doc_comments: bool, false, false, "Format doc comments.";
43+
format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments.";
4444
comment_width: usize, 80, false,
4545
"Maximum length of comments. No effect unless wrap_comments = true";
4646
normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible";

src/formatting.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,7 @@ struct FormatLines<'a> {
458458
errors: Vec<FormattingError>,
459459
issue_seeker: BadIssueSeeker,
460460
line_buffer: String,
461-
// `true` if the current line contains a string literal.
462-
is_string: bool,
461+
current_line_contains_string_literal: bool,
463462
format_line: bool,
464463
allow_issue_seek: bool,
465464
config: &'a Config,
@@ -483,7 +482,7 @@ impl<'a> FormatLines<'a> {
483482
allow_issue_seek: !issue_seeker.is_disabled(),
484483
issue_seeker,
485484
line_buffer: String::with_capacity(config.max_width() * 2),
486-
is_string: false,
485+
current_line_contains_string_literal: false,
487486
format_line: config.file_lines().contains_line(name, 1),
488487
config,
489488
}
@@ -547,7 +546,7 @@ impl<'a> FormatLines<'a> {
547546
&& !self.is_skipped_line()
548547
&& self.should_report_error(kind, &error_kind)
549548
{
550-
let is_string = self.is_string;
549+
let is_string = self.current_line_contains_string_literal;
551550
self.push_err(error_kind, kind.is_comment(), is_string);
552551
}
553552
}
@@ -561,7 +560,7 @@ impl<'a> FormatLines<'a> {
561560
self.newline_count += 1;
562561
self.last_was_space = false;
563562
self.line_buffer.clear();
564-
self.is_string = false;
563+
self.current_line_contains_string_literal = false;
565564
}
566565

567566
fn char(&mut self, c: char, kind: FullCodeCharKind) {
@@ -574,7 +573,7 @@ impl<'a> FormatLines<'a> {
574573
self.last_was_space = c.is_whitespace();
575574
self.line_buffer.push(c);
576575
if kind.is_string() {
577-
self.is_string = true;
576+
self.current_line_contains_string_literal = true;
578577
}
579578
}
580579

@@ -589,12 +588,14 @@ impl<'a> FormatLines<'a> {
589588
}
590589

591590
fn should_report_error(&self, char_kind: FullCodeCharKind, error_kind: &ErrorKind) -> bool {
592-
let allow_error_report =
593-
if char_kind.is_comment() || self.is_string || error_kind.is_comment() {
594-
self.config.error_on_unformatted()
595-
} else {
596-
true
597-
};
591+
let allow_error_report = if char_kind.is_comment()
592+
|| self.current_line_contains_string_literal
593+
|| error_kind.is_comment()
594+
{
595+
self.config.error_on_unformatted()
596+
} else {
597+
true
598+
};
598599

599600
match error_kind {
600601
ErrorKind::LineOverflow(..) => {

src/items.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,6 @@ pub(crate) fn format_impl(
664664
context: &RewriteContext<'_>,
665665
item: &ast::Item,
666666
offset: Indent,
667-
where_span_end: Option<BytePos>,
668667
) -> Option<String> {
669668
if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node {
670669
let mut result = String::with_capacity(128);
@@ -691,6 +690,8 @@ pub(crate) fn format_impl(
691690
option.compress_where();
692691
}
693692

693+
let misssing_span = mk_sp(self_ty.span.hi(), item.span.hi());
694+
let where_span_end = context.snippet_provider.opt_span_before(misssing_span, "{");
694695
let where_clause_str = rewrite_where_clause(
695696
context,
696697
&generics.where_clause,

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ pub use crate::rustfmt_diff::{ModifiedChunk, ModifiedLines};
4040
#[macro_use]
4141
mod utils;
4242

43+
#[macro_use]
44+
mod release_channel;
45+
4346
mod attr;
4447
mod chains;
4548
pub(crate) mod checkstyle;

src/release_channel.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/// Checks if we're in a nightly build.
2+
///
3+
/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap
4+
/// to "stable", "beta", or "nightly" depending on what toolchain is being built.
5+
/// If we are being built as part of the stable or beta toolchains, we want
6+
/// to disable unstable configuration options.
7+
///
8+
/// If we're being built by cargo (e.g., `cargo +nightly install rustfmt-nightly`),
9+
/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the
10+
/// nightly compiler when installed from crates.io, default to nightly mode.
11+
#[macro_export]
12+
macro_rules! is_nightly_channel {
13+
() => {
14+
option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev")
15+
};
16+
}

0 commit comments

Comments
 (0)