diff --git a/internal/formatter/formatter.go b/internal/formatter/formatter.go index f7df66c..15cbf96 100644 --- a/internal/formatter/formatter.go +++ b/internal/formatter/formatter.go @@ -64,6 +64,9 @@ func (e *formatEnvironment) indentLevelUp() { func (e *formatEnvironment) indentLevelDown() { e.indentLevel-- + if e.indentLevel < 0 { + e.indentLevel = 0 + } } func (e *formatEnvironment) genIndent() []ast.Node { @@ -242,6 +245,7 @@ func formatItem(node ast.Node, env *formatEnvironment) ast.Node { } if commentAfterMatcher.IsMatch(node) { results = append(results, linebreakNode) + env.indentLevelDown() } breakStatementAfterMatcher := astutil.NodeMatcher{ @@ -251,7 +255,7 @@ func formatItem(node ast.Node, env *formatEnvironment) ast.Node { } if breakStatementAfterMatcher.IsMatch(node) { results = append(results, linebreakNode) - env.indentLevelDown() + env.indentLevelReset() } return &ast.ItemWith{Toks: results} diff --git a/internal/formatter/formatter_test.go b/internal/formatter/formatter_test.go index 38ff936..997eb55 100644 --- a/internal/formatter/formatter_test.go +++ b/internal/formatter/formatter_test.go @@ -1,6 +1,11 @@ package formatter import ( + "os" + "path/filepath" + "runtime" + "slices" + "strings" "testing" "github.com/sqls-server/sqls/ast" @@ -20,7 +25,7 @@ func TestEval(t *testing.T) { { name: "InsertIntoFormat", input: "INSERT INTO users (NAME, email) VALUES ('john doe', 'example@host.com')", - expected: "INSERT INTO users(\n\tNAME,\n\temail\n)\nVALUES(\n'john doe',\n'example@host.com'\n)", + expected: "INSERT INTO users(\n\tNAME,\n\temail\n)\nVALUES(\n\t'john doe',\n\t'example@host.com'\n)", params: lsp.DocumentFormattingParams{}, config: &config.Config{ LowercaseKeywords: false, @@ -117,3 +122,51 @@ func parseInit(t *testing.T, input string) []*ast.Statement { } return stmts } + +func TestFormat(t *testing.T) { + _, filename, _, _ := runtime.Caller(0) + dir := filepath.Dir(filename) + + files, err := filepath.Glob(filepath.Join(dir, "testdata", "*.sql")) + if err != nil { + t.Fatal(err) + } + slices.Sort(files) + + opts := &ast.RenderOptions{ + LowerCase: false, + IdentifierQuoted: false, + } + env := &formatEnvironment{} + for _, fname := range files { + b, err := os.ReadFile(fname) + if err != nil { + t.Fatal(err) + } + parsed, err := parser.Parse(string(b)) + if err != nil { + t.Fatal(err) + } + formatted := Eval(parsed, env) + got := strings.TrimRight(formatted.Render(opts), "\n") + "\n" + + b, err = os.ReadFile(fname[:len(fname)-4] + ".golden") + if err != nil { + t.Fatal(err) + } + want := string(b) + if got != want { + if _, err := os.Stat(fname[:len(fname)-4] + ".ignore"); err != nil { + t.Logf("%s:\n"+ + " want: %q\n"+ + " got: %q\n", + fname, want, got) + } else { + t.Errorf("%s:\n"+ + " want: %q\n"+ + " got: %q\n", + fname, want, got) + } + } + } +} diff --git a/internal/formatter/testdata/001.golden b/internal/formatter/testdata/001.golden new file mode 100644 index 0000000..bac5b43 --- /dev/null +++ b/internal/formatter/testdata/001.golden @@ -0,0 +1,4 @@ +SELECT + * +FROM + TABLE diff --git a/internal/formatter/testdata/001.sql b/internal/formatter/testdata/001.sql new file mode 100644 index 0000000..84b380f --- /dev/null +++ b/internal/formatter/testdata/001.sql @@ -0,0 +1 @@ +select * From table diff --git a/internal/formatter/testdata/002.golden b/internal/formatter/testdata/002.golden new file mode 100644 index 0000000..5a60070 --- /dev/null +++ b/internal/formatter/testdata/002.golden @@ -0,0 +1,13 @@ +-- hoge -- +SELECT + x/*x*/, + /*x*/y +FROM + zzz; +-- zzzz +SELECT + * +FROM + yyy; +-- yyyy +-- hage -- diff --git a/internal/formatter/testdata/002.sql b/internal/formatter/testdata/002.sql new file mode 100644 index 0000000..2106699 --- /dev/null +++ b/internal/formatter/testdata/002.sql @@ -0,0 +1,4 @@ + -- hoge -- +SELECT x/*x*/, /*x*/y FROM zzz; -- zzzz +SELECT * FROM yyy; -- yyyy + -- hage -- diff --git a/internal/formatter/testdata/003.golden b/internal/formatter/testdata/003.golden new file mode 100644 index 0000000..b09ee57 --- /dev/null +++ b/internal/formatter/testdata/003.golden @@ -0,0 +1,28 @@ +-- hoge -- +SELECT + x/*x*/, + /*x*/y + FROM + zzz; +-- zzzz +SELECT + * + FROM + yyy; +-- yyyy +-- hage -- +SELECT + ap.autograph_purchase_id AS "id", + ap.order_number AS "order", + ap.product_price AS "productPrice", + i.name AS "influencerName", + p.name AS "productName", + u.email AS "email" +FROM + autograph_purchaseASap innser +JOIN influencer AS i + ON autograph_purchase.influencer_id = influencer.influencer_id +LEFT JOIN product AS p + ON product.product_id = autograph_purchase.product_id +LEFT JOIN USER AS u + ON USER.user_id = autograph_purchase.user_id diff --git a/internal/formatter/testdata/003.ignroe b/internal/formatter/testdata/003.ignroe new file mode 100644 index 0000000..e69de29 diff --git a/internal/formatter/testdata/003.sql b/internal/formatter/testdata/003.sql new file mode 100644 index 0000000..540808c --- /dev/null +++ b/internal/formatter/testdata/003.sql @@ -0,0 +1,15 @@ +SELECT + ap.autograph_purchase_id AS "id", + ap.order_number AS "order", + ap.product_price AS "productPrice", + i.name AS "influencerName", + p.name AS "productName", + u.email AS "email" +FROM + autograph_purchaseASap innser +JOIN influencer AS i + ON autograph_purchase.influencer_id = influencer.influencer_id +LEFT JOIN product AS p + ON product.product_id = autograph_purchase.product_id +LEFT JOIN USER1 AS u + ON USER1.user_id = autograph_purchase.user_id