Skip to content

Commit c9b3567

Browse files
committed
fix - invalid indentation - kokororin/vscode-phpfmt#122
1 parent e7df353 commit c9b3567

13 files changed

Lines changed: 239 additions & 7 deletions

fmt.stub.php

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4222,6 +4222,9 @@ private function manageAttribute($text) {
42224222
}
42234223

42244224
final class ReindentColonBlocks extends FormatterPass {
4225+
private $lastCloseTagHadNewline = false;
4226+
private $inTemplateGap = false;
4227+
42254228
public function candidate($source, $foundTokens) {
42264229
if (isset($foundTokens[T_ENDIF]) || isset($foundTokens[T_ENDWHILE]) || isset($foundTokens[T_ENDFOREACH]) || isset($foundTokens[T_ENDFOR])) {
42274230
return true;
@@ -4233,6 +4236,8 @@ public function candidate($source, $foundTokens) {
42334236
public function format($source) {
42344237
$this->tkns = token_get_all($source);
42354238
$this->code = '';
4239+
$this->lastCloseTagHadNewline = false;
4240+
$this->inTemplateGap = false;
42364241

42374242
while (list($index, $token) = $this->each($this->tkns)) {
42384243
list($id, $text) = $this->getToken($token);
@@ -4274,15 +4279,51 @@ public function format($source) {
42744279
$this->printUntil(T_END_HEREDOC);
42754280
break;
42764281

4282+
case T_CLOSE_TAG:
4283+
$this->appendCode($text);
4284+
$this->lastCloseTagHadNewline = $this->hasLn($text);
4285+
$this->inTemplateGap = $this->lastCloseTagHadNewline;
4286+
break;
4287+
4288+
case T_OPEN_TAG:
4289+
case T_OPEN_TAG_WITH_ECHO:
4290+
$this->inTemplateGap = false;
4291+
if ($this->hasLn($text) && $this->indent > 0 && !$this->lastCloseTagHadNewline) {
4292+
$indent = $this->getIndent();
4293+
$text = preg_replace("/\n$/", "\n" . $indent, $text);
4294+
}
4295+
$this->appendCode($text);
4296+
break;
4297+
42774298
default:
42784299
$hasLn = $this->hasLn($text);
4279-
if ($hasLn) {
4280-
if ($this->rightTokenIs([T_ENDIF, T_ELSE, T_ELSEIF, T_ENDFOR, T_ENDFOREACH, T_ENDWHILE])) {
4281-
$this->setIndent(-1);
4282-
$text = str_replace($this->newLine, $this->newLine . $this->getIndent(), $text);
4283-
$this->setIndent(+1);
4284-
} else {
4285-
$text = str_replace($this->newLine, $this->newLine . $this->getIndent(), $text);
4300+
if ($hasLn && !$this->inTemplateGap) {
4301+
$skipIndent = false;
4302+
if ($this->rightTokenIs(T_CLOSE_TAG)) {
4303+
list(, $closeTagText) = $this->inspectToken(+1);
4304+
if ($this->hasLn($closeTagText)) {
4305+
$skipIndent = true;
4306+
}
4307+
}
4308+
if (!$skipIndent) {
4309+
$indent = $this->getIndent();
4310+
if ($this->rightUsefulTokenIs([T_ENDIF, T_ELSE, T_ELSEIF, T_ENDFOR, T_ENDFOREACH, T_ENDWHILE])) {
4311+
$this->setIndent(-1);
4312+
$indent = $this->getIndent();
4313+
$this->setIndent(+1);
4314+
}
4315+
// For T_INLINE_HTML, only add indentation after newlines if the content doesn't already start with whitespace
4316+
if ($id === T_INLINE_HTML) {
4317+
$text = preg_replace_callback('/\n([^\n])/', function($m) use ($indent) {
4318+
// If the char after newline is already whitespace, don't add more
4319+
if ($m[1] === "\t" || $m[1] === " ") {
4320+
return "\n" . $m[1];
4321+
}
4322+
return "\n" . $indent . $m[1];
4323+
}, $text);
4324+
} else {
4325+
$text = str_replace($this->newLine, $this->newLine . $indent, $text);
4326+
}
42864327
}
42874328
}
42884329
$this->appendCode($text);
@@ -7975,6 +8016,18 @@ public function format($source) {
79758016
if (0 != $idx && $idx < $lastLine) {
79768017
$indent = $this->indentChar;
79778018
}
8019+
// Don't add padding if the line already has sufficient leading whitespace
8020+
$expectedPrefix = $before . $indent;
8021+
$expectedLen = strlen($expectedPrefix);
8022+
if ($expectedLen > 0) {
8023+
// Get leading whitespace from the line
8024+
preg_match('/^[\t ]*/', $line, $m);
8025+
$lineLeadingWs = isset($m[0]) ? $m[0] : '';
8026+
if (strlen($lineLeadingWs) >= $expectedLen) {
8027+
// Line already has enough indentation, don't add more
8028+
continue;
8029+
}
8030+
}
79788031
$tmp[$idx] = $before . $indent . $line;
79798032
}
79808033

@@ -9292,6 +9345,11 @@ public function format($source) {
92929345

92939346
if (T_OPEN_TAG_WITH_ECHO == $id) {
92949347
$text = '<?php echo ';
9348+
// Skip following whitespace to avoid double space
9349+
$nextToken = isset($this->tkns[$index + 1]) ? $this->tkns[$index + 1] : null;
9350+
if ($nextToken && is_array($nextToken) && T_WHITESPACE == $nextToken[0]) {
9351+
$this->each($this->tkns);
9352+
}
92959353
}
92969354

92979355
$this->appendCode($text);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
// Repro for https://github.com/kokororin/vscode-phpfmt/issues/122
3+
// Ensure formatting mixed HTML/PHP templates with colon syntax is idempotent
4+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
5+
?>
6+
<?php get_header(); ?>
7+
8+
<div class="container my-8 mx-auto flex flex-col">
9+
<?php if (have_posts()) : ?>
10+
<?php
11+
while (have_posts()) :
12+
the_post();
13+
?>
14+
<div class="section-title mb-8">
15+
<h1><?= get_the_title(); ?></h1>
16+
</div>
17+
<?php get_template_part("template-parts/content", "tribe_event_series"); ?>
18+
19+
<?php endwhile; ?>
20+
21+
<?php endif; ?>
22+
23+
</div>
24+
25+
<?php
26+
get_footer();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
// Repro for https://github.com/kokororin/vscode-phpfmt/issues/122
3+
// Ensure formatting mixed HTML/PHP templates with colon syntax is idempotent
4+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
5+
?>
6+
<?php get_header(); ?>
7+
8+
<div class="container my-8 mx-auto flex flex-col">
9+
<?php if (have_posts()): ?>
10+
<?php
11+
while (have_posts()):
12+
the_post();
13+
?>
14+
<div class="section-title mb-8">
15+
<h1><?php echo get_the_title(); ?></h1>
16+
</div>
17+
<?php get_template_part('template-parts/content', 'tribe_event_series'); ?>
18+
19+
<?php endwhile; ?>
20+
21+
<?php endif; ?>
22+
23+
</div>
24+
25+
<?php
26+
get_footer();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
// Test nested colon structures (if inside foreach)
3+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
4+
?>
5+
<ul>
6+
<?php foreach ($items as $item) : ?>
7+
<?php if ($item->isVisible()) : ?>
8+
<li><?= $item->getName(); ?></li>
9+
<?php endif; ?>
10+
<?php endforeach; ?>
11+
</ul>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
// Test nested colon structures (if inside foreach)
3+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
4+
?>
5+
<ul>
6+
<?php foreach ($items as $item): ?>
7+
<?php if ($item->isVisible()): ?>
8+
<li><?php echo $item->getName(); ?></li>
9+
<?php endif; ?>
10+
<?php endforeach; ?>
11+
</ul>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
// Test multiple short echo tags on same line
3+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
4+
?>
5+
<table>
6+
<?php foreach ($rows as $row) : ?>
7+
<tr>
8+
<td><?= $row->id; ?></td>
9+
<td><?= $row->name; ?> - <?= $row->email; ?></td>
10+
</tr>
11+
<?php endforeach; ?>
12+
</table>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
// Test multiple short echo tags on same line
3+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
4+
?>
5+
<table>
6+
<?php foreach ($rows as $row): ?>
7+
<tr>
8+
<td><?php echo $row->id; ?></td>
9+
<td><?php echo $row->name; ?> - <?php echo $row->email; ?></td>
10+
</tr>
11+
<?php endforeach; ?>
12+
</table>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
// Test if/elseif/else with colon syntax
3+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
4+
?>
5+
<div>
6+
<?php if ($status === "active") : ?>
7+
<span class="badge green"><?= $status; ?></span>
8+
<?php elseif ($status === "pending") : ?>
9+
<span class="badge yellow"><?= $status; ?></span>
10+
<?php else : ?>
11+
<span class="badge red">inactive</span>
12+
<?php endif; ?>
13+
</div>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
// Test if/elseif/else with colon syntax
3+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
4+
?>
5+
<div>
6+
<?php if ($status === 'active'): ?>
7+
<span class="badge green"><?php echo $status; ?></span>
8+
<?php elseif ($status === 'pending'): ?>
9+
<span class="badge yellow"><?php echo $status; ?></span>
10+
<?php else: ?>
11+
<span class="badge red">inactive</span>
12+
<?php endif; ?>
13+
</div>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
// Test foreach with key => value
3+
//passes:AlignPHPCode,ConvertOpenTagWithEcho,DoubleToSingleQuote
4+
?>
5+
<dl>
6+
<?php foreach ($attributes as $key => $value) : ?>
7+
<dt><?= $key; ?></dt>
8+
<dd><?= $value; ?></dd>
9+
<?php endforeach; ?>
10+
</dl>

0 commit comments

Comments
 (0)