Skip to content

Commit 0101e2b

Browse files
authored
Merge pull request #3553 from bash/minor-refactorings
Minor refactorings
2 parents cc97eaf + 4241930 commit 0101e2b

File tree

3 files changed

+75
-40
lines changed

3 files changed

+75
-40
lines changed

src/attr.rs

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

5555
/// Returns the arguments of `#[derive(...)]`.
56-
fn get_derive_spans(attr: &ast::Attribute) -> Option<Vec<Span>> {
56+
fn get_derive_spans<'a>(attr: &'a ast::Attribute) -> Option<impl Iterator<Item = Span> + 'a> {
5757
attr.meta_item_list().map(|meta_item_list| {
5858
meta_item_list
59-
.iter()
59+
.into_iter()
6060
.map(|nested_meta_item| nested_meta_item.span)
61-
.collect()
6261
})
6362
}
6463

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

0 commit comments

Comments
 (0)