Skip to content

Commit d2e91b5

Browse files
authored
Merge pull request rust-lang#3284 from scampi/issue-3270
recognize strings inside comments in order to avoid indenting them
2 parents a01990c + 083a20f commit d2e91b5

File tree

9 files changed

+150
-38
lines changed

9 files changed

+150
-38
lines changed

src/comment.rs

+69-15
Original file line numberDiff line numberDiff line change
@@ -1047,21 +1047,28 @@ impl RichChar for (usize, char) {
10471047
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
10481048
enum CharClassesStatus {
10491049
Normal,
1050+
/// Character is within a string
10501051
LitString,
10511052
LitStringEscape,
1053+
/// Character is within a raw string
10521054
LitRawString(u32),
10531055
RawStringPrefix(u32),
10541056
RawStringSuffix(u32),
10551057
LitChar,
10561058
LitCharEscape,
1057-
// The u32 is the nesting deepness of the comment
1059+
/// Character inside a block comment, with the integer indicating the nesting deepness of the
1060+
/// comment
10581061
BlockComment(u32),
1059-
// Status when the '/' has been consumed, but not yet the '*', deepness is
1060-
// the new deepness (after the comment opening).
1062+
/// Character inside a block-commented string, with the integer indicating the nesting deepness
1063+
/// of the comment
1064+
StringInBlockComment(u32),
1065+
/// Status when the '/' has been consumed, but not yet the '*', deepness is
1066+
/// the new deepness (after the comment opening).
10611067
BlockCommentOpening(u32),
1062-
// Status when the '*' has been consumed, but not yet the '/', deepness is
1063-
// the new deepness (after the comment closing).
1068+
/// Status when the '*' has been consumed, but not yet the '/', deepness is
1069+
/// the new deepness (after the comment closing).
10641070
BlockCommentClosing(u32),
1071+
/// Character is within a line comment
10651072
LineComment,
10661073
}
10671074

@@ -1085,6 +1092,12 @@ pub enum FullCodeCharKind {
10851092
InComment,
10861093
/// Last character of a comment, '\n' for a line comment, '/' for a block comment.
10871094
EndComment,
1095+
/// Start of a mutlitine string inside a comment
1096+
StartStringCommented,
1097+
/// End of a mutlitine string inside a comment
1098+
EndStringCommented,
1099+
/// Inside a commented string
1100+
InStringCommented,
10881101
/// Start of a mutlitine string
10891102
StartString,
10901103
/// End of a mutlitine string
@@ -1098,7 +1111,21 @@ impl FullCodeCharKind {
10981111
match self {
10991112
FullCodeCharKind::StartComment
11001113
| FullCodeCharKind::InComment
1101-
| FullCodeCharKind::EndComment => true,
1114+
| FullCodeCharKind::EndComment
1115+
| FullCodeCharKind::StartStringCommented
1116+
| FullCodeCharKind::InStringCommented
1117+
| FullCodeCharKind::EndStringCommented => true,
1118+
_ => false,
1119+
}
1120+
}
1121+
1122+
/// Returns true if the character is inside a comment
1123+
pub fn inside_comment(self) -> bool {
1124+
match self {
1125+
FullCodeCharKind::InComment
1126+
| FullCodeCharKind::StartStringCommented
1127+
| FullCodeCharKind::InStringCommented
1128+
| FullCodeCharKind::EndStringCommented => true,
11021129
_ => false,
11031130
}
11041131
}
@@ -1107,6 +1134,12 @@ impl FullCodeCharKind {
11071134
self == FullCodeCharKind::InString || self == FullCodeCharKind::StartString
11081135
}
11091136

1137+
/// Returns true if the character is within a commented string
1138+
pub fn is_commented_string(self) -> bool {
1139+
self == FullCodeCharKind::InStringCommented
1140+
|| self == FullCodeCharKind::StartStringCommented
1141+
}
1142+
11101143
fn to_codecharkind(self) -> CodeCharKind {
11111144
if self.is_comment() {
11121145
CodeCharKind::Comment
@@ -1250,18 +1283,27 @@ where
12501283
},
12511284
_ => CharClassesStatus::Normal,
12521285
},
1286+
CharClassesStatus::StringInBlockComment(deepness) => {
1287+
char_kind = FullCodeCharKind::InStringCommented;
1288+
if chr == '"' {
1289+
CharClassesStatus::BlockComment(deepness)
1290+
} else {
1291+
CharClassesStatus::StringInBlockComment(deepness)
1292+
}
1293+
}
12531294
CharClassesStatus::BlockComment(deepness) => {
12541295
assert_ne!(deepness, 0);
1255-
self.status = match self.base.peek() {
1296+
char_kind = FullCodeCharKind::InComment;
1297+
match self.base.peek() {
12561298
Some(next) if next.get_char() == '/' && chr == '*' => {
12571299
CharClassesStatus::BlockCommentClosing(deepness - 1)
12581300
}
12591301
Some(next) if next.get_char() == '*' && chr == '/' => {
12601302
CharClassesStatus::BlockCommentOpening(deepness + 1)
12611303
}
1262-
_ => CharClassesStatus::BlockComment(deepness),
1263-
};
1264-
return Some((FullCodeCharKind::InComment, item));
1304+
_ if chr == '"' => CharClassesStatus::StringInBlockComment(deepness),
1305+
_ => self.status,
1306+
}
12651307
}
12661308
CharClassesStatus::BlockCommentOpening(deepness) => {
12671309
assert_eq!(chr, '*');
@@ -1317,26 +1359,33 @@ impl<'a> Iterator for LineClasses<'a> {
13171359

13181360
let mut line = String::new();
13191361

1320-
let start_class = match self.base.peek() {
1362+
let start_kind = match self.base.peek() {
13211363
Some((kind, _)) => *kind,
13221364
None => unreachable!(),
13231365
};
13241366

13251367
while let Some((kind, c)) = self.base.next() {
1368+
// needed to set the kind of the ending character on the last line
1369+
self.kind = kind;
13261370
if c == '\n' {
1327-
self.kind = match (start_class, kind) {
1371+
self.kind = match (start_kind, kind) {
13281372
(FullCodeCharKind::Normal, FullCodeCharKind::InString) => {
13291373
FullCodeCharKind::StartString
13301374
}
13311375
(FullCodeCharKind::InString, FullCodeCharKind::Normal) => {
13321376
FullCodeCharKind::EndString
13331377
}
1378+
(FullCodeCharKind::InComment, FullCodeCharKind::InStringCommented) => {
1379+
FullCodeCharKind::StartStringCommented
1380+
}
1381+
(FullCodeCharKind::InStringCommented, FullCodeCharKind::InComment) => {
1382+
FullCodeCharKind::EndStringCommented
1383+
}
13341384
_ => kind,
13351385
};
13361386
break;
1337-
} else {
1338-
line.push(c);
13391387
}
1388+
line.push(c);
13401389
}
13411390

13421391
// Workaround for CRLF newline.
@@ -1382,7 +1431,12 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> {
13821431
}
13831432
FullCodeCharKind::StartComment => {
13841433
// Consume the whole comment
1385-
while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {}
1434+
loop {
1435+
match self.iter.next() {
1436+
Some((kind, ..)) if kind.inside_comment() => continue,
1437+
_ => break,
1438+
}
1439+
}
13861440
}
13871441
_ => panic!(),
13881442
}

src/utils.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use syntax::source_map::{BytePos, Span, NO_EXPANSION};
2222
use syntax_pos::Mark;
2323

2424
use comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses};
25-
use config::Config;
25+
use config::{Config, Version};
2626
use rewrite::RewriteContext;
2727
use shape::{Indent, Shape};
2828

@@ -527,18 +527,26 @@ 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 = (kind.is_string()
531+
|| (config.version() == Version::Two && kind.is_commented_string()))
532+
&& !line.ends_with('\\');
533+
let line = if veto_trim || new_veto_trim_value {
534+
veto_trim = new_veto_trim_value;
532535
trimmed = false;
533536
line
534537
} else {
535538
line.trim().to_owned()
536539
};
537540
trimmed_lines.push((trimmed, line, prefix_space_width));
538541

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
542+
// Because there is a veto against trimming and indenting lines within a string,
543+
// such lines should not be taken into account when computing the minimum.
541544
match kind {
545+
FullCodeCharKind::InStringCommented | FullCodeCharKind::EndStringCommented
546+
if config.version() == Version::Two =>
547+
{
548+
None
549+
}
542550
FullCodeCharKind::InString | FullCodeCharKind::EndString => None,
543551
_ => prefix_space_width,
544552
}

tests/source/issue-3132.rs

-13
This file was deleted.

tests/source/issue-3270/one.rs

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

tests/source/issue-3270/two.rs

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

tests/target/issue-3132.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
// rustfmt-version: Two
2+
13
fn test() {
24
/*
35
a
46
*/
57
let x = 42;
68
/*
7-
aaa
8-
"line 1
9-
line 2
10-
line 3"
11-
*/
9+
aaa
10+
"line 1
11+
line 2
12+
line 3"
13+
*/
1214
let x = 42;
1315
}

tests/target/issue-3270/one.rs

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

tests/target/issue-3270/two.rs

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

tests/target/issue-3270/wrap.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// rustfmt-wrap_comments: true
2+
// rustfmt-version: Two
3+
4+
// check that a line below max_width does not get over the limit when wrapping
5+
// it in a block comment
6+
fn func() {
7+
let x = 42;
8+
/*
9+
let something = "one line line line line line line line line line line line line line
10+
two lines
11+
three lines";
12+
*/
13+
}

0 commit comments

Comments
 (0)