fix: keep DuckDB array-slice colon dense inside [ ] - #960
Conversation
DuckDB dropped ':' from alwaysDenseOperators (f9575c0) so struct literals like {'a': 1} get their key-value space. That also spaced the array-slice colon, so foo[:5] formatted as foo[: 5] and baz[1:5] as baz[1: 5]. Only the colon followed by a value was affected; bar[1:] and zap[:] were already fine. Make the ':' spacing depend on the nearest enclosing bracket rather than being dialect-global: dense inside [ ] (array slice), spaced elsewhere ({ } struct keys, prefix aliases). This keeps the struct-literal fix intact. Un-skips the existing "supports array slice operator" test.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbit
Walkthrough
ChangesArray slice formatting
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
DuckDB's array-slice operator formats with a stray space:
foo[:5]comes out asfoo[: 5]andbaz[1:5]asbaz[1: 5].Root cause
Commit f9575c0 ("Support ':' as struct key-value separator") removed
':'from DuckDB'salwaysDenseOperators, so struct literals like{'a': 1}keep the space after the colon. As a side effect the array-slice colon, which travels the same generic operator-spacing path, also became spaced. The identical test still passes for PostgreSQL (which keeps':'dense and has no struct literals), and the DuckDB copy was skipped with a// TODO: This currently conflicts with ":"-operator in struct literals.The colon is genuinely context-dependent in DuckDB — dense inside
[...](array slice), spaced inside{...}(struct key) — butalwaysDenseOperatorsis a flat, dialect-global list with no notion of context, so neither setting is correct for both.Fix
Make the
':'spacing decision depend on the nearest enclosing bracket rather than being dialect-global: dense inside[...], spaced otherwise. The bracket context flows through the recursiveExpressionFormatter(each parenthesis passes its ownopenParendown to its children), so a struct nested in a list —[{'a': 1}]— still gets the spaced colon because its nearest bracket is{.Only the colon-followed-by-a-value case was visibly wrong (
foo[:5],baz[1:5]);bar[1:]andzap[:]already rendered correctly because the trailing space was absorbed by the closing bracket.Tests
supports array slice operatortest (all four forms:foo[:5],bar[1:],baz[1:5],zap[:]).{'k': list[1:5]}— where the struct colon stays spaced while the slice colon is dense.The four
formats {} struct literal ...andformats prefix aliasestests double as an over-fix guard: making:dense unconditionally passes the slice test but breaks all of them. Fullpnpm testis green across every dialect.Note
alwaysDenseOperatorshas no context mechanism today, so I threaded the bracket context through the formatter rather than widening that config surface. If you'd prefer a different shape (e.g. recognising the slice colon at the grammar level), happy to adjust.