Repository: shufo/blade-formatter (ts)

Issue:
[Bug]: @php blocks handled differently when nested in @if blocks
### Description

Please reference https://github.com/shufo/blade-formatter/pull/909#issuecomment-1962253902

Here I show a screenshot where the `@php` block is severely wrapped but another block below is unaffected. I had only noticed the changed after upgrading from 1.32 and believe it is a difference due to the bugfix in 1.34.1. 



### Expected Behavior

But I am confused now...I thought the line length might already ignore the indentation level. Apparently not. I guess it was not getting wrapped, though I don't know why the constant of printWidth wasn't working when I had 120 set for wrap length anyway.

### Actual Behavior

Is the length of the wrap always including the indentation space? Is there a way to exempt indentation?

Is the difference in `@php` block formatting expected when nested in an `@if` block? The above section wraps after an `=` but the lower section does not.

### Additional Context

v1.41.0
[Formatting Bug]: issues formatting indented @php blocks following #909 and v1.41.0
### Version

1.41.0

### Template before formatting

```blade
@php
    if (1) {
        if (1) {
            if (1) {
                if (1) {
                    if (1) {
                        if (1) {
                            $percent =
                                $item['historical'] ?? null
                                    ? round(
                                        (100 *
                                            ($item['today'] -
                                                $item['historical'])) /
                                            $item['historical'],
                                    )
                                    : null;

                            $color = $percent < 0 ? '#8b0000' : '#006400';
                        }
                    }
                }
            }
        }
    }
@endphp

<div>
    <div>
        <div>
            <div>
                <div>
                    <div>
                        @php
                            $percent =
                                $item['historical'] ?? null
                                    ? round(
                                        (100 *
                                            ($item['today'] -
                                                $item['historical'])) /
                                            $item['historical'],
                                    )
                                    : null;

                            $color = $percent < 0 ? '#8b0000' : '#006400';
                        @endphp
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
```


### Template after formatting

```blade
@php
    if (1) {
        if (1) {
            if (1) {
                if (1) {
                    if (1) {
                        if (1) {
                            $percent =
                                $item['historical'] ?? null
                                    ? round(
                                        (100 *
                                            ($item['today'] -
                                                $item['historical'])) /
                                            $item['historical'],
                                    )
                                    : null;

                            $color = $percent < 0 ? '#8b0000' : '#006400';
                        }
                    }
                }
            }
        }
    }
@endphp

<div>
    <div>
        <div>
            <div>
                <div>
                    <div>
                        @php
                            $percent =
                                $item[
                                    'historical'
                                ] ??
                                null
                                    ? round(
                                        (100 *
                                            ($item[
                                                'today'
                                            ] -
                                                $item[
                                                    'historical'
                                                ])) /
                                            $item[
                                                'historical'
                                            ],
                                    )
                                    : null;

                            $color =
                                $percent <
                                0
                                    ? '#8b0000'
                                    : '#006400';
                        @endphp
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
```


### Expected Behaviour

This code was reported by @calebdw at https://github.com/shufo/blade-formatter/pull/909#issuecomment-1961581690, and I've reproduced it here.

The PHP code in these blocks is indented to the same level and I would expect it to be formatted identically. In particular, the second statement (the ternary) fits into 79 chars, including indentation, and it should be left on a single line.

I can reproduce 1-token-per-line wrapping that @calebdw is seeing, but only after smashing that PHP into so many `if`s that every line exceeds the wrap limit (see below). This strongly suggests that we're telling prettier to format these to the wrong `printWidth`, because it's treating everyline line it's already exceeded the print width.

I can look into this, but it will be a few days.

**Reproduction snippet with extreme wrapping**
```
@php
    if (1) {
        if (1) {
            if (1) {
                if (1) {
                    if (1) {
                        if (1) {
                            if (1) {
                                if (1) {
                                    if (1) {
                                        if (1) {
                                            if (1) {
                                                if (1) {
                                                    if (1) {
                                                        if (1) {
                                                            if (1) {
                                                                if (1) {
                                                                    if (1) {
                                                                        $percent =
                                                                            $item[
                                                                                'historical'
                                                                            ] ??
                                                                            null
                                                                                ? round(
                                                                                    (100 *
                                                                                        ($item[
                                                                                            'today'
                                                                                        ] -
                                                                                            $item[
                                                                                                'historical'
                                                                                            ])) /
                                                                                        $item[
                                                                                            'historical'
                                                                                        ],
                                                                                )
                                                                                : null;

                                                                        $color =
                                                                            $percent <
                                                                            0
                                                                                ? '#8b0000'
                                                                                : '#006400';
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
@endphp
```


### Relevant log output

_No response_

Pull request:
fix(formatter): correct indent level for raw @php blocks (close #915, #914)
## Description
When implementing #909, I misunderstood what `indent.amount` represents. I thought it was the number of indent levels, but it's actually the number of indent characters. This corrects that behavior and should improve the formatting of deeply (and not-so-deeply) indented `@php` blocks.

## Related Issue
Fixes #914 and #915

## Motivation and Context
See #915

## How Has This Been Tested?
I added a test, and ran it on several templates.

## Screenshots (if appropriate):
With this change, the code from #915 is formatted as expected: both PHP blocks are formatted identically.
```
@php
    if (1) {
        if (1) {
            if (1) {
                if (1) {
                    if (1) {
                        if (1) {
                            $percent =
                                $item['historical'] ?? null
                                    ? round(
                                        (100 *
                                            ($item['today'] -
                                                $item['historical'])) /
                                            $item['historical'],
                                    )
                                    : null;

                            $color = $percent < 0 ? '#8b0000' : '#006400';
                        }
                    }
                }
            }
        }
    }
@endphp

<div>
    <div>
        <div>
            <div>
                <div>
                    <div>
                        @php
                            $percent =
                                $item['historical'] ?? null
                                    ? round(
                                        (100 *
                                            ($item['today'] -
                                                $item['historical'])) /
                                            $item['historical'],
                                    )
                                    : null;

                            $color = $percent < 0 ? '#8b0000' : '#006400';
                        @endphp
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
```


Patch:
diff --git a/src/formatter.ts b/src/formatter.ts
index b1b4feb..b0d3d2a 100644
--- a/src/formatter.ts
+++ b/src/formatter.ts
@@ -1301,8 +1301,7 @@ export default class Formatter {
         } else if (isMultipleStatements) {
           // multiple statments on mult lines
 
-          const indentLevel = (indent.amount + 1) * this.indentSize;
-
+          const indentLevel = indent.amount + this.indentSize;
           rawBlock = (
             await util.formatStringAsPhp(`<?php${rawBlock}?>`, {
               ...this.options,


Test patch:
diff --git a/__tests__/formatter.test.ts b/__tests__/formatter.test.ts
index 7cfbdfe..ca634f8 100644
--- a/__tests__/formatter.test.ts
+++ b/__tests__/formatter.test.ts
@@ -5417,4 +5417,54 @@ describe('formatter', () => {
 
     await util.doubleFormatCheck(content, expected);
   });
+
+  test('@php blocks respect indent level for deeply indented code (issue #915)', async () => {
+    let content = [
+      '<div>',
+      '<div>',
+      '<div>',
+      '<div>',
+      '<div>',
+      '<div>',
+      '@php',
+      "$percent = $item['historical'] ?? null ? round((100 * ($item['today'] - $item['historical'])) / $item['historical']) : null;",
+      '',
+      "$color = $percent < 0 ? '#8b0000' : '#006400';",
+      '@endphp',
+      '</div>',
+      '</div>',
+      '</div>',
+      '</div>',
+      '</div>',
+      '</div>',
+    ].join('\n');
+
+    // this is slightly different than the code presented in #915 because that
+    // code was wrapped to 80 columns, but these tests all use 120
+    let expected = [
+      '<div>',
+      '    <div>',
+      '        <div>',
+      '            <div>',
+      '                <div>',
+      '                    <div>',
+      '                        @php',
+      '                            $percent =',
+      "                                $item['historical'] ?? null",
+      "                                    ? round((100 * ($item['today'] - $item['historical'])) / $item['historical'])",
+      '                                    : null;',
+      '',
+      "                            $color = $percent < 0 ? '#8b0000' : '#006400';",
+      '                        @endphp',
+      '                    </div>',
+      '                </div>',
+      '            </div>',
+      '        </div>',
+      '    </div>',
+      '</div>',
+      ``,
+    ].join('\n');
+
+    await util.doubleFormatCheck(content, expected);
+  });
 });