Skip to content

Commit 75f36e8

Browse files
committed
Preserve outer bracket spacing for array literals with whitespace
Track whether there's whitespace after the opening [ bracket in array literals and use this to format arrays with outer spaces when appropriate. This matches ClickHouse's EXPLAIN AST behavior for multi-line arrays.
1 parent 7e24086 commit 75f36e8

File tree

4 files changed

+20
-13
lines changed

4 files changed

+20
-13
lines changed

ast/ast.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,14 +1261,15 @@ func (t *TableIdentifier) expressionNode() {}
12611261

12621262
// Literal represents a literal value.
12631263
type Literal struct {
1264-
Position token.Position `json:"-"`
1265-
Type LiteralType `json:"type"`
1266-
Value interface{} `json:"value"`
1267-
Source string `json:"source,omitempty"` // Original source text (for preserving 0.0 vs 0)
1268-
Negative bool `json:"negative,omitempty"` // True if literal was explicitly negative (for -0)
1269-
Parenthesized bool `json:"parenthesized,omitempty"` // True if wrapped in explicit parentheses
1270-
SpacedCommas bool `json:"spaced_commas,omitempty"` // True if array/tuple had spaces after commas
1271-
IsBigInt bool `json:"is_big_int,omitempty"` // True if this is a large integer stored as string
1264+
Position token.Position `json:"-"`
1265+
Type LiteralType `json:"type"`
1266+
Value interface{} `json:"value"`
1267+
Source string `json:"source,omitempty"` // Original source text (for preserving 0.0 vs 0)
1268+
Negative bool `json:"negative,omitempty"` // True if literal was explicitly negative (for -0)
1269+
Parenthesized bool `json:"parenthesized,omitempty"` // True if wrapped in explicit parentheses
1270+
SpacedCommas bool `json:"spaced_commas,omitempty"` // True if array/tuple had spaces after commas
1271+
SpacedBrackets bool `json:"spaced_brackets,omitempty"` // True if array had whitespace after [ and before ]
1272+
IsBigInt bool `json:"is_big_int,omitempty"` // True if this is a large integer stored as string
12721273
}
12731274

12741275
func (l *Literal) Pos() token.Position { return l.Position }

internal/explain/format.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,10 @@ func formatArrayAsStringFromLiteral(lit *ast.Literal) string {
558558
if lit.SpacedCommas {
559559
separator = ", "
560560
}
561+
// Use outer spaces when source had whitespace after [ (e.g., for multi-line arrays)
562+
if lit.SpacedBrackets {
563+
return "[ " + strings.Join(parts, separator) + " ]"
564+
}
561565
return "[" + strings.Join(parts, separator) + "]"
562566
}
563567

parser/expression.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,8 +1224,13 @@ func (p *Parser) parseArrayLiteral() ast.Expression {
12241224
Position: p.current.Pos,
12251225
Type: ast.LiteralArray,
12261226
}
1227+
bracketPos := p.current.Pos.Offset
12271228
p.nextToken() // skip [
12281229

1230+
// Check if there's whitespace/newline after the opening bracket
1231+
// A bracket is 1 byte, so if offset difference > 1, there's whitespace
1232+
spacedBrackets := p.current.Pos.Offset > bracketPos+1
1233+
12291234
var elements []ast.Expression
12301235
spacedCommas := false
12311236

@@ -1257,6 +1262,7 @@ func (p *Parser) parseArrayLiteral() ast.Expression {
12571262
}
12581263
lit.Value = elements
12591264
lit.SpacedCommas = spacedCommas
1265+
lit.SpacedBrackets = spacedBrackets
12601266

12611267
p.expect(token.RBRACKET)
12621268
return lit
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt9": true
4-
}
5-
}
1+
{}

0 commit comments

Comments
 (0)