Skip to content

Commit d1da537

Browse files
committed
Version gating along with rebase and commits consolidation
1 parent 5391847 commit d1da537

File tree

7 files changed

+475
-45
lines changed

7 files changed

+475
-45
lines changed

src/comment.rs

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ use lazy_static::lazy_static;
77
use regex::Regex;
88
use rustc_span::Span;
99

10-
use crate::config::Config;
10+
use crate::config::{Config, Version};
1111
use crate::rewrite::RewriteContext;
1212
use crate::shape::{Indent, Shape};
1313
use crate::string::{rewrite_string, StringFormat};
1414
use crate::utils::{
15-
count_newlines, first_line_width, last_line_width, trim_left_preserve_layout,
15+
count_newlines, first_line_width, is_single_line, last_line_width, trim_left_preserve_layout,
1616
trimmed_last_line_width, unicode_str_width,
1717
};
1818
use crate::{ErrorKind, FormattingError};
@@ -160,6 +160,20 @@ pub(crate) fn is_last_comment_block(s: &str) -> bool {
160160
s.trim_end().ends_with("*/")
161161
}
162162

163+
/// Returns true if the last comment in the first line of the passed comments block
164+
/// ends on that line.
165+
fn is_first_comment_line_ends_comment(s: &str) -> bool {
166+
if s.starts_with("/*") {
167+
// FIXME: mixed block and line comments on the same line are not properly formatted,
168+
// e.g. "/* Block comment /* // Line comment" at the end of the line.
169+
s.lines().next().map_or(false, |l| l.ends_with("*/"))
170+
} else if s.starts_with("//") {
171+
true // Comment is "// comment"
172+
} else {
173+
false
174+
}
175+
}
176+
163177
/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain
164178
/// comments between two strings. If there are such comments, then that will be
165179
/// recovered. If `allow_extend` is true and there is no comment between the two
@@ -226,7 +240,15 @@ pub(crate) fn combine_strs_with_missing_comments(
226240
} else {
227241
let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1;
228242
if prefer_same_line && one_line_width <= shape.width {
229-
Cow::from(" ")
243+
// First comment in the comments block can be in same line if it ends in the first line.
244+
if context.config.version() == Version::One
245+
|| is_single_line(&missing_comment)
246+
|| is_first_comment_line_ends_comment(&missing_comment)
247+
{
248+
Cow::from(" ")
249+
} else {
250+
indent.to_string_with_newline(config)
251+
}
230252
} else {
231253
indent.to_string_with_newline(config)
232254
}
@@ -240,7 +262,11 @@ pub(crate) fn combine_strs_with_missing_comments(
240262
indent.to_string_with_newline(config)
241263
} else {
242264
one_line_width += missing_comment.len() + first_sep.len() + 1;
243-
allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n');
265+
if context.config.version() == Version::One {
266+
allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n');
267+
} else {
268+
allow_one_line &= !missing_comment.contains('\n');
269+
}
244270
if prefer_same_line && allow_one_line && one_line_width <= shape.width {
245271
Cow::from(" ")
246272
} else {
@@ -1017,27 +1043,57 @@ fn light_rewrite_comment(
10171043
config: &Config,
10181044
is_doc_comment: bool,
10191045
) -> String {
1020-
let lines: Vec<&str> = orig
1021-
.lines()
1022-
.map(|l| {
1023-
// This is basically just l.trim(), but in the case that a line starts
1024-
// with `*` we want to leave one space before it, so it aligns with the
1025-
// `*` in `/*`.
1026-
let first_non_whitespace = l.find(|c| !char::is_whitespace(c));
1027-
let left_trimmed = if let Some(fnw) = first_non_whitespace {
1028-
if l.as_bytes()[fnw] == b'*' && fnw > 0 {
1029-
&l[fnw - 1..]
1046+
if config.version() == Version::One {
1047+
let lines: Vec<&str> = orig
1048+
.lines()
1049+
.map(|l| {
1050+
// This is basically just l.trim(), but in the case that a line starts
1051+
// with `*` we want to leave one space before it, so it aligns with the
1052+
// `*` in `/*`.
1053+
let first_non_whitespace = l.find(|c| !char::is_whitespace(c));
1054+
let left_trimmed = if let Some(fnw) = first_non_whitespace {
1055+
if l.as_bytes()[fnw] == b'*' && fnw > 0 {
1056+
&l[fnw - 1..]
1057+
} else {
1058+
&l[fnw..]
1059+
}
10301060
} else {
1031-
&l[fnw..]
1032-
}
1033-
} else {
1034-
""
1035-
};
1061+
""
1062+
};
1063+
// Preserve markdown's double-space line break syntax in doc comment.
1064+
trim_end_unless_two_whitespaces(left_trimmed, is_doc_comment)
1065+
})
1066+
.collect();
1067+
lines.join(&format!("\n{}", offset.to_string(config)))
1068+
} else {
1069+
// Version::Two
1070+
let mut result = String::with_capacity(orig.len() * 2);
1071+
let mut lines = orig.lines().peekable();
1072+
1073+
// This is basically just l.trim(), but in the case that a line starts with `*`
1074+
// we want to leave one space before it, so it aligns with the `*` in `/*`.
1075+
while let Some(full_line) = lines.next() {
1076+
let line = full_line.trim_start();
1077+
1078+
if line.is_empty() {
1079+
continue;
1080+
}
1081+
1082+
if line.starts_with('*') {
1083+
result.push(' ');
1084+
}
1085+
10361086
// Preserve markdown's double-space line break syntax in doc comment.
1037-
trim_end_unless_two_whitespaces(left_trimmed, is_doc_comment)
1038-
})
1039-
.collect();
1040-
lines.join(&format!("\n{}", offset.to_string(config)))
1087+
let trimmed = trim_end_unless_two_whitespaces(line, is_doc_comment);
1088+
result.push_str(trimmed);
1089+
1090+
let is_last = lines.peek().is_none();
1091+
if !is_last {
1092+
result.push_str(&offset.to_string_with_newline(config))
1093+
}
1094+
}
1095+
result
1096+
}
10411097
}
10421098

10431099
/// Trims comment characters and possibly a single space from the left of a string.

src/expr.rs

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl Rewrite for ast::Expr {
4242
}
4343
}
4444

45-
#[derive(Copy, Clone, PartialEq)]
45+
#[derive(Copy, Clone, PartialEq, Debug)]
4646
pub(crate) enum ExprType {
4747
Statement,
4848
SubExpression,
@@ -171,11 +171,19 @@ pub(crate) fn format_expr(
171171
ast::ExprKind::Path(ref qself, ref path) => {
172172
rewrite_path(context, PathContext::Expr, qself, path, shape)
173173
}
174-
ast::ExprKind::Assign(ref lhs, ref rhs, _) => {
175-
rewrite_assignment(context, lhs, rhs, None, shape)
174+
ast::ExprKind::Assign(ref lhs, ref rhs, op_span) => {
175+
if context.config.version() == Version::One {
176+
rewrite_assignment_for_op(context, lhs, rhs, None, shape)
177+
} else {
178+
rewrite_assignment_for_op_span(context, lhs, rhs, op_span, shape)
179+
}
176180
}
177181
ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => {
178-
rewrite_assignment(context, lhs, rhs, Some(op), shape)
182+
if context.config.version() == Version::One {
183+
rewrite_assignment_for_op(context, lhs, rhs, Some(op), shape)
184+
} else {
185+
rewrite_assignment_for_op_span(context, lhs, rhs, op.span, shape)
186+
}
179187
}
180188
ast::ExprKind::Continue(ref opt_label) => {
181189
let id_str = match *opt_label {
@@ -1898,7 +1906,7 @@ impl<'ast> RhsAssignKind<'ast> {
18981906
}
18991907
}
19001908

1901-
fn rewrite_assignment(
1909+
fn rewrite_assignment_for_op(
19021910
context: &RewriteContext<'_>,
19031911
lhs: &ast::Expr,
19041912
rhs: &ast::Expr,
@@ -1910,19 +1918,60 @@ fn rewrite_assignment(
19101918
None => "=",
19111919
};
19121920

1913-
// 1 = space between lhs and operator.
1914-
let lhs_shape = shape.sub_width(operator_str.len() + 1)?;
1915-
let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str);
1921+
rewrite_assignment(context, lhs, rhs, operator_str, None, shape)
1922+
}
19161923

1917-
rewrite_assign_rhs(
1924+
fn rewrite_assignment_for_op_span(
1925+
context: &RewriteContext<'_>,
1926+
lhs: &ast::Expr,
1927+
rhs: &ast::Expr,
1928+
op_span: Span,
1929+
shape: Shape,
1930+
) -> Option<String> {
1931+
rewrite_assignment(
19181932
context,
1919-
lhs_str,
1933+
lhs,
19201934
rhs,
1921-
&RhsAssignKind::Expr(&rhs.kind, rhs.span),
1935+
context.snippet(op_span),
1936+
Some(mk_sp(op_span.hi(), rhs.span.lo())),
19221937
shape,
19231938
)
19241939
}
19251940

1941+
fn rewrite_assignment(
1942+
context: &RewriteContext<'_>,
1943+
lhs: &ast::Expr,
1944+
rhs: &ast::Expr,
1945+
operator_str: &str,
1946+
comment_span: Option<Span>,
1947+
shape: Shape,
1948+
) -> Option<String> {
1949+
// 1 = space between lhs and operator.
1950+
let lhs_shape = shape.sub_width(operator_str.len() + 1)?;
1951+
let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str);
1952+
1953+
if context.config.version() == Version::One {
1954+
rewrite_assign_rhs(
1955+
context,
1956+
lhs_str,
1957+
rhs,
1958+
&RhsAssignKind::Expr(&rhs.kind, rhs.span),
1959+
shape,
1960+
)
1961+
} else {
1962+
rewrite_assign_rhs_with_comments(
1963+
context,
1964+
lhs_str,
1965+
rhs,
1966+
shape,
1967+
&RhsAssignKind::Expr(&rhs.kind, rhs.span),
1968+
RhsTactics::Default,
1969+
comment_span?,
1970+
true,
1971+
)
1972+
}
1973+
}
1974+
19261975
/// Controls where to put the rhs.
19271976
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
19281977
pub(crate) enum RhsTactics {

src/items.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,45 @@ impl Rewrite for ast::Local {
112112

113113
result.push_str(&infix);
114114

115-
if let Some((init, _els)) = self.kind.init_else_opt() {
116-
// 1 = trailing semicolon;
117-
let nested_shape = shape.sub_width(1)?;
115+
if context.config.version() == Version::One {
116+
if let Some((init, _els)) = self.kind.init_else_opt() {
117+
// 1 = trailing semicolon;
118+
let nested_shape = shape.sub_width(1)?;
118119

119-
result = rewrite_assign_rhs(
120-
context,
121-
result,
122-
init,
123-
&RhsAssignKind::Expr(&init.kind, init.span),
124-
nested_shape,
125-
)?;
126-
// todo else
120+
result = rewrite_assign_rhs(
121+
context,
122+
result,
123+
init,
124+
&RhsAssignKind::Expr(&init.kind, init.span),
125+
nested_shape,
126+
)?;
127+
// todo else
128+
}
129+
} else {
130+
// Version:Two+
131+
if let Some(expr) = self.kind.init() {
132+
let base_span = if let Some(ref ty) = self.ty {
133+
mk_sp(ty.span.hi(), self.span.hi())
134+
} else {
135+
mk_sp(self.pat.span.hi(), self.span.hi())
136+
};
137+
138+
let comment_lo = context.snippet_provider.span_after(base_span, "=");
139+
let comment_span = mk_sp(comment_lo, expr.span.lo());
140+
141+
// 1 = trailing semicolon;
142+
let nested_shape = shape.sub_width(1)?;
143+
result = rewrite_assign_rhs_with_comments(
144+
context,
145+
result,
146+
expr,
147+
nested_shape,
148+
&RhsAssignKind::Expr(&expr.kind, expr.span),
149+
RhsTactics::Default,
150+
comment_span,
151+
true,
152+
)?;
153+
}
127154
}
128155

129156
result.push(';');
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// rustfmt-version: Two
2+
// "=" Assignemnt - Multiline Block comments
3+
fn main () {
4+
let var = /* Block comment line 1
5+
* Block comment line 2
6+
* Block comment line 3 */ first;
7+
var = /* Block comment line 1
8+
* Block comment line 2
9+
* Block comment line 3 */ second;
10+
var = /* Block comment line 1 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
11+
* Block comment line 2
12+
* Block comment line 3 */ third;
13+
var = /* Block comment line 1
14+
* Block comment line 2 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
15+
* Block comment line 3 */ forth;
16+
}
17+
18+
// "=" Assignemnt - Multiline Line and Block comments
19+
fn main () {
20+
let var = // Line comment 1
21+
// Line comment 2
22+
// Line comment 3
23+
first;
24+
var = // Line comment
25+
/* Block comment line 1
26+
* Block comment line 2 */ second;
27+
var = /* Block comment single line */
28+
// Line comment
29+
/* Block comment line 1
30+
* Block comment line 2 */ third;
31+
var = /* Block comment single line 1 */
32+
/* Block comment single line 2*/ forth;
33+
var = /* Block comment single line 1 */
34+
/* Block comment single line 2*/
35+
fifth;
36+
var = /* Block comment line 1 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
37+
* Block comment line 2 */
38+
// Line comment
39+
sixth;
40+
var = // Line comment
41+
/* Block comment line 1 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
42+
* Block comment line 2 */ seventh;
43+
}
44+
45+
// BinOp Assignemnt - Multiline Block comments
46+
fn main () {
47+
let var = /* Block comment line 1
48+
* Block comment line 2
49+
* Block comment line 3 */ first;
50+
var += /* Block comment line 1
51+
* Block comment line 2
52+
* Block comment line 3 */ second;
53+
var -= /* Block comment line 1 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
54+
* Block comment line 2
55+
* Block comment line 3 */ third;
56+
var *= /* Block comment line 1
57+
* Block comment line 2 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
58+
* Block comment line 3 */ forth;
59+
}
60+
61+
// BinOp Assignemnt - Multiline Line and Block comments
62+
fn main () {
63+
let var = // Line comment 1
64+
// Line comment 2
65+
// Line comment 3
66+
first;
67+
var += // Line comment
68+
/* Block comment line 1
69+
* Block comment line 2 */ second;
70+
var -= /* Block comment single line */
71+
// Line comment
72+
/* Block comment line 1
73+
* Block comment line 2 */ third;
74+
var *= /* Block comment line 1 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
75+
* Block comment line 2 */
76+
// Line comment
77+
forth;
78+
var /= // Line comment
79+
/* Block comment line 1 longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
80+
* Block comment line 2 */ fifth;
81+
}

0 commit comments

Comments
 (0)