Skip to content

Commit baa62c6

Browse files
committed
recognize strings inside comments in order to avoid indenting them
Close rust-lang#3270
1 parent 2c204c1 commit baa62c6

File tree

7 files changed

+114
-38
lines changed

7 files changed

+114
-38
lines changed

src/comment.rs

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,21 +1029,28 @@ impl RichChar for (usize, char) {
10291029
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
10301030
enum CharClassesStatus {
10311031
Normal,
1032+
/// Character is within a string
10321033
LitString,
10331034
LitStringEscape,
1035+
/// Character is within a raw string
10341036
LitRawString(u32),
10351037
RawStringPrefix(u32),
10361038
RawStringSuffix(u32),
10371039
LitChar,
10381040
LitCharEscape,
1039-
// The u32 is the nesting deepness of the comment
1041+
/// Character inside a block comment, with the integer indicating the nesting deepness of the
1042+
/// comment
10401043
BlockComment(u32),
1041-
// Status when the '/' has been consumed, but not yet the '*', deepness is
1042-
// the new deepness (after the comment opening).
1044+
/// Character inside a block-commented string, with the integer indicating the nesting deepness
1045+
/// of the comment
1046+
StringInBlockComment(u32),
1047+
/// Status when the '/' has been consumed, but not yet the '*', deepness is
1048+
/// the new deepness (after the comment opening).
10431049
BlockCommentOpening(u32),
1044-
// Status when the '*' has been consumed, but not yet the '/', deepness is
1045-
// the new deepness (after the comment closing).
1050+
/// Status when the '*' has been consumed, but not yet the '/', deepness is
1051+
/// the new deepness (after the comment closing).
10461052
BlockCommentClosing(u32),
1053+
/// Character is within a line comment
10471054
LineComment,
10481055
}
10491056

@@ -1067,6 +1074,12 @@ pub enum FullCodeCharKind {
10671074
InComment,
10681075
/// Last character of a comment, '\n' for a line comment, '/' for a block comment.
10691076
EndComment,
1077+
/// Start of a mutlitine string inside a comment
1078+
StartStringCommented,
1079+
/// End of a mutlitine string inside a comment
1080+
EndStringCommented,
1081+
/// Inside a commented string
1082+
InStringCommented,
10701083
/// Start of a mutlitine string
10711084
StartString,
10721085
/// End of a mutlitine string
@@ -1080,7 +1093,21 @@ impl FullCodeCharKind {
10801093
match self {
10811094
FullCodeCharKind::StartComment
10821095
| FullCodeCharKind::InComment
1083-
| FullCodeCharKind::EndComment => true,
1096+
| FullCodeCharKind::EndComment
1097+
| FullCodeCharKind::StartStringCommented
1098+
| FullCodeCharKind::InStringCommented
1099+
| FullCodeCharKind::EndStringCommented => true,
1100+
_ => false,
1101+
}
1102+
}
1103+
1104+
/// Returns true if the character is inside a comment
1105+
pub fn inside_comment(self) -> bool {
1106+
match self {
1107+
FullCodeCharKind::InComment
1108+
| FullCodeCharKind::StartStringCommented
1109+
| FullCodeCharKind::InStringCommented
1110+
| FullCodeCharKind::EndStringCommented => true,
10841111
_ => false,
10851112
}
10861113
}
@@ -1089,6 +1116,12 @@ impl FullCodeCharKind {
10891116
self == FullCodeCharKind::InString || self == FullCodeCharKind::StartString
10901117
}
10911118

1119+
/// Returns true if the character is within a commented string
1120+
pub fn is_commented_string(self) -> bool {
1121+
self == FullCodeCharKind::InStringCommented
1122+
|| self == FullCodeCharKind::StartStringCommented
1123+
}
1124+
10921125
fn to_codecharkind(self) -> CodeCharKind {
10931126
if self.is_comment() {
10941127
CodeCharKind::Comment
@@ -1232,18 +1265,27 @@ where
12321265
},
12331266
_ => CharClassesStatus::Normal,
12341267
},
1268+
CharClassesStatus::StringInBlockComment(deepness) => {
1269+
char_kind = FullCodeCharKind::InStringCommented;
1270+
if chr == '"' {
1271+
CharClassesStatus::BlockComment(deepness)
1272+
} else {
1273+
CharClassesStatus::StringInBlockComment(deepness)
1274+
}
1275+
}
12351276
CharClassesStatus::BlockComment(deepness) => {
12361277
assert_ne!(deepness, 0);
1237-
self.status = match self.base.peek() {
1278+
char_kind = FullCodeCharKind::InComment;
1279+
match self.base.peek() {
12381280
Some(next) if next.get_char() == '/' && chr == '*' => {
12391281
CharClassesStatus::BlockCommentClosing(deepness - 1)
12401282
}
12411283
Some(next) if next.get_char() == '*' && chr == '/' => {
12421284
CharClassesStatus::BlockCommentOpening(deepness + 1)
12431285
}
1244-
_ => CharClassesStatus::BlockComment(deepness),
1245-
};
1246-
return Some((FullCodeCharKind::InComment, item));
1286+
_ if chr == '"' => CharClassesStatus::StringInBlockComment(deepness),
1287+
_ => self.status,
1288+
}
12471289
}
12481290
CharClassesStatus::BlockCommentOpening(deepness) => {
12491291
assert_eq!(chr, '*');
@@ -1299,26 +1341,33 @@ impl<'a> Iterator for LineClasses<'a> {
12991341

13001342
let mut line = String::new();
13011343

1302-
let start_class = match self.base.peek() {
1344+
let start_kind = match self.base.peek() {
13031345
Some((kind, _)) => *kind,
13041346
None => unreachable!(),
13051347
};
13061348

13071349
while let Some((kind, c)) = self.base.next() {
1350+
// needed to set the kind of the ending character on the last line
1351+
self.kind = kind;
13081352
if c == '\n' {
1309-
self.kind = match (start_class, kind) {
1353+
self.kind = match (start_kind, kind) {
13101354
(FullCodeCharKind::Normal, FullCodeCharKind::InString) => {
13111355
FullCodeCharKind::StartString
13121356
}
13131357
(FullCodeCharKind::InString, FullCodeCharKind::Normal) => {
13141358
FullCodeCharKind::EndString
13151359
}
1360+
(FullCodeCharKind::InComment, FullCodeCharKind::InStringCommented) => {
1361+
FullCodeCharKind::StartStringCommented
1362+
}
1363+
(FullCodeCharKind::InStringCommented, FullCodeCharKind::InComment) => {
1364+
FullCodeCharKind::EndStringCommented
1365+
}
13161366
_ => kind,
13171367
};
13181368
break;
1319-
} else {
1320-
line.push(c);
13211369
}
1370+
line.push(c);
13221371
}
13231372

13241373
// Workaround for CRLF newline.
@@ -1364,7 +1413,12 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> {
13641413
}
13651414
FullCodeCharKind::StartComment => {
13661415
// Consume the whole comment
1367-
while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {}
1416+
loop {
1417+
match self.iter.next() {
1418+
Some((kind, ..)) if kind.inside_comment() => continue,
1419+
_ => break,
1420+
}
1421+
}
13681422
}
13691423
_ => panic!(),
13701424
}

src/utils.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -527,19 +527,24 @@ pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) ->
527527
Some(get_prefix_space_width(config, &line))
528528
};
529529

530-
let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) {
531-
veto_trim = kind.is_string() && !line.ends_with('\\');
530+
let new_veto_trim_value =
531+
(kind.is_string() || kind.is_commented_string()) && !line.ends_with('\\');
532+
let line = if veto_trim || new_veto_trim_value {
533+
veto_trim = new_veto_trim_value;
532534
trimmed = false;
533535
line
534536
} else {
535537
line.trim().to_owned()
536538
};
537539
trimmed_lines.push((trimmed, line, prefix_space_width));
538540

539-
// When computing the minimum, do not consider lines within a string.
540-
// The reason is there is a veto against trimming and indenting such lines
541+
// Because there is a veto against trimming and indenting lines within a string,
542+
// such lines should not be taken into account when computing the minimum.
541543
match kind {
542-
FullCodeCharKind::InString | FullCodeCharKind::EndString => None,
544+
FullCodeCharKind::InString
545+
| FullCodeCharKind::EndString
546+
| FullCodeCharKind::InStringCommented
547+
| FullCodeCharKind::EndStringCommented => None,
543548
_ => prefix_space_width,
544549
}
545550
})

tests/source/issue-3132.rs

Lines changed: 0 additions & 13 deletions
This file was deleted.

tests/source/issue-3270.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub fn main() {
2+
/* let s = String::from(
3+
"
4+
hello
5+
world
6+
",
7+
); */
8+
9+
assert_eq!(s, "\nhello\nworld\n");
10+
}

tests/target/issue-3132.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ fn test() {
44
*/
55
let x = 42;
66
/*
7-
aaa
8-
"line 1
9-
line 2
10-
line 3"
11-
*/
7+
aaa
8+
"line 1
9+
line 2
10+
line 3"
11+
*/
1212
let x = 42;
1313
}

tests/target/issue-3270-wrap.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// rustfmt-wrap_comments: true
2+
3+
fn func() {
4+
let x = 42;
5+
/*
6+
let something = "one line line line line line line line line line line line line
7+
two lines
8+
three lines";
9+
*/
10+
}

tests/target/issue-3270.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub fn main() {
2+
/* let s = String::from(
3+
"
4+
hello
5+
world
6+
",
7+
); */
8+
9+
assert_eq!(s, "\nhello\nworld\n");
10+
}

0 commit comments

Comments
 (0)