@@ -123,25 +123,60 @@ impl RCallLikeArguments {
123
123
///
124
124
/// Example:
125
125
///
126
+ /// An inline function without braces is an example where "most flat" is considered.
127
+ /// We consider this as groupable because it is possible that a long function body
128
+ /// or long function signature can cause a break, which may benefit from the middle
129
+ /// variant before expanding all the way to the most expanded variant.
130
+ ///
126
131
/// ```r
127
- /// # NOTE: Not currently possible, as the `{}` always force a break right now,
128
- /// # but this would be an example if `{}` didn't force a break.
129
- /// map(xs, function(x) {})
132
+ /// # Most flat wins
133
+ /// map(xs, function(x) x + 1)
134
+ ///
135
+ /// # Middle variant wins
136
+ /// map(xs, function(x) x + a_really_long_thing_here + a_really_long_thing_there)
137
+ /// # ->
138
+ /// map(xs, function(x) {
139
+ /// x + a_really_long_thing_here + a_really_long_thing_there
140
+ /// })
141
+ ///
142
+ /// # Most expanded wins (middle variant wouldn't fit within line length)
143
+ /// map(xs_are_extremely_long_too, function(this_argument_is_really_long, option = "so is this") this_argument_is_really_long)
144
+ /// # ->
145
+ /// map(
146
+ /// xs_are_extremely_long_too,
147
+ /// function(this_argument_is_really_long, option = "so is this") {
148
+ /// this_argument_is_really_long
149
+ /// }
150
+ /// )
130
151
/// ```
131
152
///
132
153
/// This variant is removed from the set if we detect that the grouped argument
133
154
/// contains a forced break in the body (if a forced break is found in the
134
155
/// parameters, we bail entirely and use the most expanded form, as noted
135
156
/// at the beginning of this documentation page).
136
157
///
137
- /// Note that because `{}` currently unconditionally force a break, and because
138
- /// we only go down this path when we have a `{}` to begin with, that means that
139
- /// currently the most flat variant is always removed. There is an
140
- /// `unreachable!()` in the code to assert this. We can't simply remove the
141
- /// `most_flat` code path though, because it is also where we detect if a
142
- /// parameter forces a break, triggering one of our early exists. Additionally,
143
- /// in the future we may allow `{}` to not force a break, meaning this variant
144
- /// may come back into play.
158
+ /// ```r
159
+ /// # Forced break in the body
160
+ /// map(xs, function(x) {
161
+ /// x
162
+ /// })
163
+ ///
164
+ /// # This is a forced break in the body too, and triggers autobracing and
165
+ /// # results in the middle variant winning
166
+ /// map(xs, function(x)
167
+ /// x)
168
+ /// ```
169
+ ///
170
+ /// Note that because `{}` currently unconditionally force a break, that means that
171
+ /// currently the most flat variant is always removed when `{}` are present. In the
172
+ /// future we will make empty `{}` never break and we will declare cases of empty
173
+ /// `{}` as not groupable, so it won't go through this best fitting process at all.
174
+ ///
175
+ /// ```r
176
+ /// # NOTE: Currently considered groupable, but the `{}` currently unconditionally
177
+ /// # force a break, so the `most_flat` variant is always removed
178
+ /// map(xs, function(x) {})
179
+ /// ```
145
180
///
146
181
/// ```r
147
182
/// # NOTE: We explicitly disallow curly-curly as a groupable argument,
@@ -297,7 +332,7 @@ impl RCallLikeArguments {
297
332
298
333
// Write the most flat variant with the first or last argument grouped
299
334
// (but not forcibly expanded)
300
- let _most_flat = {
335
+ let most_flat = {
301
336
let snapshot = f. state_snapshot ( ) ;
302
337
let mut buffer = VecBuffer :: new ( f. state_mut ( ) ) ;
303
338
buffer. write_element ( FormatElement :: Tag ( Tag :: StartEntry ) ) ?;
@@ -375,14 +410,15 @@ impl RCallLikeArguments {
375
410
buffer. into_vec ( ) . into_boxed_slice ( )
376
411
} ;
377
412
378
- // If the grouped content breaks, then we can skip the most_flat variant,
379
- // since we already know that it won't be fitting on a single line.
380
413
let variants = if grouped_breaks {
414
+ // If the grouped content breaks, then we can skip the most_flat variant,
415
+ // since we already know that it won't be fitting on a single line. We can
416
+ // also go ahead and signal that we will be expanding.
381
417
write ! ( f, [ expand_parent( ) ] ) ?;
382
418
vec ! [ middle_variant, most_expanded. into_boxed_slice( ) ]
383
419
} else {
384
- unreachable ! ( "`grouped_breaks` is currently always `true`." ) ;
385
- // vec![most_flat, middle_variant, most_expanded.into_boxed_slice()]
420
+ // Otherwise we best fit between all variants
421
+ vec ! [ most_flat, middle_variant, most_expanded. into_boxed_slice( ) ]
386
422
} ;
387
423
388
424
// SAFETY: Safe because variants is guaranteed to contain >=2 entries:
@@ -1087,7 +1123,7 @@ fn argument_is_groupable(argument: &AnyRExpression) -> SyntaxResult<bool> {
1087
1123
// })
1088
1124
// ```
1089
1125
//
1090
- // Empty braces always expand, so they benefit from grouping
1126
+ // Empty braces currently always expand, so they benefit from grouping
1091
1127
//
1092
1128
// ```r
1093
1129
// with(data, {
@@ -1098,7 +1134,7 @@ fn argument_is_groupable(argument: &AnyRExpression) -> SyntaxResult<bool> {
1098
1134
//
1099
1135
// ```r
1100
1136
// with(data, {
1101
- // // comment
1137
+ // # comment
1102
1138
// })
1103
1139
// ```
1104
1140
//
@@ -1119,15 +1155,91 @@ fn argument_is_groupable(argument: &AnyRExpression) -> SyntaxResult<bool> {
1119
1155
// ```
1120
1156
RBracedExpressions ( node) => as_curly_curly ( node) . is_none ( ) ,
1121
1157
1158
+ // Currently, every kind of function definition can benefit from grouping.
1159
+ //
1160
+ // - If the body has `{}` and is not empty, the braces will be expanded across
1161
+ // multiple lines, so it can benefit from grouping.
1162
+ //
1163
+ // - If the body does not have `{}`, we may keep the function definition
1164
+ // completely flat on one line, or we may expand it over multiple lines if
1165
+ // it exceeds the line length or a persistent line break forces a break. If
1166
+ // it were to break, it would benefit from grouping.
1167
+ //
1168
+ // - NOTE: If the body has `{}` and is empty (including no comments), then
1169
+ // currently those are always expanded anyways, so it can benefit from grouping.
1170
+ // In the future we will force empty `{}` to not expand, and when that happens
1171
+ // we should return `false` from here to signal that it can't benefit from
1172
+ // grouping (use the same rule as `RBracedExpressions` above, but applied to
1173
+ // the `node.body()`).
1174
+ //
1175
+ // Here are some examples:
1176
+ //
1177
+ // Trailing function definition with braces is the classic example of something
1178
+ // that benefits from grouping
1179
+ //
1122
1180
// ```r
1123
- // map(a , function(x) {
1181
+ // map(xs , function(x) {
1124
1182
// x
1125
1183
// })
1126
1184
// ```
1127
- RFunctionDefinition ( node) => {
1128
- let body = node. body ( ) ?;
1129
- matches ! ( & body, AnyRExpression :: RBracedExpressions ( _) )
1130
- }
1185
+ //
1186
+ // When the braces are empty, it still benefits from grouping right now because
1187
+ // we currently always expand the braces.
1188
+ //
1189
+ // ```r
1190
+ // map(xs, function(x) {
1191
+ // })
1192
+ // ```
1193
+ //
1194
+ // With a dangling comment in empty braces, we always benefit from grouping
1195
+ //
1196
+ // ```r
1197
+ // map(xs, function(x) {
1198
+ // # comment
1199
+ // })
1200
+ // ```
1201
+ //
1202
+ // Long function definition that would be split over multiple lines, triggering
1203
+ // autobracing, and would benefit from grouping
1204
+ //
1205
+ // ```r
1206
+ // map(xs, function(x) x + a_really_really_long_name + another_really_long_name)
1207
+ //
1208
+ // # Becomes:
1209
+ // map(xs, function(x) {
1210
+ // x + a_really_really_long_name + another_really_long_name
1211
+ // })
1212
+ //
1213
+ // # Which is preferred over fully expanding:
1214
+ // map(
1215
+ // xs,
1216
+ // function(x) {
1217
+ // x + a_really_really_long_name + another_really_long_name
1218
+ // }
1219
+ // )
1220
+ // ```
1221
+ //
1222
+ // Line break in the function definition body, triggering autobracing, and would
1223
+ // benefit from grouping
1224
+ //
1225
+ // ```r
1226
+ // map(xs, function(x)
1227
+ // x + 1)
1228
+ //
1229
+ // # Becomes:
1230
+ // map(xs, function(x) {
1231
+ // x + 1
1232
+ // })
1233
+ //
1234
+ // # Which is preferred over fully expanding:
1235
+ // map(
1236
+ // xs,
1237
+ // function(x) {
1238
+ // x + 1
1239
+ // }
1240
+ // )
1241
+ // ```
1242
+ RFunctionDefinition ( _) => true ,
1131
1243
1132
1244
// Nothing else benefits from grouping
1133
1245
_ => false ,
0 commit comments