internal/lsp: disable fillstruct for type params

Do not suggest fixes for types that require type params
or that have fields that require type parameters.

Change-Id: I68059956a7d38be0ffa3f79230615437ccc5788f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/353109
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Trust: Rebecca Stambler <rstambler@golang.org>
Trust: Suzy Mueller <suzmue@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
diff --git a/internal/lsp/analysis/fillstruct/fillstruct.go b/internal/lsp/analysis/fillstruct/fillstruct.go
index 0547288..a4dd8cc 100644
--- a/internal/lsp/analysis/fillstruct/fillstruct.go
+++ b/internal/lsp/analysis/fillstruct/fillstruct.go
@@ -22,6 +22,7 @@
 	"golang.org/x/tools/go/ast/inspector"
 	"golang.org/x/tools/internal/analysisinternal"
 	"golang.org/x/tools/internal/span"
+	"golang.org/x/tools/internal/typeparams"
 )
 
 const Doc = `note incomplete struct initializations
@@ -66,6 +67,14 @@
 			return
 		}
 
+		// Ignore types that have type parameters for now.
+		// TODO: support type params.
+		if typ, ok := typ.(*types.Named); ok {
+			if tparams := typeparams.ForNamed(typ); tparams != nil && tparams.Len() > 0 {
+				return
+			}
+		}
+
 		// Find reference to the type declaration of the struct being initialized.
 		for {
 			p, ok := typ.Underlying().(*types.Pointer)
@@ -95,6 +104,16 @@
 			if field.Pkg() != nil && field.Pkg() != pass.Pkg && !field.Exported() {
 				continue
 			}
+			// Ignore structs containing fields that have type parameters for now.
+			// TODO: support type params.
+			if typ, ok := field.Type().(*types.Named); ok {
+				if tparams := typeparams.ForNamed(typ); tparams != nil && tparams.Len() > 0 {
+					return
+				}
+			}
+			if _, ok := field.Type().(*typeparams.TypeParam); ok {
+				return
+			}
 			fillable = true
 			fillableFields = append(fillableFields, fmt.Sprintf("%s: %s", field.Name(), field.Type().String()))
 		}
diff --git a/internal/lsp/analysis/fillstruct/fillstruct_test.go b/internal/lsp/analysis/fillstruct/fillstruct_test.go
index 34c9923e..51a516c 100644
--- a/internal/lsp/analysis/fillstruct/fillstruct_test.go
+++ b/internal/lsp/analysis/fillstruct/fillstruct_test.go
@@ -9,9 +9,14 @@
 
 	"golang.org/x/tools/go/analysis/analysistest"
 	"golang.org/x/tools/internal/lsp/analysis/fillstruct"
+	"golang.org/x/tools/internal/typeparams"
 )
 
 func Test(t *testing.T) {
 	testdata := analysistest.TestData()
-	analysistest.Run(t, testdata, fillstruct.Analyzer, "a")
+	tests := []string{"a"}
+	if typeparams.Enabled {
+		tests = append(tests, "typeparams")
+	}
+	analysistest.Run(t, testdata, fillstruct.Analyzer, tests...)
 }
diff --git a/internal/lsp/analysis/fillstruct/testdata/src/typeparams/typeparams.go b/internal/lsp/analysis/fillstruct/testdata/src/typeparams/typeparams.go
new file mode 100644
index 0000000..9029061
--- /dev/null
+++ b/internal/lsp/analysis/fillstruct/testdata/src/typeparams/typeparams.go
@@ -0,0 +1,41 @@
+// Copyright 2020 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 fillstruct
+
+type emptyStruct[A any] struct{}
+
+var _ = emptyStruct[int]{}
+
+type basicStruct[T any] struct {
+	foo T
+}
+
+var _ = basicStruct[int]{}
+
+type fooType[T any] T
+
+type twoArgStruct[F, B any] struct {
+	foo fooType[F]
+	bar fooType[B]
+}
+
+var _ = twoArgStruct[string, int]{}
+
+var _ = twoArgStruct[int, string]{
+	bar: "bar",
+}
+
+type nestedStruct struct {
+	bar   string
+	basic basicStruct[int]
+}
+
+var _ = nestedStruct{}
+
+func _[T any]() {
+	type S struct{ t T }
+	x := S{}
+	_ = x
+}