internal/lsp: add suggested fix for unusedparams analysis

Suggest replacing the unused function parameter with _.

Updates golang/go#36602

Change-Id: I53738e65907b8a4b4857dd8954f1477a043cf442
Reviewed-on: https://go-review.googlesource.com/c/tools/+/374254
Trust: Suzy Mueller <suzmue@golang.org>
Run-TryBot: Suzy Mueller <suzmue@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/internal/lsp/analysis/unusedparams/testdata/src/a/a.go b/internal/lsp/analysis/unusedparams/testdata/src/a/a.go
index 248ecfc..23e4122 100644
--- a/internal/lsp/analysis/unusedparams/testdata/src/a/a.go
+++ b/internal/lsp/analysis/unusedparams/testdata/src/a/a.go
@@ -1,4 +1,4 @@
-// Copyright 2020 The Go Authors. All rights reserved.
+// Copyright 2022 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.
 
diff --git a/internal/lsp/analysis/unusedparams/testdata/src/a/a.go.golden b/internal/lsp/analysis/unusedparams/testdata/src/a/a.go.golden
new file mode 100644
index 0000000..e28a6bd
--- /dev/null
+++ b/internal/lsp/analysis/unusedparams/testdata/src/a/a.go.golden
@@ -0,0 +1,55 @@
+// Copyright 2022 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 a
+
+import (
+	"bytes"
+	"fmt"
+	"net/http"
+)
+
+type parent interface {
+	n(f bool)
+}
+
+type yuh struct {
+	a int
+}
+
+func (y *yuh) n(f bool) {
+	for i := 0; i < 10; i++ {
+		fmt.Println(i)
+	}
+}
+
+func a(i1 int, _ int, i3 int) int { // want "potentially unused parameter: 'i2'"
+	i3 += i1
+	_ = func(_ int) int { // want "potentially unused parameter: 'z'"
+		_ = 1
+		return 1
+	}
+	return i3
+}
+
+func b(_ bytes.Buffer) { // want "potentially unused parameter: 'c'"
+	_ = 1
+}
+
+func z(_ http.ResponseWriter, _ *http.Request) { // want "potentially unused parameter: 'h'"
+	fmt.Println("Before")
+}
+
+func l(h http.Handler) http.Handler {
+	return http.HandlerFunc(z)
+}
+
+func mult(a, _ int) int { // want "potentially unused parameter: 'b'"
+	a += 1
+	return a
+}
+
+func y(a int) {
+	panic("yo")
+}
diff --git a/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go b/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go
index 000a62f..93af268 100644
--- a/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go
+++ b/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go
@@ -1,4 +1,4 @@
-// Copyright 2021 The Go Authors. All rights reserved.
+// Copyright 2022 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.
 
diff --git a/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden b/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden
new file mode 100644
index 0000000..c86bf28
--- /dev/null
+++ b/internal/lsp/analysis/unusedparams/testdata/src/typeparams/typeparams.go.golden
@@ -0,0 +1,55 @@
+// Copyright 2022 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 typeparams
+
+import (
+	"bytes"
+	"fmt"
+	"net/http"
+)
+
+type parent[T any] interface {
+	n(f T)
+}
+
+type yuh[T any] struct {
+	a T
+}
+
+func (y *yuh[int]) n(f bool) {
+	for i := 0; i < 10; i++ {
+		fmt.Println(i)
+	}
+}
+
+func a[T comparable](i1 int, _ T, i3 int) int { // want "potentially unused parameter: 'i2'"
+	i3 += i1
+	_ = func(_ int) int { // want "potentially unused parameter: 'z'"
+		_ = 1
+		return 1
+	}
+	return i3
+}
+
+func b[T any](_ bytes.Buffer) { // want "potentially unused parameter: 'c'"
+	_ = 1
+}
+
+func z[T http.ResponseWriter](_ T, _ *http.Request) { // want "potentially unused parameter: 'h'"
+	fmt.Println("Before")
+}
+
+func l(h http.Handler) http.Handler {
+	return http.HandlerFunc(z[http.ResponseWriter])
+}
+
+func mult(a, _ int) int { // want "potentially unused parameter: 'b'"
+	a += 1
+	return a
+}
+
+func y[T any](a T) {
+	panic("yo")
+}
diff --git a/internal/lsp/analysis/unusedparams/unusedparams.go b/internal/lsp/analysis/unusedparams/unusedparams.go
index e6f2274..4c933c8 100644
--- a/internal/lsp/analysis/unusedparams/unusedparams.go
+++ b/internal/lsp/analysis/unusedparams/unusedparams.go
@@ -131,13 +131,20 @@
 				start, end = u.ident.Pos(), u.ident.End()
 			}
 			// TODO(golang/go#36602): Add suggested fixes to automatically
-			// remove the unused parameter. To start, just remove it from the
-			// function declaration. Later, remove it from every use of this
+			// remove the unused parameter from every use of this
 			// function.
 			pass.Report(analysis.Diagnostic{
 				Pos:     start,
 				End:     end,
 				Message: fmt.Sprintf("potentially unused parameter: '%s'", u.ident.Name),
+				SuggestedFixes: []analysis.SuggestedFix{{
+					Message: `Replace with "_"`,
+					TextEdits: []analysis.TextEdit{{
+						Pos:     u.ident.Pos(),
+						End:     u.ident.End(),
+						NewText: []byte("_"),
+					}},
+				}},
 			})
 		}
 	})
diff --git a/internal/lsp/analysis/unusedparams/unusedparams_test.go b/internal/lsp/analysis/unusedparams/unusedparams_test.go
index 646a3dc..dff17c9 100644
--- a/internal/lsp/analysis/unusedparams/unusedparams_test.go
+++ b/internal/lsp/analysis/unusedparams/unusedparams_test.go
@@ -18,5 +18,5 @@
 	if typeparams.Enabled {
 		tests = append(tests, "typeparams")
 	}
-	analysistest.Run(t, testdata, unusedparams.Analyzer, tests...)
+	analysistest.RunWithSuggestedFixes(t, testdata, unusedparams.Analyzer, tests...)
 }