Open calebcartwright opened 2 years ago
@calebcartwright I'm happy to help look into this 😁. Would we want to add a Version Two
section to each configuration's documentation or did you have something else in mind in regards to how we'd document the V1
vs V2
formatting differences?
Thanks! The most immediate need is really just an enumeration of the differences in one place, as succinctly as possible. Even something as simple as comments posted on this issue would help in the short term.
Sure! I'll take a look through the codebase to look for all the places where we special case the formatting for Version One
or Version Two
. I like the idea of compiling all the differences here, and then moving them over to the docs once we've got them mostly listed out. @jmj0502 would there be any interest on your end in helping me work on this?
@ytmimi I'm up for it 🚀! Thanks for taking me into consideration. It would be cool if we can define the structure we'll use to describe each V2
feature as a starting point (the simplest that comes to mind would be title -> snippet). What do you think?
hard_tabs (Indentation for generics on impl blocks)
V2
The examples are taken out of the different test cases available on the master branch (the examples of this change are applied over the generics of impl
blocks at top and module levels).
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
mod foo {
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
}
items.rs/format_impl_ref_and_type
.
https://github.com/rust-lang/rustfmt/blob/ad9fb89c3009282a55582f1c478d215d0c6005b0/src/items.rs#L830-L838
V1
formatimpl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
mod foo {
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
}
@ytmimi @calebcartwright Please, let me know if there's something else you would like me to add to this code sample (a detailed description, more code, etc.). I plan to use this sample as a template for further examples.
@jmj0502 I like it! This is similar to the approach that I was going to take. I think maybe the only addition that would be nice is a reference to where in the codebase we conditionally check for v2
/ v1
formatting.
@ytmimi Cool! That would be awesome. I'll modify the example, in order to add such reference as soon as I can!
Indentation for generics on impl blocks (No additional options)
V2
The examples for this particular feature are taken out of the different test cases available on the main branch. The feature is tested on top and module level impl
blocks.
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
mod foo {
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
}
items.rs/format_impl_ref_and_type
.
https://github.com/rust-lang/rustfmt/blob/ad9fb89c3009282a55582f1c478d215d0c6005b0/src/items.rs#L830-L838
V1
formatimpl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
mod foo {
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
}
Reference in codebase
V2
The examples for this feature are taken out of different test cases available on the master
branch. Such test cases contain long line comments after different const
and variable
declarations.
pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast
// Multicast using broadcst. add.
pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE
pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE
pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX
//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX
//const SQ_GRANT: u16 = 0x0012; // GRANT
//const SQ_REVOKE: u16 = 0x0013; // REVOKE
fn foo() {
let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem.
// Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis
// malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at
// nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci
// bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc
// suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a
// pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus.
// In hac habitasse platea dictumst. Vivamus a orci at nulla tristique
// condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit
// amet, ipsum. In pharetra sagittis nunc.
let b = baz();
let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0]
// TODO(emilio): It may make sense to make this range [.01, 10.0], to align
// with css-fonts-4's range of [1, 1000].
}
V1
formatpub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast
// Multicast using broadcst. add.
pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE
pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE
pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX
//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX
//const SQ_GRANT: u16 = 0x0012; // GRANT
//const SQ_REVOKE: u16 = 0x0013; // REVOKE
fn foo() {
let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla.
// Lorem. Id turpis. Nam posuere lectus vitae nibh. Etiam
// tortor orci, sagittis malesuada, rhoncus quis, hendrerit eget, libero.
// Quisque commodo nulla at nunc. Mauris consequat, enim vitae venenatis
// sollicitudin, dolor orci bibendum enim, a sagittis nulla nunc quis elit.
// Phasellus augue. Nunc suscipit, magna tincidunt lacinia faucibus, lacus
// tellus ornare purus, a pulvinar lacus orci eget nibh. Maecenas sed nibh non
// lacus tempor faucibus. In hac habitasse platea dictumst. Vivamus a orci at
// nulla tristique condimentum. Donec arcu quam, dictum accumsan, convallis
// accumsan, cursus sit amet, ipsum. In pharetra sagittis nunc.
let b = baz();
let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0]
// TODO(emilio): It may make sense to make this range [.01, 10.0], to align
// with css-fonts-4's range of [1, 1000].
}
Came up with a little script to help us find all the Version::One
and Version::Two
uses throughout the codebase:
regex="Version::One|Version::Two"
for file in $(rg "$regex" --files-with-matches src);
do
echo "Version Usage in $file "
git --no-pager blame -- $file | rg "$regex" -A 3 -B 3
echo "
"
done
Here's the output with some annotations and references to PRs where the version gates were added. Hoping that the links to PRs can help us get some context for the version gates (and maybe some examples):
Version gate added in #3833
c0e616bc1 (Seiichi Uchida 2019-07-17 23:07:12 +0900 297)
c0e616bc1 (Seiichi Uchida 2019-07-17 23:07:12 +0900 298) let mut comment_shape =
c0e616bc1 (Seiichi Uchida 2019-07-17 23:07:12 +0900 299) Shape::indented(self.block_indent, config).comment(config);
fb01dc857 (Stéphane Campinas 2019-10-04 17:22:01 +0200 300) if self.config.version() == Version::Two && comment_on_same_line {
c0e616bc1 (Seiichi Uchida 2019-07-17 23:07:12 +0900 301) self.push_str(" ");
fb01dc857 (Stéphane Campinas 2019-10-04 17:22:01 +0200 302) // put the first line of the comment on the same line as the
fb01dc857 (Stéphane Campinas 2019-10-04 17:22:01 +0200 303) // block's last line
Version gate added in #3326
2d718a3fc (Stéphane Campinas 2018-10-30 01:09:09 +0100 589)
813aa7956 (Stéphane Campinas 2019-02-07 00:05:05 +0100 590) // just InString{Commented} in order to allow the start of a string to be indented
813aa7956 (Stéphane Campinas 2019-02-07 00:05:05 +0100 591) let new_veto_trim_value = (kind == FullCodeCharKind::InString
813aa7956 (Stéphane Campinas 2019-02-07 00:05:05 +0100 592) || (config.version() == Version::Two
813aa7956 (Stéphane Campinas 2019-02-07 00:05:05 +0100 593) && kind == FullCodeCharKind::InStringCommented))
083a20fb1 (Stéphane Campinas 2019-01-16 23:06:28 +0100 594) && !line.ends_with('\\');
baa62c609 (Stéphane Campinas 2019-01-10 14:25:07 +0100 595) let line = if veto_trim || new_veto_trim_value {
Version gate added in #3284
baa62c609 (Stéphane Campinas 2019-01-10 14:25:07 +0100 605) // such lines should not be taken into account when computing the minimum.
2d718a3fc (Stéphane Campinas 2018-10-30 01:09:09 +0100 606) match kind {
083a20fb1 (Stéphane Campinas 2019-01-16 23:06:28 +0100 607) FullCodeCharKind::InStringCommented | FullCodeCharKind::EndStringCommented
083a20fb1 (Stéphane Campinas 2019-01-16 23:06:28 +0100 608) if config.version() == Version::Two =>
083a20fb1 (Stéphane Campinas 2019-01-16 23:06:28 +0100 609) {
083a20fb1 (Stéphane Campinas 2019-01-16 23:06:28 +0100 610) None
083a20fb1 (Stéphane Campinas 2019-01-16 23:06:28 +0100 611) }
Version gate added in #5201
8211d64c7 (Caleb Cartwright 2022-03-29 23:17:30 -0500 649) // formatting the code block, therefore the string's indentation needs
8211d64c7 (Caleb Cartwright 2022-03-29 23:17:30 -0500 650) // to be adjusted for the code surrounding the code block.
8211d64c7 (Caleb Cartwright 2022-03-29 23:17:30 -0500 651) config.format_strings() && line.ends_with('\\')
8211d64c7 (Caleb Cartwright 2022-03-29 23:17:30 -0500 652) } else if config.version() == Version::Two {
8211d64c7 (Caleb Cartwright 2022-03-29 23:17:30 -0500 653) !kind.is_commented_string()
8211d64c7 (Caleb Cartwright 2022-03-29 23:17:30 -0500 654) } else {
8211d64c7 (Caleb Cartwright 2022-03-29 23:17:30 -0500 655) true
Version gate added in #3833
efb68ee21 (Seiichi Uchida 2017-12-12 13:48:24 +0900 246) let indent_str = self.block_indent.to_string(self.config);
efb68ee21 (Seiichi Uchida 2017-12-12 13:48:24 +0900 247) self.push_str(&indent_str);
984ac100a (topecongiro 2017-12-22 12:00:24 +0900 248) self.block_indent
fb01dc857 (Stéphane Campinas 2019-10-04 17:22:01 +0200 249) } else if self.config.version() == Version::Two && !snippet.starts_with('\n') {
fb01dc857 (Stéphane Campinas 2019-10-04 17:22:01 +0200 250) // The comment appears on the same line as the previous formatted code.
fb01dc857 (Stéphane Campinas 2019-10-04 17:22:01 +0200 251) // Assuming that comment is logically associated with that code, we want to keep it on
fb01dc857 (Stéphane Campinas 2019-10-04 17:22:01 +0200 252) // the same level and avoid mixing it with possible other comment.
Version gate added in #3556
ae9ce7bcd (Seiichi Uchida 2017-06-18 22:44:56 +0900 1206) .lines()
ff0683d66 (Shotaro Yamada 2019-03-29 17:54:29 +0900 1207) .dropping_back(1)
ae9ce7bcd (Seiichi Uchida 2017-06-18 22:44:56 +0900 1208) .all(|line| line.ends_with('\\'))
69c7dbcd5 (Rui 2019-10-19 17:19:47 +0800 1209) && context.config.version() == Version::Two
ae9ce7bcd (Seiichi Uchida 2017-06-18 22:44:56 +0900 1210) {
69c7dbcd5 (Rui 2019-10-19 17:19:47 +0800 1211) return Some(string_lit.to_owned());
ae9ce7bcd (Seiichi Uchida 2017-06-18 22:44:56 +0900 1212) } else {
Version gate added in #3856
0167c5303 (Caleb Cartwright 2021-12-02 21:35:30 -0600 827) result.push_str(format_defaultness(defaultness));
0167c5303 (Caleb Cartwright 2021-12-02 21:35:30 -0600 828) result.push_str(format_unsafety(unsafety));
a5d7073bf (dawirstejeck 2016-09-06 07:11:56 +0200 829)
0167c5303 (Caleb Cartwright 2021-12-02 21:35:30 -0600 830) let shape = if context.config.version() == Version::Two {
0167c5303 (Caleb Cartwright 2021-12-02 21:35:30 -0600 831) Shape::indented(offset + last_line_width(&result), context.config)
0167c5303 (Caleb Cartwright 2021-12-02 21:35:30 -0600 832) } else {
0167c5303 (Caleb Cartwright 2021-12-02 21:35:30 -0600 833) generics_shape_from_config(
Version gate added in #3731
582aa4f2f (Marcus Klaas 2015-09-08 20:56:33 +0200 1946) match *self {
7a76ec062 (Caleb Cartwright 2020-03-26 15:26:58 -0500 1947) ast::FnRetTy::Default(_) => Some(String::new()),
7a76ec062 (Caleb Cartwright 2020-03-26 15:26:58 -0500 1948) ast::FnRetTy::Ty(ref ty) => {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 1949) if context.config.version() == Version::One
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 1950) || context.config.indent_style() == IndentStyle::Visual
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 1951) {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 1952) let inner_width = shape.width.checked_sub(3)?;
Version gate(s) added in #3294
54233acc8 (topecongiro 2017-06-17 16:56:54 +0900 2323) .last()
d8357484a (Seiichi Uchida 2018-09-11 13:31:37 +0900 2324) .map_or(false, |last_line| last_line.contains("//"));
7b996542c (rchaser53 2019-01-25 23:40:12 +0900 2325)
f92f3e3bd (rchaser53 2019-01-27 14:33:03 +0900 2326) if context.config.version() == Version::Two {
233497ace (rChaser53 2019-10-24 22:16:56 +0900 2327) if closing_paren_overflow_max_width {
233497ace (rChaser53 2019-10-24 22:16:56 +0900 2328) result.push(')');
233497ace (rChaser53 2019-10-24 22:16:56 +0900 2329) result.push_str(&indent.to_string_with_newline(context.config));
Version gate(s) added in #3731
4edc6f1a4 (Erik Johnston 2016-04-07 20:01:16 +0100 2366) }
4edc6f1a4 (Erik Johnston 2016-04-07 20:01:16 +0100 2367) };
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 2368) let ret_shape = if ret_should_indent {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 2369) if context.config.version() == Version::One
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 2370) || context.config.indent_style() == IndentStyle::Visual
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 2371) {
9c2b375ba (Caleb Cartwright 2019-09-23 19:25:19 -0500 2372) let indent = if param_str.is_empty() {
Version gate(s) added (#3731) / updated (#3803 some renaming)
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 2399) ret_shape
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 2400) }
1b0ae0048 (Marcus Klaas 2015-11-22 13:45:51 +0100 2401) } else {
f92f3e3bd (rchaser53 2019-01-27 14:33:03 +0900 2402) if context.config.version() == Version::Two {
9c2b375ba (Caleb Cartwright 2019-09-23 19:25:19 -0500 2403) if !param_str.is_empty() || !no_params_and_over_max_width {
f92f3e3bd (rchaser53 2019-01-27 14:33:03 +0900 2404) result.push(' ');
f92f3e3bd (rchaser53 2019-01-27 14:33:03 +0900 2405) }
Version gate(s) added #4503 commit 63f172d995e4419575907e84a9bd529d200d7b6c
08e282877 (Seiichi Uchida 2018-09-01 16:18:27 +0900 254) ChainItemKind::StructField(ident) => format!(".{}", rewrite_ident(context, ident)),
08e282877 (Seiichi Uchida 2018-09-01 16:18:27 +0900 255) ChainItemKind::TupleField(ident, nested) => format!(
08e282877 (Seiichi Uchida 2018-09-01 16:18:27 +0900 256) "{}.{}",
15854e5fd (Caleb Cartwright 2020-10-30 00:03:03 -0500 257) if nested && context.config.version() == Version::One {
15854e5fd (Caleb Cartwright 2020-10-30 00:03:03 -0500 258) " "
15854e5fd (Caleb Cartwright 2020-10-30 00:03:03 -0500 259) } else {
15854e5fd (Caleb Cartwright 2020-10-30 00:03:03 -0500 260) ""
Version gate added (#3250) / updated (#3756)
b73a602d6 (Stéphane Campinas 2018-12-14 09:48:20 +0100 425) } else {
b73a602d6 (Stéphane Campinas 2018-12-14 09:48:20 +0100 426) ""
deb329a6b (Seiichi Uchida 2019-08-28 20:50:41 +0900 427) };
deb329a6b (Seiichi Uchida 2019-08-28 20:50:41 +0900 428) let semicolon = if context.config.version() == Version::One {
deb329a6b (Seiichi Uchida 2019-08-28 20:50:41 +0900 429) ""
deb329a6b (Seiichi Uchida 2019-08-28 20:50:41 +0900 430) } else {
deb329a6b (Seiichi Uchida 2019-08-28 20:50:41 +0900 431) if semicolon_for_expr(context, body) {
Version gate added in #4994
fe05e8883 (rChaser53 2019-07-30 14:32:38 +0900 233) rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
ca023ba9b (Marcus Klaas 2015-10-17 15:56:53 +0200 234) }
428339fdc (Nick Cameron 2017-01-31 08:28:48 +1300 235) PatKind::Lit(ref expr) => expr.rewrite(context, shape),
f0f449d6e (Patrick Walton 2021-09-17 18:56:30 -0700 236) PatKind::Slice(ref slice_pat) if context.config.version() == Version::One => {
fe05e8883 (rChaser53 2019-07-30 14:32:38 +0900 237) let rw: Vec<String> = slice_pat
fe05e8883 (rChaser53 2019-07-30 14:32:38 +0900 238) .iter()
fe05e8883 (rChaser53 2019-07-30 14:32:38 +0900 239) .map(|p| {
Version gate added in #3631
1d19a08ed (Seiichi Uchida 2019-06-17 08:53:39 +0900 75)
1d19a08ed (Seiichi Uchida 2019-06-17 08:53:39 +0900 76) impl<'a> Rewrite for Stmt<'a> {
1d19a08ed (Seiichi Uchida 2019-06-17 08:53:39 +0900 77) fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
1d19a08ed (Seiichi Uchida 2019-06-17 08:53:39 +0900 78) let expr_type = if context.config.version() == Version::Two && self.is_last_expr() {
1d19a08ed (Seiichi Uchida 2019-06-17 08:53:39 +0900 79) ExprType::SubExpression
1d19a08ed (Seiichi Uchida 2019-06-17 08:53:39 +0900 80) } else {
1d19a08ed (Seiichi Uchida 2019-06-17 08:53:39 +0900 81) ExprType::Statement
Version gates both added in #3298
181ca427d (topecongiro 2019-01-27 21:01:12 +0900 469) Some(OverflowableItem::MacroArg(MacroArg::Expr(expr)))
181ca427d (topecongiro 2019-01-27 21:01:12 +0900 470) if !combine_arg_with_callee
181ca427d (topecongiro 2019-01-27 21:01:12 +0900 471) && is_method_call(expr)
181ca427d (topecongiro 2019-01-27 21:01:12 +0900 472) && self.context.config.version() == Version::Two =>
181ca427d (topecongiro 2019-01-27 21:01:12 +0900 473) {
181ca427d (topecongiro 2019-01-27 21:01:12 +0900 474) self.context.force_one_line_chain.replace(true);
181ca427d (topecongiro 2019-01-27 21:01:12 +0900 475) }
--
ae629abc4 (Seiichi Uchida 2018-03-07 15:40:52 +0900 659) );
ae629abc4 (Seiichi Uchida 2018-03-07 15:40:52 +0900 660) result.push_str(self.ident);
98c6f7b73 (Seiichi Uchida 2018-03-26 07:36:44 +0900 661) result.push_str(prefix);
5df0a1884 (topecongiro 2019-01-27 20:50:16 +0900 662) let force_single_line = if self.context.config.version() == Version::Two {
5df0a1884 (topecongiro 2019-01-27 20:50:16 +0900 663) !self.context.use_block_indent() || (is_extendable && extend_width <= shape.width)
5df0a1884 (topecongiro 2019-01-27 20:50:16 +0900 664) } else {
5df0a1884 (topecongiro 2019-01-27 20:50:16 +0900 665) // 2 = `()`
Version gates both added in #3731
01937061a (Marcus Klaas 2015-10-17 14:19:55 +0200 761) // FIXME: we drop any comments here, even though it's a silly place to put
01937061a (Marcus Klaas 2015-10-17 14:19:55 +0200 762) // comments.
589dabda2 (Kamal Marhubi 2016-03-01 17:27:19 -0500 763) ast::TyKind::Paren(ref ty) => {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 764) if context.config.version() == Version::One
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 765) || context.config.indent_style() == IndentStyle::Visual
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 766) {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 767) let budget = shape.width.checked_sub(2)?;
--
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 828) if it.is_empty() {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 829) return Some("impl".to_owned());
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 830) }
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 831) let rw = if context.config.version() == Version::One {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 832) it.rewrite(context, shape)
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 833) } else {
1643d726e (Seiichi Uchida 2019-08-16 11:15:28 +0900 834) join_bounds(context, shape, it, false)
Version gate added in #3334
7d9a2ef96 (rchaser53 2019-02-08 21:39:11 +0900 416) fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool {
383306e5f (Seiichi Uchida 2019-10-05 23:40:24 +0900 417) match expr.kind {
983a92c87 (Seiichi Uchida 2019-07-29 05:52:45 +0900 418) ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true,
7d9a2ef96 (rchaser53 2019-02-08 21:39:11 +0900 419) ast::ExprKind::Loop(..) if version == Version::Two => true,
c60416ed2 (Caleb Cartwright 2020-02-08 22:21:37 -0600 420) ast::ExprKind::AddrOf(_, _, ref expr)
34c249902 (topecongiro 2017-11-16 16:42:07 +0900 421) | ast::ExprKind::Box(ref expr)
34c249902 (topecongiro 2017-11-16 16:42:07 +0900 422) | ast::ExprKind::Try(ref expr)
Version gates added in backport PR #5384
795efb206 (Yacin Tmimi 2022-06-13 10:53:53 -0400 890) | (Super(ref a), Super(ref b))
795efb206 (Yacin Tmimi 2022-06-13 10:53:53 -0400 891) | (Crate(ref a), Crate(ref b)) => match (a, b) {
5ae94cc6b (Yacin Tmimi 2022-06-13 08:34:47 -0400 892) (Some(sa), Some(sb)) => {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 893) if self.version == Version::Two {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 894) sa.trim_start_matches("r#").cmp(sb.trim_start_matches("r#"))
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 895) } else {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 896) a.cmp(b)
--
5ae94cc6b (Yacin Tmimi 2022-06-13 08:34:47 -0400 900) },
795efb206 (Yacin Tmimi 2022-06-13 10:53:53 -0400 901) (Glob, Glob) => Ordering::Equal,
795efb206 (Yacin Tmimi 2022-06-13 10:53:53 -0400 902) (Ident(ref pia, ref aa), Ident(ref pib, ref ab)) => {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 903) let (ia, ib) = if self.version == Version::Two {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 904) (pia.trim_start_matches("r#"), pib.trim_start_matches("r#"))
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 905) } else {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 906) (pia.as_str(), pib.as_str())
--
5ae94cc6b (Yacin Tmimi 2022-06-13 08:34:47 -0400 926) (None, Some(_)) => Ordering::Less,
5ae94cc6b (Yacin Tmimi 2022-06-13 08:34:47 -0400 927) (Some(_), None) => Ordering::Greater,
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 928) (Some(aas), Some(abs)) => {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 929) if self.version == Version::Two {
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 930) aas.trim_start_matches("r#")
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 931) .cmp(abs.trim_start_matches("r#"))
e44380b34 (Yacin Tmimi 2022-06-13 11:36:20 -0400 932) } else {
--
01311c63e (Seiichi Uchida 2018-03-31 13:21:13 +0900 1246)
01311c63e (Seiichi Uchida 2018-03-31 13:21:13 +0900 1247) let mut parser = Parser {
01311c63e (Seiichi Uchida 2018-03-31 13:21:13 +0900 1248) input: s.chars().peekable(),
795efb206 (Yacin Tmimi 2022-06-13 10:53:53 -0400 1249) version: Version::One,
01311c63e (Seiichi Uchida 2018-03-31 13:21:13 +0900 1250) };
01311c63e (Seiichi Uchida 2018-03-31 13:21:13 +0900 1251) parser.parse_in_list()
01311c63e (Seiichi Uchida 2018-03-31 13:21:13 +0900 1252) }
Table of what I found above. Might be useful to track which examples we've already added.
Version Usage in src/visitor.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-Version Usage in src/utils.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1331585855None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1331592380Version Usage in src/missed_spans.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1315302533Version Usage in src/expr.rs
format_strings=false (default)
-- Examples added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1331628360Version Usage in src/items.rs
hard_tabs=true
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1305649570None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1305717684None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1321344498None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1345037570Version Usage in src/chains.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1322963218Version Usage in src/matches.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1345068602Version Usage in src/patterns.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1322955255Version Usage in src/stmt.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1345097702Version Usage in src/overflow.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1321354613None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1321519237Version Usage in src/types.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1321344498Version Usage in src/closures.rs
None
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1321330401Version Usage in src/imports.rs
reorder_imports=true (default)
-- Example added in https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1321035553reorder_imports=true
(default)Reference in codebase: impl Ord for UseSegment
use websocket::r#async::futures::Stream;
use websocket::client::ClientBuilder;
use websocket::result::WebSocketError;
use websocket::client::ClientBuilder;
use websocket::r#async::futures::Stream;
use websocket::result::WebSocketError;
loop
body.Reference in codebase: closures::is_block_closure_forced_inner
loop
s are written with a block closures.
fn main() {
thread::spawn(|| {
loop {
println!("iteration");
}
});
}
loop
s are not forced to be written in a block closures.
fn main() {
thread::spawn(|| loop {
println!("iteration");
});
}
Reference in codebase:
impl Rewrite for ast::Ty (ast::TyKindParen)
impl Rewrite for ast::Ty (ast::TyKindImplTrait)
impl Rewrite for ast::FnRetTy (ast::FnRetTy::Ty)
items::rewrite_fn_base
return type indent fn build_sorted_static_get_entry_names(
mut entries: Vec<(u8, &'static str)>,
) -> (
impl Fn(
AlphabeticalTraversal,
Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>,
) -> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+ Send
+ Sync
+ 'static
) {
}
fn build_sorted_static_get_entry_names(
mut entries: Vec<(u8, &'static str)>,
) -> (impl Fn(
AlphabeticalTraversal,
Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>,
) -> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+ Send
+ Sync
+ 'static) {
}
There was some version gates that were also associated with indent_style=Visual
that were added in #3731 so I thought it might be worth adding the version config in combination with indent_style=Visual
.
indent_style=Visual
)fn build_sorted_static_get_entry_names(
mut entries: Vec<(u8, &'static str)>)
-> (impl Fn(AlphabeticalTraversal,
Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>)
-> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+ Send
+ Sync
+ 'static) {
}
indent_style=Visual
)fn build_sorted_static_get_entry_names(
mut entries: Vec<(u8, &'static str)>)
-> (impl Fn(AlphabeticalTraversal,
Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>)
-> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+ Send
+ Sync
+ 'static) {
}
Reference in codebase: overflow::Context::try_overflow_last_item
fn main() {
assert!(
HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some()
);
assert(
HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some(),
);
}
fn main() {
assert!(HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some());
assert(
HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some(),
);
}
Reference in codebase: overflow::Context::rewrite_items
Overflow rules don't take macro context into account.
macro_rules! bar {
($m:ident) => {
$m!([
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,
]);
$m!([
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
]);
};
}
Overflow rules do take macro context into account.
macro_rules! bar {
($m:ident) => {
$m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,]);
$m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]);
};
}
Reference in codebase: impl Rewrite for Pat (PatKind::Slice)
Added in PR: https://github.com/rust-lang/rustfmt/pull/4994
fn main() {
let [
aaaaaaaaaaaaaaaaaaaaaaaaaa,
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
cccccccccccccccccccccccccc,
ddddddddddddddddddddddddd,
] = panic!();
}
fn main() {
let [aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccccc, ddddddddddddddddddddddddd] =
panic!();
}
Reference in codebase: impl Rewrite for ChainItem (ChainItemKind::TupleField)
No spaces added
fn main() {
let _ = ((1,),).0.0;
}
A space is added for the nested item access.
fn main() {
let _ = ((1,),).0 .0;
}
Reference in codebase:
macro_rules! moo {
() => {
bar! {
"
"
}
};
}
macro_rules! moo {
() => {
bar! {
"
"
}
};
}
Reference in codebase:
pub fn main() {
/* let s = String::from(
"
hello
world
",
); */
assert_eq!(s, "\nhello\nworld\n");
}
pub fn main() {
/* let s = String::from(
"
hello
world
",
); */
assert_eq!(s, "\nhello\nworld\n");
}
wrap_str
when each line ends with line continuation (\\
) and format_string=false
and Version=Two
.This version gate only seems to work in some contexts where a string literal is a subexpression of another expression.
Reference in codebase: expr::rewrite_string_lit
, which is only called in rewrite_literal
. Then rewirte_literal
is only called when rewriting ast::NestedMetaItem::Literal
and ast::MetaItemKind::NameValue
as well as when rewriting ast::ExprKind::Lit
Input:
// long string literal in attribute is formatted the same for `Version::One` and `Version::Two`.
#![attr(something = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")]
fn main() {
// long string literal in chains prevent formatting and are formatted the same for `Version::One` and `Version::Two`.
something.something(|| {
// ...
}).unwrap_or_else(|| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor innderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
}
// long string literal in conditionals will prevent formatting for `Version::One`.
fn main() {
let value = if x == "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." { 0 } else {10};
value
}
// long string literal in attribute is formatted the same for `Version::One` and `Version::Two`.
#![attr(
something = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
)]
fn main() {
// long string literal in chains prevent formatting and are formatted the same for `Version::One` and `Version::Two`.
something.something(|| {
// ...
}).unwrap_or_else(|| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
}
// long string literal in conditionals will prevent formatting for `Version::One`.
fn main() {
let value = if x
== "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
{
0
} else {
10
};
value
}
// long string literal in attribute is formatted the same for `Version::One` and `Version::Two`.
#![attr(
something = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
)]
fn main() {
// long string literal in chains prevent formatting and are formatted the same for `Version::One` and `Version::Two`.
something.something(|| {
// ...
}).unwrap_or_else(|| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor innderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
}
// long string literal in conditionals will prevent formatting for `Version::One`.
fn main() {
let value = if x == "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." { 0 } else {10};
value
}
[!NOTE] https://github.com/rust-lang/rustfmt/pull/6362 pushes those changes to
style_edition=2027
. They're now documented here: https://github.com/rust-lang/rustfmt/issues/6371#issuecomment-2427434682
->
instead of breaking between ()
for zero argument functionsReference in codebase: items::rewrite_fn_base
pub fn parse_conditional<'a, I: 'a>()
-> impl Parser<Input = I, Output = Expr, PartialState = ()> + 'a
where
I: Stream<Item = char>,
{
}
pub fn parse_conditional<'a, I: 'a>(
) -> impl Parser<Input = I, Output = Expr, PartialState = ()> + 'a
where
I: Stream<Item = char>,
{
}
Reference in codebase: matches::rewrite_match_body
match arm 0
Includes a trailing semicolon.
fn foo() {
match 0 {
0 => {
return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
}
1 => {
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
}
_ => "",
};
}
match arm 0
does not includes a trailing semicolon.
fn foo() {
match 0 {
0 => {
return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
}
1 => {
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
}
_ => "",
};
}
Reference in codebase: impl<'a> Rewrite for Stmt<'a>
fn main() {
let toto = || {
if true { 42 } else { 24 }
};
{ T }
}
fn main() {
let toto = || {
if true {
42
} else {
24
}
};
{
T
}
}
Reference in codebase: types::join_bounds_inner
pub trait PrettyPrinter<'tcx>:
Printer<
'tcx,
Error = fmt::Error,
Path = Self,
Region = Self,
Type = Self,
DynExistential = Self,
Const = Self,
>
{
//
}
pub trait PrettyPrinter<'tcx>:
Printer<
'tcx,
Error = fmt::Error,
Path = Self,
Region = Self,
Type = Self,
DynExistential = Self,
Const = Self,
> + fmt::Write
{
//
}
pub trait PrettyPrinter<'tcx>:
Printer<
'tcx,
Error = fmt::Error,
Path = Self,
Region = Self,
Type = Self,
DynExistential = Self,
Const = Self,
>
{
//
}
pub trait PrettyPrinter<'tcx>:
Printer<
'tcx,
Error = fmt::Error,
Path = Self,
Region = Self,
Type = Self,
DynExistential = Self,
Const = Self,
> + fmt::Write
{
//
}
TODO: Document https://github.com/rust-lang/rustfmt/pull/5867
TODO: Document #5902
TODO: Ensure #4800 is covered somewhere in a human-readable manner
log
crate.Reference in codebase: overflow::OverflowableItem::special_cases
Added in PR #5989
All of the macros are formatted consistently.
fn main() {
trace!(
"get some longer length in here yes yes {} {}",
"hello", "world"
);
debug!(
"get some longer length in here yes yes {} {}",
"hello", "world"
);
}
The trace!
macro is not special cased.
fn main() {
trace!(
"get some longer length in here yes yes {} {}",
"hello",
"world"
);
debug!(
"get some longer length in here yes yes {} {}",
"hello", "world"
);
}
TODO: Document https://github.com/rust-lang/rustfmt/pull/6000
TODO: Document https://github.com/rust-lang/rustfmt/pull/5582
TODO: Document #6092
TODO: Document #6147 / #6148
Note to future selves that https://github.com/rust-lang/rustfmt/issues/5577#issuecomment-1345037570 is the one the style team decided we didn't want to keep for 2024 style edition
Edit(ytmimi): https://github.com/rust-lang/rustfmt/pull/6362 pushes those changes to style_edition=2027
.
TODO: Document #6284 (version sort for imports)
To the best of my knowledge we don't have this info captured anywhere in a single place, but it's something we should have. Unfortunately I think the only way to pull this together will be scanning through the source code and trying to reproduce associated snippets with respective constructs.
@ytmimi - if you have bandwidth and are willing to look into it that'd be most appreciated, but no worries if not