Skip to content

Commit ec1907b

Browse files
committed
Do not indent or unindent inside string literal
Closes #2588.
1 parent 89070a2 commit ec1907b

File tree

2 files changed

+61
-34
lines changed

2 files changed

+61
-34
lines changed

src/lib.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use syntax::errors::{DiagnosticBuilder, Handler};
4747
use syntax::parse::{self, ParseSess};
4848

4949
use checkstyle::{output_footer, output_header};
50-
use comment::{CharClasses, FullCodeCharKind};
50+
use comment::{CharClasses, FullCodeCharKind, LineClasses};
5151
use issues::{BadIssueSeeker, Issue};
5252
use shape::Indent;
5353
use utils::use_colored_tty;
@@ -605,10 +605,19 @@ const FN_MAIN_PREFIX: &str = "fn main() {\n";
605605

606606
fn enclose_in_main_block(s: &str, config: &Config) -> String {
607607
let indent = Indent::from_width(config, config.tab_spaces());
608-
FN_MAIN_PREFIX.to_owned() + &indent.to_string(config)
609-
+ &s.lines()
610-
.collect::<Vec<_>>()
611-
.join(&indent.to_string_with_newline(config)) + "\n}"
608+
let mut result = String::with_capacity(s.len() * 2);
609+
result.push_str(FN_MAIN_PREFIX);
610+
let mut need_indent = true;
611+
for (kind, line) in LineClasses::new(s) {
612+
if need_indent {
613+
result.push_str(&indent.to_string(config));
614+
}
615+
result.push_str(&line);
616+
result.push('\n');
617+
need_indent = !(kind.is_string() && !line.ends_with('\\'));
618+
}
619+
result.push('}');
620+
result
612621
}
613622

614623
/// Format the given code block. Mainly targeted for code block in comment.
@@ -626,13 +635,16 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option<String>
626635
let formatted = format_snippet(&snippet, config)?;
627636
// 2 = "}\n"
628637
let block_len = formatted.len().checked_sub(2).unwrap_or(0);
629-
for line in formatted[FN_MAIN_PREFIX.len()..block_len].lines() {
638+
let mut is_indented = true;
639+
for (kind, ref line) in LineClasses::new(&formatted[FN_MAIN_PREFIX.len()..block_len]) {
630640
if !is_first {
631641
result.push('\n');
632642
} else {
633643
is_first = false;
634644
}
635-
let trimmed_line = if line.len() > config.max_width() {
645+
let trimmed_line = if !is_indented {
646+
line
647+
} else if line.len() > config.max_width() {
636648
// If there are lines that are larger than max width, we cannot tell
637649
// whether we have succeeded but have some comments or strings that
638650
// are too long, or we have failed to format code block. We will be
@@ -655,6 +667,7 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option<String>
655667
line
656668
};
657669
result.push_str(trimmed_line);
670+
is_indented = !(kind.is_string() && !line.ends_with('\\'));
658671
}
659672
Some(result)
660673
}

src/macros.rs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use syntax::{ast, ptr};
3434

3535
use codemap::SpanUtils;
3636
use comment::{contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented,
37-
FullCodeCharKind};
37+
FullCodeCharKind, LineClasses};
3838
use expr::rewrite_array;
3939
use lists::{itemize_list, write_list, ListFormatting};
4040
use overflow;
@@ -1054,18 +1054,27 @@ fn indent_macro_snippet(
10541054
macro_str: &str,
10551055
indent: Indent,
10561056
) -> Option<String> {
1057-
let mut lines = macro_str.lines();
1058-
let first_line = lines.next().map(|s| s.trim_right())?;
1057+
let mut lines = LineClasses::new(macro_str);
1058+
let first_line = lines.next().map(|(_, s)| s.trim_right().to_owned())?;
10591059
let mut trimmed_lines = Vec::with_capacity(16);
10601060

1061+
let mut veto_trim = false;
10611062
let min_prefix_space_width = lines
1062-
.filter_map(|line| {
1063-
let prefix_space_width = if is_empty_line(line) {
1063+
.filter_map(|(kind, line)| {
1064+
let mut trimmed = true;
1065+
let prefix_space_width = if is_empty_line(&line) {
10641066
None
10651067
} else {
1066-
Some(get_prefix_space_width(context, line))
1068+
Some(get_prefix_space_width(context, &line))
10671069
};
1068-
trimmed_lines.push((line.trim(), prefix_space_width));
1070+
let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) {
1071+
veto_trim = kind.is_string() && !line.ends_with('\\');
1072+
trimmed = false;
1073+
line
1074+
} else {
1075+
line.trim().to_owned()
1076+
};
1077+
trimmed_lines.push((trimmed, line, prefix_space_width));
10691078
prefix_space_width
10701079
})
10711080
.min()?;
@@ -1074,17 +1083,20 @@ fn indent_macro_snippet(
10741083
String::from(first_line) + "\n"
10751084
+ &trimmed_lines
10761085
.iter()
1077-
.map(|&(line, prefix_space_width)| match prefix_space_width {
1078-
Some(original_indent_width) => {
1079-
let new_indent_width = indent.width()
1080-
+ original_indent_width
1081-
.checked_sub(min_prefix_space_width)
1082-
.unwrap_or(0);
1083-
let new_indent = Indent::from_width(context.config, new_indent_width);
1084-
format!("{}{}", new_indent.to_string(context.config), line.trim())
1085-
}
1086-
None => String::new(),
1087-
})
1086+
.map(
1087+
|&(trimmed, ref line, prefix_space_width)| match prefix_space_width {
1088+
_ if !trimmed => line.to_owned(),
1089+
Some(original_indent_width) => {
1090+
let new_indent_width = indent.width()
1091+
+ original_indent_width
1092+
.checked_sub(min_prefix_space_width)
1093+
.unwrap_or(0);
1094+
let new_indent = Indent::from_width(context.config, new_indent_width);
1095+
format!("{}{}", new_indent.to_string(context.config), line.trim())
1096+
}
1097+
None => String::new(),
1098+
},
1099+
)
10881100
.collect::<Vec<_>>()
10891101
.join("\n"),
10901102
)
@@ -1231,15 +1243,17 @@ impl MacroBranch {
12311243

12321244
// Indent the body since it is in a block.
12331245
let indent_str = body_indent.to_string(&config);
1234-
let mut new_body = new_body
1235-
.trim_right()
1236-
.lines()
1237-
.fold(String::new(), |mut s, l| {
1238-
if !l.is_empty() {
1239-
s += &indent_str;
1240-
}
1241-
s + l + "\n"
1242-
});
1246+
let mut new_body = LineClasses::new(new_body.trim_right())
1247+
.fold(
1248+
(String::new(), true),
1249+
|(mut s, need_indent), (kind, ref l)| {
1250+
if !l.is_empty() && need_indent {
1251+
s += &indent_str;
1252+
}
1253+
(s + l + "\n", !(kind.is_string() && !l.ends_with('\\')))
1254+
},
1255+
)
1256+
.0;
12431257

12441258
// Undo our replacement of macro variables.
12451259
// FIXME: this could be *much* more efficient.

0 commit comments

Comments
 (0)