Hi again. (FYI This builds on the branch for #39, so I'll just rebase this onto main
once that's merged.)
This adds:
1. Initial support for loops: @for
, @foreach
, @forelse
and @while
.
OK, this is great and was easy, but to be clear, it takes the cowards way out. Instead of adding AST nodes/type/etc for the various loops, I am relying on string manipulation w/i DirectiveNode
. This seemed like the easiest way forward, and also made # 2 trivial. For example, w/o this change, @for( $i = 1; $i++, $i < 5 )
would be handed off to prettier as <?php $i = 1; $i++, $i < 5;
and @foreach ( $foo as $bar )
would be handed off to prettier as <?php $foo as bar;
. The former is always broken onto multiple lines (b/c it just looks like multiple statements on 1 line) while the latter is invalid PHP, so is never actually rerformatted. With this change, these are instead handed off to prettier as just <?php for ($i = 1; $i++, $i < 5) {}
and <?php foreach ( $foo as $bar ) {}
, and then the for/foreach syntax is stripped off again before we put it back into the Blade.
Note that, when formatting loops, I have opted to put a space between the directive name and the opening paren. This is easy to remove if desired, but it matches how prettier formats loops. For example @while (true)
vs @while(true)
. Loops are the only directives have that space.
Main caveat w/ loops: @empty
doesn't work. This is because forelse
is just a special foreach
loop that allows the @empty
case/directive, but @empty($var)
is also valid directive in it's own right. In this PR (and FWIW on main
, I think) the @empty
directive w/o any params totally breaks the formatter. This PR does not solve this. A @forelse
loop w/o an @empty
directive will format just fine, but any blade w/ an @empty
directive w/o any arguments will halt formatting completely.
More context, @empty
is one of a handful of special directives that have multiple forms based on their context:
@empty
is a paired directive if written w/ parameters, or child directive of @forelse
if written w/o
@slot
and @section
are paired if written w/ 1 parameter, but are solo directives if written w/ 2 params
In this regard, I kind of feel like this PR is "correct" in that it allows/unlocks formatting of loops, and that handling of these whacky directives is out of scope here and might be best left to someone w/ more knowledge of chevrotain than I. On the other hand, it's hard to say we "support" forelse
w/o supporting empty
.
2. Changes how the code w/i directive arguments is formatted.
Most directives only take a single parameter, and we can get by pretty easily by treating that param as regular php. Eg @method($foo)
works just fine if we hand the params to prettier as <?php $foo;
. However, many directives take several parameters, and this approach doesn't work on those: @inject($foo, $bar)
is currently handed to prettier as <?php $foo, $bar;
, which is invalid PHP, which means we leave it as is and never format it.
My solution is to follow the approach of # 1 and hand all directive parameters to prettier as if they were params to a function call, then remove the fake function call before putting them back into blade. So the previous examples will be handed to prettier as <?php a($foo);
and <?php a($foo, $bar);
, resp. In all the cases I threw at it, this worked correctly, though I wonder if there's some edge cases I haven't thought of.
3. Fixes an edge case where echo braces appear at the end of a line.
No idea why this was needed; the existing regexps should have allowed for option line breaks, but the regression fixture I added would only pass if the those optional break were removed. This was uncovered while working on # 1, but isn't directly related.
4. Fixes an edge (??) case where comments were having extra whitespace added to them.
Totally unrelated, but I noticed that {{-- foo --}}
was sometimes being reformatted as {{-- foo --}}
. This fix prevents that.
5. Adds a micro-optimization that prevents us from even trying to format empty strings because ... there's nothing to format!
Not much to this. I just noticed that there were a number of times when we're asking prettier to format an empty string (ie <?php ;
).
As always, I'm happy for any feedback or comments you may have. Thank you!