diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 7f820f7..bde69c2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/setup-go@v5 with: go-version: stable - - uses: golangci/golangci-lint-action@v4 + - uses: golangci/golangci-lint-action@v6 with: version: v1.62.2 @@ -41,6 +41,9 @@ jobs: - name: Test code run: go test -race -v ./... + - name: Run + run: go run ./cmd/wsl/ ./... + coverage: runs-on: ubuntu-latest steps: diff --git a/.golangci.yml b/.golangci.yml index 786b50c..6a349af 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -59,7 +59,6 @@ linters: - paralleltest - prealloc - rowserrcheck - - tparallel - testpackage - varnamelen - wastedassign @@ -68,5 +67,4 @@ issues: exclude-use-default: true max-issues-per-linter: 0 max-same-issues: 0 - # vim: set sw=2 ts=2 et: diff --git a/analyzer.go b/analyzer.go index 46d5019..9de53c3 100644 --- a/analyzer.go +++ b/analyzer.go @@ -3,6 +3,7 @@ package wsl import ( "flag" "go/ast" + "go/token" "strings" "golang.org/x/tools/go/analysis" @@ -82,7 +83,7 @@ func (wa *wslAnalyzer) run(pass *analysis.Pass) (interface{}, error) { continue } - filename := pass.Fset.PositionFor(file.Pos(), false).Filename + filename := getFilename(pass.Fset, file) if !strings.HasSuffix(filename, ".go") { continue } @@ -127,7 +128,7 @@ type multiStringValue struct { // Set implements the flag.Value interface and will overwrite the pointer to the // slice with a new pointer after splitting the flag by comma. func (m *multiStringValue) Set(value string) error { - s := []string{} + var s []string for _, v := range strings.Split(value, ",") { s = append(s, strings.TrimSpace(v)) @@ -146,3 +147,12 @@ func (m *multiStringValue) String() string { return strings.Join(*m.slicePtr, ", ") } + +func getFilename(fset *token.FileSet, file *ast.File) string { + filename := fset.PositionFor(file.Pos(), true).Filename + if !strings.HasSuffix(filename, ".go") { + return fset.PositionFor(file.Pos(), false).Filename + } + + return filename +} diff --git a/go.mod b/go.mod index be3cd12..aaafe53 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,7 @@ module github.com/bombsimon/wsl/v4 -go 1.21 +go 1.22 require golang.org/x/tools v0.17.0 -require ( - golang.org/x/mod v0.15.0 // indirect - golang.org/x/sys v0.17.0 // indirect -) +require golang.org/x/mod v0.15.0 // indirect diff --git a/go.sum b/go.sum index bdce42b..f3a7dec 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,6 @@ -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= diff --git a/testdata/src/default_config/cgo.go b/testdata/src/default_config/cgo.go new file mode 100644 index 0000000..56f8905 --- /dev/null +++ b/testdata/src/default_config/cgo.go @@ -0,0 +1,42 @@ +package testpkg + +/* + #include + #include + + void myprint(char* s) { + printf("%d\n", s); + } +*/ +import "C" + +import ( + "unsafe" +) + +func _() { + cs := C.CString("Hello from stdio\n") + C.myprint(cs) + C.free(unsafe.Pointer(cs)) +} + +func Advanced() { + var foo = 1 + var bar = 2 // want "declarations should never be cuddled" + var biz int // want "declarations should never be cuddled" + + x := []string{} + x = append(x, "literal") + notUsed := "just assigning, don't mind me" + x = append(x, "not z..") // want "append only allowed to cuddle with appended value" + useMe := "right away" + alsoNotUsed := ":(" + x = append(x, "just noise") // want "append only allowed to cuddle with appended value" + x = append(x, useMe) + + _ = foo + _ = bar + _ = biz + _ = notUsed + _ = alsoNotUsed +} diff --git a/testdata/src/default_config/cgo.go.golden b/testdata/src/default_config/cgo.go.golden new file mode 100644 index 0000000..5789e81 --- /dev/null +++ b/testdata/src/default_config/cgo.go.golden @@ -0,0 +1,46 @@ +package testpkg + +/* + #include + #include + + void myprint(char* s) { + printf("%d\n", s); + } +*/ +import "C" + +import ( + "unsafe" +) + +func _() { + cs := C.CString("Hello from stdio\n") + C.myprint(cs) + C.free(unsafe.Pointer(cs)) +} + +func Advanced() { + var foo = 1 + + var bar = 2 // want "declarations should never be cuddled" + + var biz int // want "declarations should never be cuddled" + + x := []string{} + x = append(x, "literal") + notUsed := "just assigning, don't mind me" + + x = append(x, "not z..") // want "append only allowed to cuddle with appended value" + useMe := "right away" + alsoNotUsed := ":(" + + x = append(x, "just noise") // want "append only allowed to cuddle with appended value" + x = append(x, useMe) + + _ = foo + _ = bar + _ = biz + _ = notUsed + _ = alsoNotUsed +} diff --git a/testdata/src/default_config/line_directive.go b/testdata/src/default_config/line_directive.go new file mode 100644 index 0000000..d7e1ed7 --- /dev/null +++ b/testdata/src/default_config/line_directive.go @@ -0,0 +1,41 @@ +//line line_directive.tmpl:1 +package pkg + +import ( + "fmt" + + "golang.org/x/tools/go/analysis" +) + +func _() { + var x int + _ = x + x = 0 // x +} + +func main() { + a() + b() + wsl() +} + +func a() { + fmt.Println("foo") +} + +func b() { + fmt.Println("foo") +} + +func c() { + _ = analysis.Analyzer{} +} + +// want +1 "block should not start with a whitespace" +func wsl() bool { + + return true +} + +func notFormatted() { +} diff --git a/testdata/src/default_config/line_directive.go.golden b/testdata/src/default_config/line_directive.go.golden new file mode 100644 index 0000000..846c1ba --- /dev/null +++ b/testdata/src/default_config/line_directive.go.golden @@ -0,0 +1,40 @@ +//line line_directive.tmpl:1 +package pkg + +import ( + "fmt" + + "golang.org/x/tools/go/analysis" +) + +func _() { + var x int + _ = x + x = 0 // x +} + +func main() { + a() + b() + wsl() +} + +func a() { + fmt.Println("foo") +} + +func b() { + fmt.Println("foo") +} + +func c() { + _ = analysis.Analyzer{} +} + +// want +1 "block should not start with a whitespace" +func wsl() bool { + return true +} + +func notFormatted() { +} diff --git a/testdata/src/default_config/line_directive.tmpl b/testdata/src/default_config/line_directive.tmpl new file mode 100644 index 0000000..082dc6f --- /dev/null +++ b/testdata/src/default_config/line_directive.tmpl @@ -0,0 +1 @@ +# This is a template file for some code generator, and is not a valid go source file. diff --git a/wsl.go b/wsl.go index 76f4abf..44c7abe 100644 --- a/wsl.go +++ b/wsl.go @@ -353,7 +353,7 @@ func (p *processor) parseBlockStatements(statements []ast.Stmt) { return false } - for j := 0; j < n; j++ { + for j := range n { s1 := statements[i+j] s2 := statements[i+j+1] @@ -1113,8 +1113,8 @@ func (p *processor) findLeadingAndTrailingWhitespaces(ident *ast.Ident, stmt, ne return } - blockStartLine = p.fileSet.PositionFor(blockStartPos, false).Line - blockEndLine = p.fileSet.PositionFor(blockEndPos, false).Line + blockStartLine = p.fileSet.Position(blockStartPos).Line + blockEndLine = p.fileSet.Position(blockEndPos).Line // No whitespace possible if LBrace and RBrace is on the same line. if blockStartLine == blockEndLine { @@ -1362,14 +1362,14 @@ func isExampleFunc(ident *ast.Ident) bool { } func (p *processor) nodeStart(node ast.Node) int { - return p.fileSet.PositionFor(node.Pos(), false).Line + return p.fileSet.Position(node.Pos()).Line } func (p *processor) nodeEnd(node ast.Node) int { - line := p.fileSet.PositionFor(node.End(), false).Line + line := p.fileSet.Position(node.End()).Line if isEmptyLabeledStmt(node) { - return p.fileSet.PositionFor(node.Pos(), false).Line + return p.fileSet.Position(node.Pos()).Line } return line @@ -1408,7 +1408,7 @@ func (p *processor) addErrorRange(reportAt, start, end token.Pos, reason string) } func (p *processor) addWarning(w string, pos token.Pos, t interface{}) { - position := p.fileSet.PositionFor(pos, false) + position := p.fileSet.Position(pos) p.warnings = append(p.warnings, fmt.Sprintf("%s:%d: %s (%T)", position.Filename, position.Line, w, t), diff --git a/wsl_test.go b/wsl_test.go index 78243be..b845657 100644 --- a/wsl_test.go +++ b/wsl_test.go @@ -15,6 +15,8 @@ func TestWIP(t *testing.T) { } func TestDefaultConfig(t *testing.T) { + t.Parallel() + testdata := analysistest.TestData() testCases := []struct {