Skip to content

Commit d23fbca

Browse files
authored
Support anonymous block arguments (#471)
* Support anonymous blocks on method definitions * Format anon block args in sends * Add a fixture for anon block args * Format
1 parent 87d948a commit d23fbca

File tree

4 files changed

+56
-27
lines changed

4 files changed

+56
-27
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def foo(a, b, &)
2+
bar a, b, &
3+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def foo(a, b, &)
2+
bar(a, b, &)
3+
end

librubyfmt/src/format.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,10 @@ pub fn format_block_arg(
251251
Box::new(|ps| {
252252
ps.emit_soft_indent();
253253
ps.emit_ident("&".to_string());
254-
bind_ident(ps, &ba.1);
255-
format_ident(ps, ba.1);
254+
if let Some(ident) = ba.1 {
255+
bind_ident(ps, &ident);
256+
format_ident(ps, ident);
257+
}
256258
}),
257259
);
258260

@@ -2067,10 +2069,11 @@ pub fn format_next(ps: &mut dyn ConcreteParserState, next: Next) {
20672069
}
20682070
}
20692071
ArgsAddBlockOrExpressionList::ArgsAddBlock(aab) => match aab.2 {
2070-
ToProcExpr::Present(_) => {
2072+
Some(ToProcExpr::Present(_)) => {
20712073
panic!("got a block in a next, should be impossible");
20722074
}
2073-
ToProcExpr::NotPresent(_) => {
2075+
None => unreachable!("got an anonymous block in a next, should be impossible"),
2076+
Some(ToProcExpr::NotPresent(_)) => {
20742077
ps.emit_space();
20752078
format_list_like_thing(
20762079
ps,
@@ -3103,7 +3106,7 @@ pub fn format_keyword(
31033106
ArgsAddBlockInner::ArgsAddStarOrExpressionListOrArgsForward(
31043107
ArgsAddStarOrExpressionListOrArgsForward::ExpressionList(vec![]),
31053108
),
3106-
ToProcExpr::NotPresent(false),
3109+
Some(ToProcExpr::NotPresent(false)),
31073110
start_end.clone(),
31083111
)
31093112
}
@@ -3599,6 +3602,10 @@ pub fn format_to_proc(ps: &mut dyn ConcreteParserState, e: Box<Expression>) {
35993602
ps.with_start_of_line(false, Box::new(|ps| format_expression(ps, *e)));
36003603
}
36013604

3605+
pub fn format_anon_block_arg(ps: &mut dyn ConcreteParserState) {
3606+
ps.emit_ident("&".to_string());
3607+
}
3608+
36023609
pub fn format_zsuper(ps: &mut dyn ConcreteParserState, start_end: StartEnd) {
36033610
format_keyword(
36043611
ps,
@@ -3764,6 +3771,7 @@ pub fn format_expression(ps: &mut dyn ConcreteParserState, expression: Expressio
37643771
Expression::OpAssign(op) => format_opassign(ps, op),
37653772
Expression::Unless(u) => format_unless(ps, u),
37663773
Expression::ToProc(ToProc(_, e)) => format_to_proc(ps, e),
3774+
Expression::AnonBlockArg(AnonBlockArg(_, _)) => format_anon_block_arg(ps),
37673775
Expression::ZSuper(ZSuper(_, se)) => format_zsuper(ps, se),
37683776
Expression::Yield0(Yield0(_, se)) => format_yield0(ps, se),
37693777
Expression::Return(ret) => format_return(ps, ret),

librubyfmt/src/ripper_tree_types.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,17 @@ def_tag!(undeserializable, "oiqjweoifjqwoeifjwqoiefjqwoiej");
7979
#[derive(Deserialize, Debug, Clone)]
8080
pub struct ToProc(pub undeserializable, pub Box<Expression>);
8181

82+
def_tag!(
83+
undeserializable_anon_block_arg,
84+
"oiqjweoifjqwoeifjwqoiefjqwoiej_anon_block_arg"
85+
);
86+
#[derive(Deserialize, Debug, Clone)]
87+
pub struct AnonBlockArg(pub undeserializable_anon_block_arg, pub u64);
88+
8289
#[derive(RipperDeserialize, Debug, Clone)]
8390
pub enum Expression {
8491
ToProc(ToProc),
92+
AnonBlockArg(AnonBlockArg),
8593
Class(Class),
8694
If(If),
8795
Unary(Unary),
@@ -296,6 +304,9 @@ impl Expression {
296304
// Arefs only have an accurate closing line and not a starting line,
297305
// so don't use it here
298306
Expression::Aref(Aref(_, expr, ..)) => expr.start_line(),
307+
// Anonymous block arguments have no location information, so we use the end of the
308+
// original enclosing `args_add_block` node.
309+
Expression::AnonBlockArg(AnonBlockArg(.., line_start)) => Some(*line_start),
299310
}
300311
}
301312
}
@@ -1298,7 +1309,7 @@ pub struct KwRestParam(pub kw_rest_param_tag, pub Option<Ident>);
12981309

12991310
def_tag!(blockarg_tag, "blockarg");
13001311
#[derive(Deserialize, Debug, Clone)]
1301-
pub struct BlockArg(pub blockarg_tag, pub Ident);
1312+
pub struct BlockArg(pub blockarg_tag, pub Option<Ident>);
13021313

13031314
#[derive(Deserialize, Debug, Clone)]
13041315
pub struct LineCol(pub LineNumber, pub u64);
@@ -1350,26 +1361,30 @@ pub fn normalize_args_add_block_or_expression_list(
13501361
pub fn normalize_args_add_block(aab: ArgsAddBlock) -> ArgsAddStarOrExpressionListOrArgsForward {
13511362
// .1 is expression list
13521363
// .2 is block
1353-
match aab.2 {
1354-
ToProcExpr::NotPresent(_) => (aab.1).into_args_add_star_or_expression_list(),
1355-
ToProcExpr::Present(e) => {
1356-
let trailing_expr_as_vec = vec![Expression::ToProc(ToProc(undeserializable, e))];
1357-
1358-
match (aab.1).into_args_add_star_or_expression_list() {
1359-
ArgsAddStarOrExpressionListOrArgsForward::ExpressionList(items) => {
1360-
ArgsAddStarOrExpressionListOrArgsForward::ExpressionList(
1361-
vec![items, trailing_expr_as_vec].concat(),
1362-
)
1363-
}
1364-
ArgsAddStarOrExpressionListOrArgsForward::ArgsAddStar(aas) => {
1365-
let mut new_aas = aas;
1366-
new_aas.3 = vec![new_aas.3, trailing_expr_as_vec].concat();
1367-
ArgsAddStarOrExpressionListOrArgsForward::ArgsAddStar(new_aas)
1368-
}
1369-
ArgsAddStarOrExpressionListOrArgsForward::ArgsForward(af) => {
1370-
ArgsAddStarOrExpressionListOrArgsForward::ArgsForward(af)
1371-
}
1372-
}
1364+
1365+
let trailing_expr = match aab.2 {
1366+
Some(ToProcExpr::NotPresent(_)) => {
1367+
return (aab.1).into_args_add_star_or_expression_list();
1368+
}
1369+
Some(ToProcExpr::Present(e)) => Expression::ToProc(ToProc(undeserializable, e)),
1370+
// anonymous block
1371+
None => Expression::AnonBlockArg(AnonBlockArg(
1372+
undeserializable_anon_block_arg,
1373+
aab.3.end_line(),
1374+
)),
1375+
};
1376+
1377+
match (aab.1).into_args_add_star_or_expression_list() {
1378+
ArgsAddStarOrExpressionListOrArgsForward::ExpressionList(mut items) => {
1379+
items.push(trailing_expr);
1380+
ArgsAddStarOrExpressionListOrArgsForward::ExpressionList(items)
1381+
}
1382+
ArgsAddStarOrExpressionListOrArgsForward::ArgsAddStar(mut aas) => {
1383+
aas.3.push(trailing_expr);
1384+
ArgsAddStarOrExpressionListOrArgsForward::ArgsAddStar(aas)
1385+
}
1386+
ArgsAddStarOrExpressionListOrArgsForward::ArgsForward(af) => {
1387+
ArgsAddStarOrExpressionListOrArgsForward::ArgsForward(af)
13731388
}
13741389
}
13751390
}
@@ -1420,7 +1435,7 @@ def_tag!(args_add_block_tag, "args_add_block");
14201435
pub struct ArgsAddBlock(
14211436
pub args_add_block_tag,
14221437
pub ArgsAddBlockInner,
1423-
pub ToProcExpr,
1438+
pub Option<ToProcExpr>,
14241439
pub StartEnd,
14251440
);
14261441

0 commit comments

Comments
 (0)