fix(cmd): handle errors and improve output formatting
* 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:
+18
-18
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user