fix(cmd): handle errors and improve output formatting
CI / Test (push) Successful in 28s
CI / Build (push) Successful in 25s

* update error handling in various commands to use blank identifier
* enhance output formatting for better readability
* add golangci-lint to Makefile for linting checks
This commit is contained in:
Hein
2026-07-01 12:53:25 +02:00
parent f17e87e749
commit 04711cf7b2
14 changed files with 80 additions and 82 deletions
+18 -18
View File
@@ -61,21 +61,21 @@ type Style struct {
CustomTypeCase Case // user-defined / domain types not in the built-in set
// --- Query layout ---
Commas CommaStyle
AlignColumns bool // pad SELECT list so values align
AlignLineComments bool // align trailing -- comments in a block
SelectAlignAs bool // pad between expression and AS in SELECT list
SetAlignEqual bool // align = in UPDATE SET list
IndentJoin bool // extra indentation for JOIN … ON lines
JoinIndentSize int // extra indent levels for JOINs (default 1)
WhereWrap WrapMode // always|when_long|never — each AND/OR on its own line
WhereAndOrIndent bool // AND/OR indented one level under WHERE
Commas CommaStyle
AlignColumns bool // pad SELECT list so values align
AlignLineComments bool // align trailing -- comments in a block
SelectAlignAs bool // pad between expression and AS in SELECT list
SetAlignEqual bool // align = in UPDATE SET list
IndentJoin bool // extra indentation for JOIN … ON lines
JoinIndentSize int // extra indent levels for JOINs (default 1)
WhereWrap WrapMode // always|when_long|never — each AND/OR on its own line
WhereAndOrIndent bool // AND/OR indented one level under WHERE
// --- Subqueries ---
SubqueryOpening Placement // opening ( placement: same_line|new_line
SubqueryContent Placement // content indentation: same_line|new_line
SubqueryClosing Placement // closing ) placement: same_line|new_line
SubquerySpaceBeforeParen bool // space before ( in subqueries
SubqueryOpening Placement // opening ( placement: same_line|new_line
SubqueryContent Placement // content indentation: same_line|new_line
SubqueryClosing Placement // closing ) placement: same_line|new_line
SubquerySpaceBeforeParen bool // space before ( in subqueries
// --- INSERT ---
InsertCollapseValues bool // fold multiple VALUES rows onto fewer lines
@@ -85,11 +85,11 @@ type Style struct {
RoutineAsWrap bool // newline before AS $$
// --- PL/pgSQL body ---
PlpgsqlMaxBlankLines int // max consecutive blank lines in body
PlpgsqlDeclareAlignType bool // align type column in DECLARE block
PlpgsqlDeclareAlignEq bool // align := / = in DECLARE block
PlpgsqlIfThenNewline bool // THEN on its own line
PlpgsqlLoopCollapse bool // collapse empty loop bodies to one line
PlpgsqlMaxBlankLines int // max consecutive blank lines in body
PlpgsqlDeclareAlignType bool // align type column in DECLARE block
PlpgsqlDeclareAlignEq bool // align := / = in DECLARE block
PlpgsqlIfThenNewline bool // THEN on its own line
PlpgsqlLoopCollapse bool // collapse empty loop bodies to one line
// --- Expressions ---
BinaryOpAlign bool // align =, <>, || etc. vertically in WHERE/expr lists
+9 -16
View File
@@ -10,16 +10,13 @@ import (
// isDMLStart reports whether toks begins with a DML statement keyword.
func isDMLStart(toks []cst.Tok) bool {
for _, t := range toks {
if t.Tok.Kind == lexer.Ident {
switch lowerASCII(t.Tok.Text) {
case "select", "insert", "update", "delete", "with":
return true
}
return false
}
if len(toks) == 0 || toks[0].Tok.Kind != lexer.Ident {
return false
}
switch lowerASCII(toks[0].Tok.Text) {
case "select", "insert", "update", "delete", "with":
return true
}
return false
}
@@ -510,13 +507,6 @@ func dmlSplitCommas(toks []cst.Tok) [][]cst.Tok {
return items
}
// dmlColList formats kwText followed by a comma-separated body.
// One item: kept on the same line as the keyword.
// Multiple items: each on its own line with the configured comma style.
func dmlColList(kwText string, items [][]cst.Tok, st config.Style) string {
return dmlColListSelect(kwText, items, st)
}
// dmlColListSelect formats a SELECT / RETURNING column list with optional
// align_columns and select_align_as settings.
func dmlColListSelect(kwText string, items [][]cst.Tok, st config.Style) string {
@@ -627,7 +617,10 @@ func dmlColListSet(kwText string, items [][]cst.Tok, st config.Style) string {
// alias names align vertically.
func alignSelectItems(texts []string, st config.Style) []string {
// Split each text into (expr, " AS ", alias) or keep as-is.
type part struct{ expr, alias string; hasAs bool }
type part struct {
expr, alias string
hasAs bool
}
parts := make([]part, len(texts))
maxExpr := 0
for i, t := range texts {
+3 -3
View File
@@ -68,6 +68,6 @@ to_char to_date to_json to_jsonb to_number to_timestamp to_tsvector
translate trim trunc unnest upper width_bucket
`)
func isKeyword(lower string) bool { return keywords[lower] }
func isTypeName(lower string) bool { return typeNames[lower] }
func isBuiltinFunc(lower string) bool { return builtinFunctions[lower] }
func isKeyword(lower string) bool { return keywords[lower] }
func isTypeName(lower string) bool { return typeNames[lower] }
func isBuiltinFunc(lower string) bool { return builtinFunctions[lower] }
+7 -7
View File
@@ -89,12 +89,12 @@ func (s *server) handle(raw []byte) bool {
return true
case "textDocument/didOpen":
var p didOpenParams
json.Unmarshal(req.Params, &p)
_ = json.Unmarshal(req.Params, &p)
s.docs[p.TextDocument.URI] = p.TextDocument.Text
s.pushDiagnostics(p.TextDocument.URI, p.TextDocument.Text)
case "textDocument/didChange":
var p didChangeParams
json.Unmarshal(req.Params, &p)
_ = json.Unmarshal(req.Params, &p)
if len(p.ContentChanges) > 0 {
text := p.ContentChanges[len(p.ContentChanges)-1].Text
s.docs[p.TextDocument.URI] = text
@@ -104,7 +104,7 @@ func (s *server) handle(raw []byte) bool {
var p struct {
TextDocument textDocID `json:"textDocument"`
}
json.Unmarshal(req.Params, &p)
_ = json.Unmarshal(req.Params, &p)
delete(s.docs, p.TextDocument.URI)
delete(s.fixes, p.TextDocument.URI)
s.notify("textDocument/publishDiagnostics", publishDiagnosticsParams{
@@ -113,7 +113,7 @@ func (s *server) handle(raw []byte) bool {
})
case "textDocument/formatting":
var p formattingParams
json.Unmarshal(req.Params, &p)
_ = json.Unmarshal(req.Params, &p)
text, ok := s.docs[p.TextDocument.URI]
if !ok {
s.reply(req.ID, []textEdit{})
@@ -127,7 +127,7 @@ func (s *server) handle(raw []byte) bool {
s.reply(req.ID, []textEdit{fullReplace(text, formatted)})
case "textDocument/rangeFormatting":
var p rangeFormattingParams
json.Unmarshal(req.Params, &p)
_ = json.Unmarshal(req.Params, &p)
text, ok := s.docs[p.TextDocument.URI]
if !ok {
s.reply(req.ID, []textEdit{})
@@ -136,7 +136,7 @@ func (s *server) handle(raw []byte) bool {
s.reply(req.ID, s.rangeFormat(text, p.Range))
case "textDocument/codeAction":
var p codeActionParams
json.Unmarshal(req.Params, &p)
_ = json.Unmarshal(req.Params, &p)
s.handleCodeAction(req.ID, p)
case "$/cancelRequest": // ignore
default:
@@ -360,7 +360,7 @@ func (s *server) send(v interface{}) {
if err != nil {
return
}
fmt.Fprintf(s.w, "Content-Length: %d\r\n\r\n", len(data))
_, _ = fmt.Fprintf(s.w, "Content-Length: %d\r\n\r\n", len(data))
s.w.Write(data) //nolint:errcheck
}
+2 -2
View File
@@ -51,7 +51,7 @@ func readResp(t *testing.T, buf *bytes.Buffer) map[string]interface{} {
}
lenStr := string(data[idx+16 : idx+eol])
var n int
fmt.Sscanf(lenStr, "%d", &n)
_, _ = fmt.Sscanf(lenStr, "%d", &n)
sep := bytes.Index(data, []byte("\r\n\r\n"))
if sep < 0 || len(data) < sep+4+n {
time.Sleep(5 * time.Millisecond)
@@ -60,7 +60,7 @@ func readResp(t *testing.T, buf *bytes.Buffer) map[string]interface{} {
body := data[sep+4 : sep+4+n]
buf.Next(sep + 4 + n)
var result map[string]interface{}
json.Unmarshal(body, &result)
_ = json.Unmarshal(body, &result)
return result
}
t.Fatal("timeout waiting for response")
+1 -1
View File
@@ -88,7 +88,7 @@ func parseCreateFunction(stmt []cst.Tok) (*cst.CreateFunction, bool) {
if i+1 < len(stmt) && stmt[i].Is("or") && stmt[i+1].Is("replace") {
i += 2
}
if i >= len(stmt) || !(stmt[i].Is("function") || stmt[i].Is("procedure")) {
if i >= len(stmt) || (!stmt[i].Is("function") && !stmt[i].Is("procedure")) {
return nil, false
}
i++
+1 -1
View File
@@ -41,7 +41,7 @@ func FirstTokenOffset(sql string, start int) int {
}
case i+1 < n && sql[i] == '/' && sql[i+1] == '*':
i += 2
for i+1 < n && !(sql[i] == '*' && sql[i+1] == '/') {
for i+1 < n && (sql[i] != '*' || sql[i+1] != '/') {
i++
}
if i+1 < n {