Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.PHONY: code_gen format go_lint go_lint_fix go_mod_tidy lint sqlc sql_lint sql_lint_fix vendor sql_whitespace_dry_run sql_whitespace_fix
# Sort targets alphabetically.
.PHONY: code_gen format go_lint go_lint_fix go_mod_tidy lint multiline_sql_strings_lint_fix sqlc sql_lint sql_lint_fix vendor

code_gen: go_mod_tidy sqlc

Expand All @@ -11,9 +12,12 @@ go_lint_fix:
go_mod_tidy:
go mod tidy

lint: go_lint sql_lint
lint: go_lint multiline_sql_strings_lint_fix sql_lint

lint_fix: go_lint_fix sql_lint_fix
lint_fix: go_lint_fix multiline_sql_strings_lint_fix sql_lint_fix

multiline_sql_strings_lint_fix:
go run ./scripts/lint/multiline_sql_strings_lint.go --fix

sqlc:
cd internal/queries && sqlc generate
Expand All @@ -25,11 +29,4 @@ sql_lint_fix:
sqlfluff fix

vendor:
go mod vendor

sql_whitespace_dry_run:
go run ./scripts/acceptance_test_sql_linter/main.go

sql_whitespace_fix:
go run ./scripts/acceptance_test_sql_linter/main.go --fix

go mod vendor
167 changes: 0 additions & 167 deletions scripts/acceptance_test_sql_linter/main.go

This file was deleted.

126 changes: 126 additions & 0 deletions scripts/lint/multiline_sql_strings_lint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package main

import (
"bufio"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
)

func main() {
var rootCmd = &cobra.Command{
Use: "multiline-sql-strings-lint",
Short: "Lints multiline sql strings, replacing tabs with spaces",
}
dirPath := rootCmd.Flags().String("dir", "./internal/migration_acceptance_tests", "Directory path containing files to process")
fix := rootCmd.Flags().Bool("fix", false, "Apply changes (without this flag, only shows what would change)")
rootCmd.RunE = func(cmd *cobra.Command, args []string) error {
if !*fix {
fmt.Println("Running in dry-run mode. Use --fix to apply changes.")
}

var filesRequiringChanges []string
if err := filepath.Walk(*dirPath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}

fi, err := os.Stat(path)
if err != nil {
return fmt.Errorf("os.Stat: %w", err)
}

if fi.IsDir() {
return nil
}

cr, err := processFile(path, *fix)
if err != nil {
return fmt.Errorf("processFile: %w", err)
}
if cr {
filesRequiringChanges = append(filesRequiringChanges, path)
}
return nil
}); err != nil {
return fmt.Errorf("filepath.Walk: %w", err)
}

if len(filesRequiringChanges) == 0 {
fmt.Println("No changes required!")
return nil
}

verb := "require changes"
if *fix {
verb = "fixed"
}
fmt.Printf("The following files %s:\n", verb)
for _, f := range filesRequiringChanges {
fmt.Printf(" - %s\n", f)
}
if !*fix {
// Return a non-zero exit code, since the linter failed, and fixes could not be applied.
os.Exit(1)
}
return nil
}
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

// processFile replaces tabs with spaces in multi-line comments (sql strings). It will return if changes need to be made
// and an error if any occurred. If fix is false, the files won't be updated.
func processFile(filePath string, fix bool) (bool, error) {
// Create a temporary file
tempFile, err := os.CreateTemp(filepath.Dir(filePath), "temp_*")
if err != nil {
return false, fmt.Errorf("failed to create temp file: %w", err)
}
defer os.Remove(tempFile.Name()) // Clean up in case of failure
defer tempFile.Close()

// Open source file for reading
srcFile, err := os.Open(filePath)
if err != nil {
return false, fmt.Errorf("failed to open source file: %w", err)
}
defer srcFile.Close()

scanner := bufio.NewScanner(srcFile)
writer := bufio.NewWriter(tempFile)

inMultilineString := false
changesRequired := false
for scanner.Scan() {
line := scanner.Text()
newLine := line
if inMultilineString && !strings.Contains(line, "`") && strings.Contains(line, "\t") {
changesRequired = true
newLine = strings.ReplaceAll(line, "\t", " ")
}
if _, err = writer.WriteString(newLine + "\n"); err != nil {
return false, fmt.Errorf("writing new line: %w", err)
}

if strings.Contains(line, "`") {
inMultilineString = !inMultilineString
}
}

if err := scanner.Err(); err != nil {
return false, fmt.Errorf("reading source file: %w", err)
}

if err := writer.Flush(); err != nil {
return false, fmt.Errorf("lush buffer: %w", err)
}

return changesRequired, os.Rename(tempFile.Name(), filePath)
}
Loading