Repository navigation
fix: preserve suites across dedented bracket continuations - #36
Merged
Merged
Conversation
Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
Compress increasing indentation gaps to retain the full existing stack alongside bracket depth. Preserve named line continuations before brackets and update the external fixture failure list for the corrected syntax. Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
Scan format payload before layout so spaces, tabs and carriage returns remain inside the queried format field. Keep the hidden token boundary and fresh versus incremental trees covered through the public API. Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Valid code such as
if True:\n print(1 +\n1)produces errors and detaches following statements from its suite. This addressestree-sitter/tree-sitter-python#256. Python permits arbitrary indentation on implicit continuation lines inside brackets.The scanner guesses whether it is inside brackets by checking whether a closing token is currently valid. After an operator, the parser needs an operand first, so no closing token is valid and the scanner incorrectly forces a dedent. Removing forced dedents also accepts invalid unbracketed continuations; tracking the actual bracket context preserves that recovery behavior.
Requirements
required: Improve our forked tree-sitter and grammar repositories as much as possible, ignoring backward compatibility; review our issues and major upstream issues, PRs and recent commits and create dedicated nonduplicate PRs from latest main for eligible items.
required: Fix the reproduced valid dedented bracket-continuation case while keeping meaningful public corpus, query and edit validation; run verification and the requested review-booster, complete-pr and release workflow.
required: Run review-booster and complete-pr concurrently, then release the changes.
chosen: Track actual opening and closing punctuation in serialized scanner state instead of guessing from possible closing tokens. Preserve forced dedent recovery outside brackets because removing it newly accepts incomplete assignments and unbracketed expressions across a dedent.
chosen: Preserve existing accepted node trees, fields, ranges and following-statement ownership; this lexical correction needs no new named nodes or runtime ABI change.
chosen: Preserve the existing 510-level indentation capacity at every bracket depth using a fixed 32-bit bracket counter and variable-length increasing indentation gaps. A 510-suite/127-bracket reproduction showed that adding extended-depth bytes before fixed-width indents truncates state; the gap encoding fits every stack representable by the prior format within 902 of 1024 bytes.
chosen: Scan format-specifier content as a hidden external token before layout, since its whitespace is meaningful payload. An explicit context token preserves the existing format field text/ranges without relying on a heuristic over closing-token validity.
Customer Summary
Expressions inside parentheses, square brackets and braces can continue on a less-indented line without ending their surrounding suite. Incomplete unbracketed expressions still report errors, and following statements retain their scope.
Technical Summary
grammar.jsexposes opening and closing punctuation to the scanner using the existing anonymous token symbols.src/scanner.ctracks bracket depth, includes it in serialization, and clears abandoned bracket context when recovery emits a dedent. F-string brace paths update the same state. Punctuation is not emitted across skipped explicit line continuations, allowing the internal lexer to preserve their named syntax nodes. A hidden format-content token preserves spaces, tabs and carriage returns before nested or closing format braces; it replaces the internal regular expression without introducing visible nodes. Canonical generated sources carry the external-token changes.The public incremental regression removes and restores continuation indentation for calls, groups, subscripts, lists, sets and dictionaries, 129 nested brackets and indentation widths at the gap-encoding boundaries. It checks suite ownership, standard query captures, exact operand ranges and fresh/incremental agreement. Negative cases ensure unbracketed incomplete statements remain errors and preserve the following top-level statement. Additional LF/CRLF query-and-edit coverage preserves explicit line-continuation nodes and ranges before opening and closing punctuation. The deep-indentation regression combines 510 suites with 127 nested brackets. Public format-specifier queries retain whitespace text/ranges and agree after edits for nested braces, tabs and LF/CRLF.
Testing
bun run build/ci; all 210 native and Wasm corpus cases pass.cargo test --lockedandbun run verifypass.test_compile.pycompiles and now parses without errors; the published parser rejects its dedented attribute continuations. Its obsolete expected failure is removed. PR CI parses all 5,901 external files with three expected failures, matching the updated list. All PR checks pass, including external examples, browser/Workers, fuzzing, sanitizers, Rust, Linux ARM and both macOS architectures.Notes
The existing scanner dispatch exceeds code-gauge limits (complexity 184, 211 NCSS; previously 175/202). Reducing it below the limits would require a separate string/layout scanner redesign or mechanically move the same complexity into helpers. The six other existing errors are imported fixtures: Python2
GrammarTests.testFuncdefin both newline variants (159 NCSS), Python3 equivalents (187 NCSS), and the Python3.8 example file (1,200 NCSS) and itstest_funcdef(232 NCSS). Forty-six existing warnings remain outside changed code. Intentional LF/CRLF fixture duplicates would be suitable for a code-gauge exclusion; no exclusion configuration is added.