| // Copyright 2026 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. |
| |
| package misc |
| |
| import ( |
| "slices" |
| "strings" |
| "testing" |
| |
| "golang.org/x/tools/gopls/internal/protocol" |
| . "golang.org/x/tools/gopls/internal/test/integration" |
| "golang.org/x/tools/internal/testenv" |
| ) |
| |
| // TestStringIntConvQuickFix checks the quick fixes offered for the |
| // type error that go1.28 reports for string(int) conversions |
| // (go.dev/issue/3939). They are the fixes of the stringintconv |
| // analyzer, which does not run on ill-typed packages. |
| // |
| // (We can't use a marker test since there are two quick fixes.) |
| func TestStringIntConvQuickFix(t *testing.T) { |
| testenv.NeedsGo1Point(t, 28) |
| |
| const src = ` |
| -- go.mod -- |
| module example.com |
| go 1.28 |
| |
| -- a/a.go -- |
| package a |
| |
| func _(x int64) string { return string(x) } |
| ` |
| for _, test := range []struct { |
| title string |
| want string |
| }{ |
| { |
| "Convert single rune to string (preserves behavior)", |
| `package a |
| |
| import "fmt" |
| |
| func _(x int64) string { return fmt.Sprintf("%c", x) } |
| `, |
| }, |
| { |
| "Format number as decimal (changes behavior)", |
| `package a |
| |
| import "fmt" |
| |
| func _(x int64) string { return fmt.Sprintf("%d", x) } |
| `, |
| }, |
| } { |
| t.Run(test.title, func(t *testing.T) { |
| Run(t, src, func(t *testing.T, env *Env) { |
| env.OpenFile("a/a.go") |
| var d protocol.PublishDiagnosticsParams |
| env.AfterChange( |
| Diagnostics(env.AtRegexp("a/a.go", `x\)`), WithMessage("must have type byte or rune")), |
| ReadDiagnostics("a/a.go", &d), |
| ) |
| actions := env.CodeAction(env.RegexpSearch("a/a.go", `x\)`), d.Diagnostics, protocol.CodeActionUnknownTrigger) |
| i := slices.IndexFunc(actions, func(act protocol.CodeAction) bool { |
| return act.Kind == protocol.QuickFix && act.Title == test.title |
| }) |
| if i < 0 { |
| var titles []string |
| for _, act := range actions { |
| titles = append(titles, act.Title) |
| } |
| t.Fatalf("no quick fix %q; got %s", test.title, strings.Join(titles, ", ")) |
| } |
| env.ApplyCodeAction(actions[i]) |
| if got := env.BufferText("a/a.go"); got != test.want { |
| t.Errorf("got:\n%s\nwant:\n%s", got, test.want) |
| } |
| }) |
| }) |
| } |
| } |