whatcanGOwrong

This commit is contained in:
2024-09-19 21:38:24 -04:00
commit d0ae4d841d
17908 changed files with 4096831 additions and 0 deletions
@@ -0,0 +1,60 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
func f() {
foo :=
"bar"
foo :=
"bar"
_, _ =
0,
1
_, _ = 0,
1
_ =
`
foo
`
_ = /* inline */
"foo"
_ = // inline
"foo"
}
-- foo.go.golden --
package p
func f() {
foo := "bar"
foo := "bar"
_, _ = 0,
1
_, _ = 0,
1
_ = `
foo
`
_ = /* inline */ "foo"
_ = // inline
"foo"
}
@@ -0,0 +1,85 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
func f() {
if true {
// lone comment
}
{
}
{
// lone comment
}
type S struct {
// lone comment
}
type I interface {
// lone comment
}
}
type SOut struct {
// lone comment
}
type IOut interface {
// lone comment
}
-- foo.go.golden --
package p
func f() {
if true {
// lone comment
}
{
}
{
// lone comment
}
type S struct {
// lone comment
}
type I interface {
// lone comment
}
}
type SOut struct {
// lone comment
}
type IOut interface {
// lone comment
}
@@ -0,0 +1,118 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
func f() {
if true {
println()
}
for true {
println()
}
{
println(1, 2,
3, 4, `foo
bar`)
}
{
// comment directly before
println()
// comment after
}
{
// comment before
println()
// comment directly after
}
// For readability; the empty line helps separate the multi-line
// condition from the body.
if true &&
true {
println()
}
for true &&
true {
println()
}
if true &&
true {
// documented single statement
println()
}
}
-- foo.go.golden --
package p
func f() {
if true {
println()
}
for true {
println()
}
{
println(1, 2,
3, 4, `foo
bar`)
}
{
// comment directly before
println()
// comment after
}
{
// comment before
println()
// comment directly after
}
// For readability; the empty line helps separate the multi-line
// condition from the body.
if true &&
true {
println()
}
for true &&
true {
println()
}
if true &&
true {
// documented single statement
println()
}
}
@@ -0,0 +1,47 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
import "C"
import "os"
import `C`
import "os"
import "C"
import (
"io"
"utf8"
)
import `C`
import (
"io"
"utf8"
)
-- foo.go.golden --
package p
import "C"
import "os"
import "C"
import "os"
import "C"
import (
"io"
"utf8"
)
import "C"
import (
"io"
"utf8"
)
@@ -0,0 +1,140 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
//go:build tag
// +build tag
package p
//go:generate some command
//go:unknowndirective
//lint:disablefoo
//go-sumtype:decl Foo
//nolint
//nolint // explanation
//nolint:somelinter // explanation
//NOSONAR
//NOSONAR // explanation
//noinspection ALL
//noinspection foo,bar
//not actually: a directive
//https://just.one/url
//TODO: do something
//export CgoFunc
//extern open
func c_open(name *byte, mode int, perm int) int
//line 123
//sys Unlink(path string) (err error)
//sysnb Getpid() (pid int)
//foo is foo.
type foo int
// comment with a tab.
// comment with many spaces
//comment group
//123 numbers too
// comment group
//123 numbers too
//{
//this is probably code
//}
////////////
// ascii art
//----------
//
-- foo.go.golden --
//go:build tag
// +build tag
package p
//go:generate some command
//go:unknowndirective
//lint:disablefoo
//go-sumtype:decl Foo
//nolint
//nolint // explanation
//nolint:somelinter // explanation
//NOSONAR
//NOSONAR // explanation
//noinspection ALL
//noinspection foo,bar
// not actually: a directive
// https://just.one/url
// TODO: do something
//export CgoFunc
//extern open
func c_open(name *byte, mode int, perm int) int
//line 123
//sys Unlink(path string) (err error)
//sysnb Getpid() (pid int)
// foo is foo.
type foo int
// comment with a tab.
// comment with many spaces
// comment group
// 123 numbers too
// comment group
// 123 numbers too
//{
//this is probably code
//}
////////////
// ascii art
//----------
//
@@ -0,0 +1,109 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
var _ = []string{
"foo",
}
var _ = []string{
"foo",
}
var _ = []string{
// joint comment
"foo",
}
var _ = []string{
// separate comment
"foo",
}
var _ = map[string]string{
"foo": "bar",
}
var _ = map[string]string{
"foo": "bar",
}
var _ = map[string]string{
// joint comment
"foo": "bar",
}
var _ = map[string]string{
// separate comment
"foo": "bar",
}
var _ = map[string]string{
/*
joint comment
*/
"foo": "bar",
}
-- foo.go.golden --
package p
var _ = []string{
"foo",
}
var _ = []string{
"foo",
}
var _ = []string{
// joint comment
"foo",
}
var _ = []string{
// separate comment
"foo",
}
var _ = map[string]string{
"foo": "bar",
}
var _ = map[string]string{
"foo": "bar",
}
var _ = map[string]string{
// joint comment
"foo": "bar",
}
var _ = map[string]string{
// separate comment
"foo": "bar",
}
var _ = map[string]string{
/*
joint comment
*/
"foo": "bar",
}
@@ -0,0 +1,127 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
var _ = []int{}
var _ = []int{
}
var _ = []int{1, 2,
3, 4}
var _ = []int{
1, 2, 3, 4}
var _ = [][]string{{
"no need for more newlines",
"if wrapping a single expression",
}}
var _ = []string{`
no need for newlines
`, `
if no elements are surrounded by newlines
`}
var _ = []struct{ a int }{
{ // consistent
a: 1,
},
{
a: 2,
}, { // inconsistent
a: 3,
},
}
var _ = []struct{ a int }{{
a: 1,
}, {
a: 2,
}, {
a: 3,
}}
var _ interface{
}
func _(struct{
})
var _ = []interface {
}{1, 2, 3}
func _(
)
type T struct {
Foo // comment
Bar struct { // comment
}
}
-- foo.go.golden --
package p
var _ = []int{}
var _ = []int{}
var _ = []int{
1, 2,
3, 4,
}
var _ = []int{
1, 2, 3, 4,
}
var _ = [][]string{{
"no need for more newlines",
"if wrapping a single expression",
}}
var _ = []string{`
no need for newlines
`, `
if no elements are surrounded by newlines
`}
var _ = []struct{ a int }{
{ // consistent
a: 1,
},
{
a: 2,
},
{ // inconsistent
a: 3,
},
}
var _ = []struct{ a int }{{
a: 1,
}, {
a: 2,
}, {
a: 3,
}}
var _ interface{}
func _(struct{})
var _ = []interface{}{1, 2, 3}
func _()
type T struct {
Foo // comment
Bar struct { // comment
}
}
@@ -0,0 +1,99 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
var single = "foo"
var another = "bar"
const one = 'q'
const two = 'w'
const three = 'e'
const four = 'r'
var not = 'a'
var v1 = 's'
//go:embed hello.txt
var v2 = 'd'
var v1 = 's'
// comment line 1
// comment line 2
var v2 = 'd'
var v1 = "mixed"
const c1 = "mixed"
//go:embed hello.txt
var v1 = 's'
var v2 = 'd'
var v3 = 'd'
// comment
var v1 = 's'
var v2 = 'd'
/* comment */
var v3 = 'd'
const inline1 = "s1" // c1
const inline2 = "s2" // c2
const inline3 = "s3" // c3
-- foo.go.golden --
package p
var (
single = "foo"
another = "bar"
)
const (
one = 'q'
two = 'w'
three = 'e'
four = 'r'
)
var not = 'a'
var v1 = 's'
//go:embed hello.txt
var v2 = 'd'
var (
v1 = 's'
// comment line 1
// comment line 2
v2 = 'd'
)
var v1 = "mixed"
const c1 = "mixed"
//go:embed hello.txt
var v1 = 's'
var (
v2 = 'd'
v3 = 'd'
)
// comment
var (
v1 = 's'
v2 = 'd'
/* comment */
v3 = 'd'
)
const (
inline1 = "s1" // c1
inline2 = "s2" // c2
inline3 = "s3" // c3
)
@@ -0,0 +1,100 @@
exec gofumpt -w f1.go f2.go
cmp f1.go f1.go.golden
cmp f2.go f2.go.golden
exec gofumpt -d f1.go.golden f2.go.golden
! stdout .
-- f1.go --
package p
import "non-grouped"
import (
"grouped"
)
var single = "foo"
var (
// verbose is verbose.
verbose = "bar"
)
// This entire block has a comment.
var (
groupComment = "bar"
)
var (
multiple1 string
multiple2 string
)
const (
first = iota
)
var (
multiline = []string{
"foo",
"bar",
}
)
var (
foo = "foo"
// bar = "bar"
// baz = "baz"
)
-- f1.go.golden --
package p
import "non-grouped"
import (
"grouped"
)
var single = "foo"
// verbose is verbose.
var verbose = "bar"
// This entire block has a comment.
var (
groupComment = "bar"
)
var (
multiple1 string
multiple2 string
)
const (
first = iota
)
var multiline = []string{
"foo",
"bar",
}
var foo = "foo"
// bar = "bar"
// baz = "baz"
-- f2.go --
package p
func _() {
var (
_ int
)
}
-- f2.go.golden --
package p
func _() {
var _ int
}
@@ -0,0 +1,70 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
func f1() { println("single line") }
func f2() { println("single line") }
func f3() {
println("multiline")
}
func f4() {
println("multiline")
}
// l1 is a var.
var l1 = []int{
1, 2,
}
// l2 is a var.
var l2 = []int{
3, 4,
}
var (
s3 = `
ok if grouped together
`
s4 = `
ok if grouped together
`
)
var _ = "ok if either isn't multiline"
-- foo.go.golden --
package p
func f1() { println("single line") }
func f2() { println("single line") }
func f3() {
println("multiline")
}
func f4() {
println("multiline")
}
// l1 is a var.
var l1 = []int{
1, 2,
}
// l2 is a var.
var l2 = []int{
3, 4,
}
var (
s3 = `
ok if grouped together
`
s4 = `
ok if grouped together
`
)
var _ = "ok if either isn't multiline"
@@ -0,0 +1,26 @@
cp foo.orig.go foo.go
! exec gofumpt -w -r foo foo.go
stderr 'the rewrite flag is no longer available; use "gofmt -r" instead\n'
cmp foo.orig.go foo.go
exec gofumpt -w -s foo.go
stderr 'warning: -s is deprecated as it is always enabled\n'
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.orig.go --
package p
func f() {
println("foo")
}
-- foo.go.golden --
package p
func f() {
println("foo")
}
@@ -0,0 +1,102 @@
env GO_VERSION_TEST=go1.18.29
# First, test a local build of gofumpt resulting from 'git clone'.
# Its version will be inferred from VCS, but since we want a stable test,
# we mock the VCS information. Note that test binaries do not have VCS info.
# Data obtained from a real build while developing.
env GARBLE_TEST_BUILDSETTINGS='[{"Key":"vcs","Value":"git"},{"Key":"vcs.revision","Value":"8dda8068d9f339047fc1777b688afb66a0a0db17"},{"Key":"vcs.time","Value":"2022-07-27T15:58:40Z"},{"Key":"vcs.modified","Value":"true"}]'
exec gofumpt foo.go
cmp stdout foo.go.golden
exec gofumpt outdated.go
cmp stdout foo.go.golden
exec gofumpt -extra foo.go
cmp stdout foo.go.golden-extra
exec gofumpt -lang=1.0 foo.go
cmp stdout foo.go.golden-lang
exec gofumpt -d nochange.go
! stdout .
exec gofumpt -d foo.go.golden
! stdout .
exec gofumpt -d -extra foo.go.golden-extra
! stdout .
# A local build without VCS information will result in a missing version.
env GARBLE_TEST_BUILDSETTINGS='[]'
exec gofumpt foo.go
cmp stdout foo.go.golden-devel
[short] stop 'the rest of this test builds gofumpt binaries'
# We want a published version of gofumpt on the public module proxies,
# because that's the only way that its module version will be included.
# Using a directory replace directive will not work.
# This means that any change in how gofumpt reports its own version
# will require two pull requests, the second one updating the test script.
# We could consider using go-internal/goproxytest, but then we would need to
# manually run something like go-internal/cmd/txtar-addmod reguarly.
# Or teach goproxytest to serve a mock version of gofumpt from its local checkout.
# Either way, both are relatively overkill for now.
env GOBIN=${WORK}/bin
env GOFUMPT_PUBLISHED_VERSION=v0.3.2-0.20220627183521-8dda8068d9f3
# TODO: update these once the library fix hits master
# gofumpt as the main binary with a real module version.
go install mvdan.cc/gofumpt@${GOFUMPT_PUBLISHED_VERSION}
exec ${GOBIN}/gofumpt foo.go
cmp stdout foo.go.golden-released
# gofumpt as a library with a real module version.
cd ${GOMOD_DIR}/testdata/gofumpt-external
go install .
cd ${WORK}
stdin foo.go
exec ${GOBIN}/gofumpt-external
cmp stdout foo.go.golden-external
-- go.mod --
module test
go 1.16
-- foo.go --
package p
//gofumpt:diagnose
-- outdated.go --
package p
//gofumpt:diagnose v0.1.0
-- nochange.go --
package p
//gofumpt:diagnosefoobar
-- foo.go.golden --
package p
//gofumpt:diagnose version: v0.0.0-20220727155840-8dda8068d9f3 (go1.18.29) flags: -lang=v1.16 -modpath=test
-- foo.go.golden-devel --
package p
//gofumpt:diagnose version: (devel) (go1.18.29) flags: -lang=v1.16 -modpath=test
-- foo.go.golden-extra --
package p
//gofumpt:diagnose version: v0.0.0-20220727155840-8dda8068d9f3 (go1.18.29) flags: -lang=v1.16 -modpath=test -extra
-- foo.go.golden-lang --
package p
//gofumpt:diagnose version: v0.0.0-20220727155840-8dda8068d9f3 (go1.18.29) flags: -lang=v1.0 -modpath=test
-- foo.go.golden-released --
package p
//gofumpt:diagnose v0.3.2-0.20220627183521-8dda8068d9f3 -lang=v1.16 -modpath=test
-- foo.go.golden-external --
package p
//gofumpt:diagnose (devel) -lang=v1.16 -modpath=
@@ -0,0 +1,95 @@
# By default, this rule isn't enabled.
exec gofumpt foo.go
cmp stdout foo.go
# It's run with -extra.
exec gofumpt -extra foo.go
cmp stdout foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
type f func(x int, y int) int
type i interface {
add(x int, y int)
}
type s struct {
x int
y int
}
func mergeAdjacent(x int, y int) {}
func mergeThreeAdjacent(x int, y int, z int) {}
func mergeOneWithTwo(x, y int, z int) {}
func mergeTwoWithOne(x int, y, z int) {}
func mergeWithComment(
x int, y int, // comment
)
func mergeAllSyntax(x chan []*foo.Bar, y chan []*foo.Bar) {}
func dontMergeAnonymousParams(int, int) {}
func dontMergeMultipleLines(
x int,
y int,
) {
}
func dontMergeMultipleLines2(
x,
y int,
z int,
) {
}
-- foo.go.golden --
package p
type f func(x, y int) int
type i interface {
add(x, y int)
}
type s struct {
x int
y int
}
func mergeAdjacent(x, y int) {}
func mergeThreeAdjacent(x, y, z int) {}
func mergeOneWithTwo(x, y, z int) {}
func mergeTwoWithOne(x, y, z int) {}
func mergeWithComment(
x, y int, // comment
)
func mergeAllSyntax(x, y chan []*foo.Bar) {}
func dontMergeAnonymousParams(int, int) {}
func dontMergeMultipleLines(
x int,
y int,
) {
}
func dontMergeMultipleLines2(
x,
y int,
z int,
) {
}
@@ -0,0 +1,503 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
func f1() {
println("multiple")
println("statements")
}
func f2() {
// comment directly before
println()
// comment after
}
func _() {
f3 := func() {
println()
}
}
func multilineParams(p1 string,
p2 string) {
println("body")
}
func multilineParamsUnambiguous(p1 string,
p2 string,
) {
println("body")
}
func multilineParamsListNoReturn(
p1 string,
p2 string,
) {
println("body")
}
func multilineParamsListReturningNamedSingleValue(
p1 string,
p2 string,
) (err error) {
println("body")
return err
}
func multilineParamsListReturningSingleValue(
p1 string,
p2 string,
) error {
println("body")
return nil
}
func multilineParamsListReturningNamedMultiValues(
p1 string,
p2 string,
) (s string, err error) {
println("body")
return s, err
}
func multilineParamsListReturningMultiValues(
p1 string,
p2 string,
) (string, error) {
println("body")
return "", nil
}
func multilineParamsListReturningNamedMultiLineValuesList(
p1 string,
p2 string,
) (
s string,
err error,
) {
println("body")
return s, err
}
func multilineParamsListReturningMultiLineValues(
p1 string,
p2 string,
) (
string,
error,
) {
println("body")
return "", nil
}
func multilineParamsOneParamNoReturn(
p1 string,
) {
println("body")
}
func multilineParamsOneParamReturningNamedSingleValue(
p1 string,
) (err error) {
println("body")
return err
}
func multilineParamsOneParamReturningSingleValue(
p1 string,
) error {
println("body")
return nil
}
func multilineParamsOneParamReturningNamedMultiValues(
p1 string,
) (s string, err error) {
println("body")
return s, err
}
func multilineParamsOneParamReturningMultiValues(
p1 string,
) (string, error) {
println("body")
return "", nil
}
func multilineParamsOneParamReturningNamedMultiLineValuesList(
p1 string,
) (
s string,
err error,
) {
println("body")
return s, err
}
func multilineParamsOneParamReturningMultiLineValues(
p1 string,
) (
string,
error,
) {
println("body")
return "", nil
}
func multilineResults() (p1 string,
p2 string) {
println("body")
}
func multilineResultsUnambiguous() (p1 string,
p2 string,
) {
println("body")
}
func multilineNoFields(
) {
println("body")
}
func f(
foo int,
bar string,
/* baz */) {
body()
}
func f2(
foo int,
bar string,
) (
string,
error,
/* baz */) {
return "", nil
}
func multilineResultsMultipleEmptyLines() (p1 string,
p2 string) {
println("body")
}
func multilineParamsWithoutEmptyLine(p1 string,
p2 string) {
println("body")
}
func multilineParamsWithoutEmptyLineWithComment(p1 string,
p2 string) {
// comment
println("body")
}
// Same as the others above, but with a single result parameter without
// parentheses. This used to cause token.File.Offset crashes.
func f(p1 string,
p2 string) int {
println("body")
return 0
}
func a() {
f := func(s string,
b bool,
) {
// foo
}
}
func f(p1 string,
p2 string) (int, string,
/* baz */) {
println("body")
return 0, ""
}
-- foo.go.golden --
package p
func f1() {
println("multiple")
println("statements")
}
func f2() {
// comment directly before
println()
// comment after
}
func _() {
f3 := func() {
println()
}
}
func multilineParams(p1 string,
p2 string,
) {
println("body")
}
func multilineParamsUnambiguous(p1 string,
p2 string,
) {
println("body")
}
func multilineParamsListNoReturn(
p1 string,
p2 string,
) {
println("body")
}
func multilineParamsListReturningNamedSingleValue(
p1 string,
p2 string,
) (err error) {
println("body")
return err
}
func multilineParamsListReturningSingleValue(
p1 string,
p2 string,
) error {
println("body")
return nil
}
func multilineParamsListReturningNamedMultiValues(
p1 string,
p2 string,
) (s string, err error) {
println("body")
return s, err
}
func multilineParamsListReturningMultiValues(
p1 string,
p2 string,
) (string, error) {
println("body")
return "", nil
}
func multilineParamsListReturningNamedMultiLineValuesList(
p1 string,
p2 string,
) (
s string,
err error,
) {
println("body")
return s, err
}
func multilineParamsListReturningMultiLineValues(
p1 string,
p2 string,
) (
string,
error,
) {
println("body")
return "", nil
}
func multilineParamsOneParamNoReturn(
p1 string,
) {
println("body")
}
func multilineParamsOneParamReturningNamedSingleValue(
p1 string,
) (err error) {
println("body")
return err
}
func multilineParamsOneParamReturningSingleValue(
p1 string,
) error {
println("body")
return nil
}
func multilineParamsOneParamReturningNamedMultiValues(
p1 string,
) (s string, err error) {
println("body")
return s, err
}
func multilineParamsOneParamReturningMultiValues(
p1 string,
) (string, error) {
println("body")
return "", nil
}
func multilineParamsOneParamReturningNamedMultiLineValuesList(
p1 string,
) (
s string,
err error,
) {
println("body")
return s, err
}
func multilineParamsOneParamReturningMultiLineValues(
p1 string,
) (
string,
error,
) {
println("body")
return "", nil
}
func multilineResults() (p1 string,
p2 string,
) {
println("body")
}
func multilineResultsUnambiguous() (p1 string,
p2 string,
) {
println("body")
}
func multilineNoFields() {
println("body")
}
func f(
foo int,
bar string,
/* baz */
) {
body()
}
func f2(
foo int,
bar string,
) (
string,
error,
/* baz */
) {
return "", nil
}
func multilineResultsMultipleEmptyLines() (p1 string,
p2 string,
) {
println("body")
}
func multilineParamsWithoutEmptyLine(p1 string,
p2 string,
) {
println("body")
}
func multilineParamsWithoutEmptyLineWithComment(p1 string,
p2 string,
) {
// comment
println("body")
}
// Same as the others above, but with a single result parameter without
// parentheses. This used to cause token.File.Offset crashes.
func f(p1 string,
p2 string,
) int {
println("body")
return 0
}
func a() {
f := func(s string,
b bool,
) {
// foo
}
}
func f(p1 string,
p2 string) (int, string,
/* baz */) {
println("body")
return 0, ""
}
@@ -0,0 +1,45 @@
# Explicitly given generated files are formatted with our rules.
exec gofumpt foo.go
cmp stdout foo.go.golden
# stdin is still considered an explicit file.
stdin foo.go
exec gofumpt
cmp stdout foo.go.golden
# Implicitly walked generated files get formatted without the added rules.
exec gofumpt -l .
stdout -count=1 '^badgofmt.go$'
! stdout '^foo.go$'
! stderr .
-- badgofmt.go --
// Code generated by foo. DO NOT EDIT.
package foo
func f() {
println("body")
}
-- foo.go --
// foo is a package about bar.
// Code generated by foo. DO NOT EDIT.
package foo
func f() {
println("body")
}
-- foo.go.golden --
// foo is a package about bar.
// Code generated by foo. DO NOT EDIT.
package foo
func f() {
println("body")
}
@@ -0,0 +1,27 @@
# Test various edge cases with go.mod files.
[!go1.21] skip 'Go 1.20 or older cannot parse these go.mod files'
exec gofumpt toolchain-stable/a.go
stdout '//gofumpt:diagnose.* -lang=v1.21'
exec gofumpt toolchain-unstable/a.go
stdout '//gofumpt:diagnose.* -lang=v1.21'
-- toolchain-stable/go.mod --
module a
go 1.21.2
-- toolchain-stable/a.go --
package a
//gofumpt:diagnose
-- toolchain-unstable/go.mod --
module a
go 1.21rc3
-- toolchain-unstable/a.go --
package a
//gofumpt:diagnose
@@ -0,0 +1,55 @@
exec gofumpt orig.go.golden
cp stdout formatted.go.golden
mkdir -p vendor/foo testdata/foo
cp orig.go.golden vendor/foo/foo.go
cp orig.go.golden testdata/foo/foo.go
# format explicit dirs
exec gofumpt -l vendor testdata
stdout -count=1 'vendor[/\\]foo[/\\]foo.go'
stdout -count=1 'testdata[/\\]foo[/\\]foo.go'
! stderr .
# format explicit files
exec gofumpt -l vendor/foo/foo.go testdata/foo/foo.go
stdout -count=1 'vendor[/\\]foo[/\\]foo.go'
stdout -count=1 'testdata[/\\]foo[/\\]foo.go'
! stderr .
# ignore implicit dirs via fs walking
exec gofumpt -l .
! stdout .
! stderr .
# format explicit pkg while ignoring rest
mkdir vendor/ignore testdata/ignore
cp orig.go.golden vendor/ignore/ignore.go
cp orig.go.golden testdata/ignore/ignore.go
exec gofumpt -l vendor/foo testdata/foo .
stdout -count=1 'vendor[/\\]foo[/\\]foo.go'
stdout -count=1 'testdata[/\\]foo[/\\]foo.go'
! stderr .
# format explicit dirs without clean paths
exec gofumpt -l $WORK//vendor ./testdata/./
stdout -count=1 'vendor[/\\]foo[/\\]foo.go'
stdout -count=1 'testdata[/\\]foo[/\\]foo.go'
! stderr .
-- orig.go.golden --
package p
func f() {
if true {
// lone comment
}
{
}
{
// lone comment
}
}
@@ -0,0 +1,208 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
type i1 interface {
a(x int) int
b(x int) int
c(x int) int
D()
E()
f()
}
type i2 interface {
// comment for a
a(x int) int
// comment between a and b
// comment for b
b(x int) int
// comment between b and c
c(x int) int
d(x int) int
// comment for e
e(x int) int
}
type i3 interface {
a(x int) int
// standalone comment
b(x int) int
}
type leadingLine1 interface {
a(x int) int
}
type leadingLine2 interface {
a(x int) int
}
type leadingLine3 interface {
// comment
a(x int) int
}
type leadingLine4 interface {
// comment
a(x int) int
}
type leadingLine5 interface {
// comment
// comment for a
a(x int) int
}
type leadingLine6 interface {
// comment
// comment for a
a(x int) int
}
type leadingLine7 interface {
// comment
// comment for a
a(x int) int
}
type leadingLine8 interface {
// comment
}
type ii1 interface {
DoA()
DoB()
UndoA()
UndoB()
}
-- foo.go.golden --
package p
type i1 interface {
a(x int) int
b(x int) int
c(x int) int
D()
E()
f()
}
type i2 interface {
// comment for a
a(x int) int
// comment between a and b
// comment for b
b(x int) int
// comment between b and c
c(x int) int
d(x int) int
// comment for e
e(x int) int
}
type i3 interface {
a(x int) int
// standalone comment
b(x int) int
}
type leadingLine1 interface {
a(x int) int
}
type leadingLine2 interface {
a(x int) int
}
type leadingLine3 interface {
// comment
a(x int) int
}
type leadingLine4 interface {
// comment
a(x int) int
}
type leadingLine5 interface {
// comment
// comment for a
a(x int) int
}
type leadingLine6 interface {
// comment
// comment for a
a(x int) int
}
type leadingLine7 interface {
// comment
// comment for a
a(x int) int
}
type leadingLine8 interface {
// comment
}
type ii1 interface {
DoA()
DoB()
UndoA()
UndoB()
}
@@ -0,0 +1,173 @@
# Line directives can throw off our use of MergeLines.
# We should ignore them entirely when calculating line numbers.
# The file below is borrowed from Go's test/dwarf/linedirectives.go.
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
-- foo.go --
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//line foo/bar.y:4
package main
//line foo/bar.y:60
func main() {
//line foo/bar.y:297
f, l := 0, 0
//line yacctab:1
f, l = 1, 1
//line yaccpar:1
f, l = 2, 1
//line foo/bar.y:82
f, l = 3, 82
//line foo/bar.y:90
f, l = 3, 90
//line foo/bar.y:92
f, l = 3, 92
//line foo/bar.y:100
f, l = 3, 100
//line foo/bar.y:104
l = 104
//line foo/bar.y:112
l = 112
//line foo/bar.y:117
l = 117
//line foo/bar.y:121
l = 121
//line foo/bar.y:125
l = 125
//line foo/bar.y:133
l = 133
//line foo/bar.y:146
l = 146
//line foo/bar.y:148
//line foo/bar.y:153
//line foo/bar.y:155
l = 155
//line foo/bar.y:160
//line foo/bar.y:164
//line foo/bar.y:173
//line foo/bar.y:178
//line foo/bar.y:180
//line foo/bar.y:185
//line foo/bar.y:195
//line foo/bar.y:197
//line foo/bar.y:202
//line foo/bar.y:204
//line foo/bar.y:208
//line foo/bar.y:211
//line foo/bar.y:213
//line foo/bar.y:215
//line foo/bar.y:217
//line foo/bar.y:221
//line foo/bar.y:229
//line foo/bar.y:236
//line foo/bar.y:238
//line foo/bar.y:240
//line foo/bar.y:244
//line foo/bar.y:249
//line foo/bar.y:253
//line foo/bar.y:257
//line foo/bar.y:262
//line foo/bar.y:267
//line foo/bar.y:272
if l == f {
//line foo/bar.y:277
panic("aie!")
//line foo/bar.y:281
}
//line foo/bar.y:285
return
//line foo/bar.y:288
//line foo/bar.y:290
}
//line foo/bar.y:293
//line foo/bar.y:295
-- foo.go.golden --
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//line foo/bar.y:4
package main
//line foo/bar.y:60
func main() {
//line foo/bar.y:297
f, l := 0, 0
//line yacctab:1
f, l = 1, 1
//line yaccpar:1
f, l = 2, 1
//line foo/bar.y:82
f, l = 3, 82
//line foo/bar.y:90
f, l = 3, 90
//line foo/bar.y:92
f, l = 3, 92
//line foo/bar.y:100
f, l = 3, 100
//line foo/bar.y:104
l = 104
//line foo/bar.y:112
l = 112
//line foo/bar.y:117
l = 117
//line foo/bar.y:121
l = 121
//line foo/bar.y:125
l = 125
//line foo/bar.y:133
l = 133
//line foo/bar.y:146
l = 146
//line foo/bar.y:148
//line foo/bar.y:153
//line foo/bar.y:155
l = 155
//line foo/bar.y:160
//line foo/bar.y:164
//line foo/bar.y:173
//line foo/bar.y:178
//line foo/bar.y:180
//line foo/bar.y:185
//line foo/bar.y:195
//line foo/bar.y:197
//line foo/bar.y:202
//line foo/bar.y:204
//line foo/bar.y:208
//line foo/bar.y:211
//line foo/bar.y:213
//line foo/bar.y:215
//line foo/bar.y:217
//line foo/bar.y:221
//line foo/bar.y:229
//line foo/bar.y:236
//line foo/bar.y:238
//line foo/bar.y:240
//line foo/bar.y:244
//line foo/bar.y:249
//line foo/bar.y:253
//line foo/bar.y:257
//line foo/bar.y:262
//line foo/bar.y:267
//line foo/bar.y:272
if l == f {
//line foo/bar.y:277
panic("aie!")
//line foo/bar.y:281
}
//line foo/bar.y:285
return
//line foo/bar.y:288
//line foo/bar.y:290
}
//line foo/bar.y:293
//line foo/bar.y:295
@@ -0,0 +1,157 @@
cp foo.go foo.go.orig
exec gofumpt -w foo.go
cmp foo.go foo.go.orig
env GOFUMPT_SPLIT_LONG_LINES=on
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
func _() {
if err := f(argument1, argument2, argument3, argument4, argument5, argument6, argument7, argument8, argument9, argument10); err != nil {
panic(err)
}
// Tiny arguments to ensure the length calculation is right.
if err := f(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); err != nil {
panic(err)
}
// These wouldn't take significantly less horizontal space if split.
f(x, "one single very very very very very very very very very very very very very very very very long literal")
if err := f(x, "one single very very very very very very very very very very very very very very very very long literal"); err != nil {
panic(err)
}
{
{
{
{
println("first", "one single very very very very very very very very very very very very very long literal")
}
}
}
}
// Allow splitting at the start of sub-lists too.
if err := f(argument1, argument2, argument3, argument4, someComplex{argument5, argument6, argument7, argument8, argument9, argument10}); err != nil {
panic(err)
}
if err := f(argument1, argument2, argument3, argument4, &someComplex{argument5, argument6, argument7, argument8, argument9, argument10}); err != nil {
panic(err)
}
if err := f(argument1, argument2, argument3, argument4, []someSlice{argument5, argument6, argument7, argument8, argument9, argument10}); err != nil {
panic(err)
}
// Allow splitting "lists" of binary expressions.
if boolean1 && boolean2 && boolean3 && boolean4 && boolean5 && boolean6 && boolean7 && boolean8 && boolean9 && boolean10 && boolean11 {
}
// Over 100, and we split in a way that doesn't break "len(" off.
if boolean1 || boolean2 || boolean3 || boolean4 || len(someVeryLongVarName.SomeVeryLongSelector) > 0 {
}
}
// Note that function declarations have a higher limit of 120.
// This line goes beyond the limit of 120, but splitting it would leave the
// following line with just 20 non-indentation characters. Not worth it.
func LongButNotWorthSplitting(argument1, argument2, argument3, argument4, argument5, argument6, argument7, argument8, argument9 int) bool {
}
// This line goes well past the limit and it should be split.
// Note that it has a nested func type in a parameter.
func TooLongWithFuncParam(fn func(int) (int, error), argument1, argument2, argument3, argument4, argument5, argument6, argument7, argument8, argument9, argument10 int) bool {
}
// This is like LongButNotWorthSplitting, but with a func parameter.
func LongButNotWorthSplitting2(fn func(int) (int, error), argument3, argument4, argument5, argument6, argument7, argument8, argument9 int) bool {
}
// Never split result parameter lists, as that could easily add confusion with
// extra input parameters.
func NeverSplitResults(argument1, argument2, argument3, argument4, argument5 int) (result1 int, result2, result3, result4, result5, result6, result7, result8 bool) {
}
-- foo.go.golden --
package p
func _() {
if err := f(argument1, argument2, argument3, argument4, argument5, argument6, argument7,
argument8, argument9, argument10); err != nil {
panic(err)
}
// Tiny arguments to ensure the length calculation is right.
if err := f(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10); err != nil {
panic(err)
}
// These wouldn't take significantly less horizontal space if split.
f(x, "one single very very very very very very very very very very very very very very very very long literal")
if err := f(x, "one single very very very very very very very very very very very very very very very very long literal"); err != nil {
panic(err)
}
{
{
{
{
println("first", "one single very very very very very very very very very very very very very long literal")
}
}
}
}
// Allow splitting at the start of sub-lists too.
if err := f(argument1, argument2, argument3, argument4, someComplex{
argument5, argument6, argument7, argument8, argument9, argument10,
}); err != nil {
panic(err)
}
if err := f(argument1, argument2, argument3, argument4, &someComplex{
argument5, argument6, argument7, argument8, argument9, argument10,
}); err != nil {
panic(err)
}
if err := f(argument1, argument2, argument3, argument4, []someSlice{
argument5, argument6, argument7, argument8, argument9, argument10,
}); err != nil {
panic(err)
}
// Allow splitting "lists" of binary expressions.
if boolean1 && boolean2 && boolean3 && boolean4 && boolean5 && boolean6 && boolean7 &&
boolean8 && boolean9 && boolean10 && boolean11 {
}
// Over 100, and we split in a way that doesn't break "len(" off.
if boolean1 || boolean2 || boolean3 || boolean4 ||
len(someVeryLongVarName.SomeVeryLongSelector) > 0 {
}
}
// Note that function declarations have a higher limit of 120.
// This line goes beyond the limit of 120, but splitting it would leave the
// following line with just 20 non-indentation characters. Not worth it.
func LongButNotWorthSplitting(argument1, argument2, argument3, argument4, argument5, argument6, argument7, argument8, argument9 int) bool {
}
// This line goes well past the limit and it should be split.
// Note that it has a nested func type in a parameter.
func TooLongWithFuncParam(fn func(int) (int, error), argument1, argument2, argument3, argument4,
argument5, argument6, argument7, argument8, argument9, argument10 int) bool {
}
// This is like LongButNotWorthSplitting, but with a func parameter.
func LongButNotWorthSplitting2(fn func(int) (int, error), argument3, argument4, argument5, argument6, argument7, argument8, argument9 int) bool {
}
// Never split result parameter lists, as that could easily add confusion with
// extra input parameters.
func NeverSplitResults(argument1, argument2, argument3, argument4, argument5 int) (result1 int, result2, result3, result4, result5, result6, result7, result8 bool) {
}
@@ -0,0 +1,8 @@
# A missing import shouldn't matter nor be fixed by gofumpt.
exec gofumpt foo.go
cmp stdout foo.go
-- foo.go --
package p
var _ bytes.Buffer
@@ -0,0 +1,115 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
var Do1 func() error
var Do2 func() (int, error)
func f() {
n1, err := Do2()
if err != nil {
panic(err)
}
if n2, err := Do2(); err != nil {
panic(err)
}
n3, err := Do2()
if err != nil {
panic(err)
}
select {
default:
err := Do1()
if err != nil {
panic(err)
}
}
n4, err := Do2()
if err != nil && err.Error() == "complex condition" {
panic(err)
}
err1 := Do1()
if err != nil {
panic(err)
}
{
if err != nil {
panic(err)
}
}
n5, err = Do2()
if err != nil {
panic(err)
}
}
-- foo.go.golden --
package p
var Do1 func() error
var Do2 func() (int, error)
func f() {
n1, err := Do2()
if err != nil {
panic(err)
}
if n2, err := Do2(); err != nil {
panic(err)
}
n3, err := Do2()
if err != nil {
panic(err)
}
select {
default:
err := Do1()
if err != nil {
panic(err)
}
}
n4, err := Do2()
if err != nil && err.Error() == "complex condition" {
panic(err)
}
err1 := Do1()
if err != nil {
panic(err)
}
{
if err != nil {
panic(err)
}
}
n5, err = Do2()
if err != nil {
panic(err)
}
}
@@ -0,0 +1,60 @@
# Initially, the Go language version is too low.
exec gofumpt -l .
! stdout .
# We can give an explicitly newer version.
exec gofumpt -lang=1.13 -l .
stdout -count=1 'foo\.go'
stdout -count=1 'nested[/\\]nested\.go'
# If we bump the version in go.mod, it should be picked up.
exec go mod edit -go=1.13
exec gofumpt -l .
stdout -count=1 'foo\.go'
! stdout 'nested'
# Ensure we produce the output we expect, and that it's stable.
exec gofumpt foo.go
cmp stdout foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
# We can give an explicitly older version, too
exec gofumpt -lang=1.0 -l .
! stdout .
-- go.mod --
module test
go 1.12
-- foo.go --
package p
const (
i = 0
j = 022
k = 0o_7_5_5
l = 1022
)
-- foo.go.golden --
package p
const (
i = 0
j = 0o22
k = 0o_7_5_5
l = 1022
)
-- nested/go.mod --
module nested
go 1.11
-- nested/nested.go --
package p
const (
i = 0
j = 022
k = 0o_7_5_5
l = 1022
)
@@ -0,0 +1,157 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
func f(r rune) {
switch r {
case 'a',
'b',
'c':
case 'd', 'e', 'f':
case 'a', 'b',
'c':
case 'v', 'e', 'r', 'y', 'l', 'o', 'n', 'g',
'l', 'i', 's', 't', '.', '.', '.':
// before
case 'a',
'b': // inline
// after
case 'a', // middle
'b':
case 'a', 'b', 'c', 'd', 'e', 'f',
'g': // very very long inline comment at the end
case 'a', 'b', 'c',
'd': // short comment
}
{
{
{
{
{
switch r {
case 'i', 'n', 'd', 'e',
'n', 't', 'e', 'd':
}
}
}
}
}
}
}
func s(x int) {
switch x {
case
shortConstant1,
shortConstant2:
// A comment.
fmt.Println(x)
case
shortConstant3,
shortConstant4:
// Do nothing.
default:
// Another comment.
fmt.Println(x * 2)
}
}
func s(x int) {
switch x {
case
longerConstantName1,
longerConstantName2:
// A comment.
fmt.Println(x)
case
longerConstantName3,
longerConstantName4:
// Do nothing.
default:
// Another comment.
fmt.Println(x * 2)
}
}
-- foo.go.golden --
package p
func f(r rune) {
switch r {
case 'a', 'b', 'c':
case 'd', 'e', 'f':
case 'a', 'b', 'c':
case 'v', 'e', 'r', 'y', 'l', 'o', 'n', 'g',
'l', 'i', 's', 't', '.', '.', '.':
// before
case 'a', 'b': // inline
// after
case 'a', // middle
'b':
case 'a', 'b', 'c', 'd', 'e', 'f',
'g': // very very long inline comment at the end
case 'a', 'b', 'c', 'd': // short comment
}
{
{
{
{
{
switch r {
case 'i', 'n', 'd', 'e',
'n', 't', 'e', 'd':
}
}
}
}
}
}
}
func s(x int) {
switch x {
case shortConstant1, shortConstant2:
// A comment.
fmt.Println(x)
case shortConstant3, shortConstant4:
// Do nothing.
default:
// Another comment.
fmt.Println(x * 2)
}
}
func s(x int) {
switch x {
case
longerConstantName1,
longerConstantName2:
// A comment.
fmt.Println(x)
case
longerConstantName3,
longerConstantName4:
// Do nothing.
default:
// Another comment.
fmt.Println(x * 2)
}
}
@@ -0,0 +1,48 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- foo.go --
package p
var global = x
func f() {
var local = x
var local2, local3 = x, y
var onlyType T
var typeAndVar T = x
var _ = unused
var (
aligned = x
vars = y
here = y
)
}
-- foo.go.golden --
package p
var global = x
func f() {
local := x
local2, local3 := x, y
var onlyType T
var typeAndVar T = x
_ = unused
var (
aligned = x
vars = y
here = y
)
}
@@ -0,0 +1,42 @@
# gofumpt changes -s to default to true.
exec gofumpt foo.go
cmp stdout foo.go.golden
-- foo.go --
package p
const ()
const (
// Comment
)
type ()
type (
// Comment
)
var ()
var (
// Comment
)
var _ = [][]int{[]int{1}}
-- foo.go.golden --
package p
const (
// Comment
)
type (
// Comment
)
var (
// Comment
)
var _ = [][]int{{1}}
@@ -0,0 +1,193 @@
exec gofumpt -w foo.go
cmp foo.go foo.go.golden
exec gofumpt -d foo.go.golden
! stdout .
-- go.mod --
module nodomainmod/mod1
go 1.16
-- foo.go --
package p
import (
"io"
"io/ioutil" // if the user keeps them in the top group, obey that
_ "io/ioutil"
_ "image/png"
"bufio" // the above is for a side effect; this one has a comment
)
import (
"os"
"foo.local/one"
bytes_ "bytes"
"io"
)
import (
"foo.local/two"
"fmt"
)
// If they are in order, but with extra newlines, join them.
import (
"more"
"std"
)
// We need to split std vs non-std in this case too.
import (
"foo.local"
"foo.local/three"
math "math"
)
import (
"x"
// don't mess up this comment
"y"
// or many
// of them
"z"
)
// This used to crash gofumpt, as there's no space to insert an extra newline.
import (
"std"
"non.std/pkg"
)
// All of the extra imports below are known to not belong in std.
// For example/ and test/, see https://golang.org/issue/37641.
import (
"io"
"example/foo"
"internal/bar"
"test/baz"
)
import (
"io"
"nodomainmod"
"nodomainmod/mod1/pkg1"
"nodomainmod/mod2"
"nodomainmodextra"
)
import (
"io"
"nodomainother/mod.withdot/pkg1"
)
// TODO: fix issue 225.
import (
"path/filepath"
"time"
"github.com/tinkerbell/tink/pkg/apis/core/v1alpha1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/yaml"
)
-- foo.go.golden --
package p
import (
"io"
"io/ioutil" // if the user keeps them in the top group, obey that
_ "io/ioutil"
_ "image/png"
"bufio" // the above is for a side effect; this one has a comment
)
import (
"io"
"os"
"foo.local/one"
bytes_ "bytes"
)
import (
"fmt"
"foo.local/two"
)
// If they are in order, but with extra newlines, join them.
import (
"more"
"std"
)
// We need to split std vs non-std in this case too.
import (
math "math"
"foo.local"
"foo.local/three"
)
import (
"x"
// don't mess up this comment
"y"
// or many
// of them
"z"
)
// This used to crash gofumpt, as there's no space to insert an extra newline.
import (
"std"
"non.std/pkg"
)
// All of the extra imports below are known to not belong in std.
// For example/ and test/, see https://golang.org/issue/37641.
import (
"io"
"example/foo"
"internal/bar"
"test/baz"
)
import (
"io"
"nodomainmodextra"
"nodomainmod"
"nodomainmod/mod1/pkg1"
"nodomainmod/mod2"
)
import (
"io"
"nodomainother/mod.withdot/pkg1"
)
// TODO: fix issue 225.
import (
"path/filepath"
"time"
"github.com/tinkerbell/tink/pkg/apis/core/v1alpha1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/yaml"
)
@@ -0,0 +1,98 @@
exec gofumpt foo.go
cmp stdout foo.go.golden
-- go.mod --
module test
go 1.18
-- foo.go --
package p
func Foo[A, B any](x A, y B) {}
type Vector[T any] []T
var v Vector[int ]
type PredeclaredSignedInteger interface {
int | int8 | int16 | int32 | int64
}
type StringableSignedInteger interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
String() string
}
type CombineEmbeds interface {
fmt.Stringer
comparable | io.Reader
Foo()
}
func Caller() {
Foo[int,int](1,2)
}
func Issue235[K interface {
comparable
constraints.Ordered
}, V any](m map[K]V) []K {
keys := maps.Keys(m)
slices.Sort(keys)
return keys
}
func multilineParams[V any](p1 V,
p2 V) {
println("body")
}
-- foo.go.golden --
package p
func Foo[A, B any](x A, y B) {}
type Vector[T any] []T
var v Vector[int]
type PredeclaredSignedInteger interface {
int | int8 | int16 | int32 | int64
}
type StringableSignedInteger interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
String() string
}
type CombineEmbeds interface {
fmt.Stringer
comparable | io.Reader
Foo()
}
func Caller() {
Foo[int, int](1, 2)
}
func Issue235[K interface {
comparable
constraints.Ordered
}, V any](m map[K]V) []K {
keys := maps.Keys(m)
slices.Sort(keys)
return keys
}
func multilineParams[V any](p1 V,
p2 V,
) {
println("body")
}
@@ -0,0 +1,33 @@
# Whether we run gofumpt from inside or outside a module,
# we should always use the information from its go.mod.
# We also test that we don't get confused by the presence of go.work.
exec gofumpt a/go112.go
cmp stdout a/go113.go
cd a
exec gofumpt go112.go
cmp stdout go113.go
-- go.work --
go 1.18
use ./a
use ./b
-- a/go.mod --
module a
go 1.18
-- a/a.go --
package a
-- a/go112.go --
package main
const x = 0777
-- a/go113.go --
package main
const x = 0o777
-- b/go.mod --
module b
go 1.18
-- b/b.go --
package b