Skip to content

Indent catch arm bodies relative to enclosing blocks#3710

Draft
ATX24 wants to merge 2 commits into
canaryfrom
cursor/baml-fmt-catch-indentation-0aaa
Draft

Indent catch arm bodies relative to enclosing blocks#3710
ATX24 wants to merge 2 commits into
canaryfrom
cursor/baml-fmt-catch-indentation-0aaa

Conversation

@ATX24

@ATX24 ATX24 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Pull Request Template

Thanks for taking the time to fill out this pull request!

Issue Reference

Please link to any related issues

  • This PR fixes/closes #[issue number]

The error

Running baml fmt on a catch expression in a function body preserved raw catch-body indentation after the first line, producing mixed 4-space/2-space layout:

function demo(s: string) -> int {
    baml.json.from_string<int>(s) catch (e) {
    baml.json.JsonParseError => 0,
    baml.json.JsonDecodeError => 0,
  };
    42
}

Incorrect formatted output before this change:

function demo(s: string) -> int {
    baml.json.from_string<int>(s) catch (e) {
    baml.json.JsonParseError => 0,
    baml.json.JsonDecodeError => 0,
  };
    42
}

The formatter exited successfully, so this was a formatter layout bug rather than a parse/type error.

Root cause

CATCH_EXPR was not handled by the strong formatter AST in baml_language/crates/baml_fmt/src/ast/expressions.rs. Expression::from_cst fell through to Expression::Unknown(TextRange), whose printer uses print_input_range_trimmed_start: it strips only the first line's leading whitespace and then emits continuation lines at their original absolute indentation. That raw fallback made catch arms keep whatever source indentation they had instead of being indented from the enclosing block's Shape.

The fix

  • Added Expression::Catch plus CatchExpr, CatchClause, CatchArm, and CatchKeyword formatter nodes in baml_language/crates/baml_fmt/src/ast/expressions.rs.
  • Added formatter token wrappers for catch and catch_all in baml_language/crates/baml_fmt/src/ast/tokens.rs.
  • Catch clauses now print like other block containers: arms use shape.indent + indent_width, and the catch closing brace uses the enclosing shape.indent.
  • Added focused unit tests for malformed catch indentation and chained catch_all indentation in baml_language/crates/baml_fmt/src/lib.rs.
  • Updated the affected generated formatter snapshot for catch_return_type_mismatch.

Verification

Focused formatter tests:

$ cargo test -p baml_fmt catch_format_tests
running 2 tests
test catch_format_tests::test_catch_arm_indentation_in_function_body ... ok
test catch_format_tests::test_chained_catch_all_indentation ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 54 filtered out; finished in 0.00s

Full formatter crate:

$ cargo test -p baml_fmt
running 56 tests
...
test result: ok. 56 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s

Existing catch formatter snapshots:

$ cargo test -p baml_tests catch_throw::test_10_formatter
...
test result: ok

$ cargo test -p baml_tests catch_all_keyword::test_10_formatter
...
test result: ok

Workspace library tests for crates that support plain cargo test --lib:

$ cargo test --lib --workspace --exclude bridge_nodejs --exclude sdk_test_typescript_node
...
test result: ok

bridge_nodejs documents in its Cargo.toml that standalone Rust test binaries cannot link N-API symbols; the TypeScript SDK crate documents that plain cargo test skips its setup and must be run with nextest. I ran that documented suite separately:

$ cargo nextest run -p sdk_test_typescript_node --lib
Summary [  47.428s] 15 tests run: 15 passed, 0 skipped

CLI reproduction after the fix:

$ cargo run -p baml_cli -- fmt repro_fmt.baml
  Formatting repro_fmt.baml
    Finished formatted 1 file(s) in 0s

Formatted output now succeeds with catch arms indented relative to the enclosing function body:

function demo(s: string) -> int {
    baml.json.from_string<int>(s) catch (e) {
        baml.json.JsonParseError => 0,
        baml.json.JsonDecodeError => 0,
    };
    42
}

Changes

Please describe the changes proposed in this pull request

See The fix above.

Testing

Please describe how you tested these changes

  • Unit tests added/updated
  • Manual testing performed
  • Tested in Linux cloud agent environment

Screenshots

If applicable, add screenshots to help explain your changes

N/A

PR Checklist

Please ensure you've completed these items

  • I have read and followed the contributing guidelines
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

Additional Notes

Environment setup performed during verification: installed python3.12-dev so bridge_python tests could link libpython3.12; installed/trusted mise and installed uv/cargo-nextest for the SDK test suites.

Open in Web Open in Cursor 

cursoragent and others added 2 commits June 8, 2026 17:03
@vercel

vercel Bot commented Jun 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jun 8, 2026 6:08pm
promptfiddle Ready Ready Preview, Comment Jun 8, 2026 6:08pm
promptfiddle2 Ready Ready Preview, Comment Jun 8, 2026 6:08pm

Request Review

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

No description provided.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants