Skip to content

BufferAnalyzer::hasBalancedBrackets() miscounts }-tokens from string interpolation in 0.12.22 #930

Description

@pieterwebparking

Summary

In v0.12.22, Psy\CodeAnalysis\BufferAnalyzer::hasBalancedBrackets() returns false for any buffer containing "…{$var}…" style string interpolation, because the analyzer treats T_CURLY_OPEN (the {$ opener) as an array-form token and skips it, but the closing } arrives as a single-char token and falls through into the bracket counter — so each interpolation registers as one extra unmatched }.

Because StatementCompletenessPolicy::isCompleteStatement() consults hasBalancedBrackets() whenever there's no parse error, any complete buffer containing interpolation is classified as incomplete. With the new readline (legacy or experimental), Enter then keeps inserting line breaks instead of submitting, and the prompt is stuck on . indefinitely.

Minimal repro

$a = new \Psy\CodeAnalysis\BufferAnalyzer();
var_dump($a->analyze('echo "hi {$x}";')->hasBalancedBrackets());
// bool(false) — expected bool(true)

It also surfaces interactively as soon as you paste any multi-line block containing "…{$var}…". e.g.

foreach ($items as $r) {
    echo "rehashed {$r->id}\n";
}

…enters the buffer fine, but Enter never submits. Adding "" at the end happens to flip the policy through a different branch (canBeFixedWithSemicolon) and submits the whole thing — accidental escape hatch, not a fix.

Environment

  • PsySH v0.12.22
  • PHP 8.5.5 (also reproducible on 8.3 / 8.4 since the issue is in static token analysis)
  • Linux, kitty terminal — but the bug is terminal-agnostic; the BufferAnalyzer::analyze(…) call alone reproduces it

Suspected fix

In BufferAnalyzer::hasBalancedBrackets(), the bracket walker needs to skip closing } tokens that match an earlier T_CURLY_OPEN/T_DOLLAR_OPEN_CURLY_BRACES opener (which are array-form tokens that the current implementation skips). Easiest is to track string-interpolation depth alongside the structural-bracket stack.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions