feat(format): skip non-plpgsql bodies; keep literals and embedded code safe

- Only restyle bodies for plpgsql/sql; skip pl* (plpython3u, plperl, ...), c and internal
- Keep LANGUAGE clause on DO blocks
- Carry multi-line string and dollar-quoted literals verbatim in bodies and DML
- Format dollar-quoted literals that contain code (declare/begin/select/...), never format() templates
- Fix code joined onto -- comments, early flush after raise exception, dropped comment before BEGIN
- Regenerate test_mm_proc golden; document in README, plan, todo
This commit is contained in:
Hein
2026-10-06 14:43:43 +02:00
parent 41fdaf415c
commit 4ff729eeeb
8 changed files with 729 additions and 228 deletions
+17 -1
View File
@@ -490,6 +490,12 @@ func dmlWrapSubquery(inner []cst.Tok, st config.Style) string {
return b.String()
}
// litNL stands in for a newline inside a multi-line string literal while DML
// text is assembled; formatDML's caller restores it (see restoreLiteralNewlines).
const litNL = "\x00\x01"
func restoreLiteralNewlines(s string) string { return strings.ReplaceAll(s, litNL, "\n") }
// dmlInline renders toks on one line with keyword casing and proper spacing.
// If toks[1:] contains comment trivia the function falls back to verbatimSpan
// so no comment is lost. Subquery parens and CASE…END expressions embedded
@@ -548,7 +554,17 @@ func dmlInline(toks []cst.Tok, st config.Style) string {
prev = toks[i-1].Tok
}
nextIsLParen := i+1 < len(toks) && toks[i+1].Tok.Kind == lexer.LParen
b.WriteString(caseTextCtx(t.Tok, prev, nextIsLParen, st))
txt := caseTextCtx(t.Tok, prev, nextIsLParen, st)
if t.Tok.Kind == lexer.DollarString {
txt = formatEmbedded(txt, st)
}
switch t.Tok.Kind {
case lexer.String, lexer.EscapeString, lexer.BitString, lexer.DollarString:
// Line breaks inside a literal are content: hide them from the
// line-based indent helpers that post-process this text.
txt = strings.ReplaceAll(txt, "\n", litNL)
}
b.WriteString(txt)
i++
}
return b.String()