I have one snapshot test failing on re-formatting and I honestly just don't understand the progression. I've updated the output of the case to be helpful, but here are the original/formatted/reformatted asts (with the source code below). I've lined up the relevant nodes with each other
Screenshot 2025-01-10 at 9.28.32 AM.png
For those like @Joshua Warner or @Sam Mohr who are familiar with this where do you think this SpaceAfter comes from around the PncApply in the reformatted AST?
Can you paste the source code?
Oh, I see it
In the bottom of the image
Yeah so the extra newline coming in is what is perplexing, and what makes the formatting so terrible
Yep, the formatting that comes as "step 2" here makes sense to me
The re-formatting is weird indeed
But I think it comes from how we format patterns
But I think it's the parsing of the formatted AST
Or I guess not
If you look at the docs for Str.walkUtf8, whenever we have a multiline function type, we make sure the arrow is indented
It would be the formatted of the formatted ast
Which makes sense for types
But this is a value, right?
This is a value, you can see the top level node is an Expr
So either our formatting for PNC patterns has some artifacts from formatting multiline spaced patterns
So it's an Expr::Closure, and the first list is a [Pattern<'_>]
I'll look at the code in a few minutes
It's on my branch, maybe I did something goofy aligning it with Expr formatting
Trying to finish up this invalid ident warning code
No worries. I have to go to work and write and test some Java.
Shed a tear for me
Historically this sort of thing happened when is_multiline
or one of the matches in the outer scopes differed slightly in details from how the child is actually formatted (e.g. adding/removing parens).
Now, these bugs have generally been pushed into <>.to_node()
, expr_lift_spaces
, pattern_lift_spaces
, etc. in such a way that those functions are not sufficiently "normalizing".
In the initial formatted version (the middle column of your screenshot), it looks to me like the closure is for some reason incorrectly thinking that the arg list is _not_ multiline - and then it turning out it actually is when formatted.
I think this is the issue:
buf.push('\\');
let arguments_are_multiline = loc_patterns
.iter()
.any(|loc_pattern| loc_pattern.is_multiline());
// If the arguments are multiline, go down a line and indent.
let indent = if arguments_are_multiline {
indent + INDENT
} else {
indent
};
let mut first = true;
for loc_pattern in loc_patterns.iter() {
if !first {
buf.indent(indent);
if arguments_are_multiline {
buf.push(',');
buf.newline();
} else {
buf.push_str(",");
buf.spaces(1);
}
}
first = false;
let arg = pattern_lift_spaces(buf.text.bump(), &loc_pattern.value);
if !arg.before.is_empty() {
fmt_comments_only(buf, arg.before.iter(), NewlineAt::Bottom, indent)
}
arg.item
.format_with_options(buf, Parens::InClosurePattern, Newlines::No, indent);
if !arg.after.is_empty() {
if starts_with_inline_comment(arg.after.iter()) {
buf.spaces(1);
}
fmt_comments_only(buf, arg.after.iter(), NewlineAt::Bottom, indent)
}
}
The comment doesn't tell the truth
Nor is it correct - in my opinion
We do not go down a line and indent. We just increase the indent
And I'm not sure we should do that at all for a single multi-line pattern
I think I'm going to say "If arguments_are_multiline AND there are more than 1 argument - actually go down a line and indent with an increased indent. otherwise keep the same indent and have the arrow be on the same line as the end of the arg pattern.
Does this sound correct?
That sounds correct, but I'd have to see examples get formatted in the PR
So:
\
SomeThing({
with: 'multilining',
more: 'args',
}),
foo
-> ....
But:
\L(
z, # This is multiline
) -> ....
That works for now. I don't like the \
being on a different line, but we're killing it soon, so :shrug:
But maybe we also want:
\foo, L(
z, # This is multiline
) -> ....
Yeah
|
SomeThing({
with: 'multilining',
more: 'args',
}),
foo
| ....
looks better I guess?
Not great, but better
I don't think we can do better than that, though, so it's good
So I think the rule is if there is a multiline arg _before the last arg_, then we do the whole outdenting thing
Hmmm...thinking. That would mean with ||
syntax:
|foo, SomeThing(
z, # This is multiline
) | ....
Is that better than:
|
foo,
SomeThing(
z, # This is multiline
),
| ....
?
I like symmetry, so I vote 2
Maybe that's just me
Function args have different aesthetic rules than function bodies
I agree that comment doesn't match the code, and that the current formatting is not ideal - but I'm not sure that's the cause of the bug you're looking at
Ok, So for now I'll do if more than one arg do the outdent. But with ||
I'll go back to doing it for any number of args that are multiline
Joshua Warner said:
I agree that comment doesn't match the code, and that the current formatting is not ideal - but I'm not sure that's the cause of the bug you're looking at
We'll find out soon
But I have some other things to do first
Last updated: Jul 06 2025 at 12:14 UTC