cmd/viewer: import types/views when generating a getter for a map field

Fixes #13873

Signed-off-by: Nick Khyl <nickk@tailscale.com>
This commit is contained in:
Nick Khyl 2024-10-21 12:28:41 -05:00 committed by Nick Khyl
parent f8f53bb6d4
commit 0f4c9c0ecb
3 changed files with 84 additions and 0 deletions

View File

@ -258,6 +258,7 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, thi
writeTemplate("unsupportedField")
continue
}
it.Import("tailscale.com/types/views")
args.MapKeyType = it.QualifiedName(key)
mElem := m.Elem()
var template string

78
cmd/viewer/viewer_test.go Normal file
View File

@ -0,0 +1,78 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package main
import (
"bytes"
"fmt"
"go/ast"
"go/parser"
"go/token"
"go/types"
"testing"
"tailscale.com/util/codegen"
)
func TestViewerImports(t *testing.T) {
tests := []struct {
name string
content string
typeNames []string
wantImports []string
}{
{
name: "Map",
content: `type Test struct { Map map[string]int }`,
typeNames: []string{"Test"},
wantImports: []string{"tailscale.com/types/views"},
},
{
name: "Slice",
content: `type Test struct { Slice []int }`,
typeNames: []string{"Test"},
wantImports: []string{"tailscale.com/types/views"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "test.go", "package test\n\n"+tt.content, 0)
if err != nil {
fmt.Println("Error parsing:", err)
return
}
info := &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
}
conf := types.Config{}
pkg, err := conf.Check("", fset, []*ast.File{f}, info)
if err != nil {
t.Fatal(err)
}
var output bytes.Buffer
tracker := codegen.NewImportTracker(pkg)
for i := range tt.typeNames {
typeName, ok := pkg.Scope().Lookup(tt.typeNames[i]).(*types.TypeName)
if !ok {
t.Fatalf("type %q does not exist", tt.typeNames[i])
}
namedType, ok := typeName.Type().(*types.Named)
if !ok {
t.Fatalf("%q is not a named type", tt.typeNames[i])
}
genView(&output, tracker, namedType, pkg)
}
for _, pkgName := range tt.wantImports {
if !tracker.Has(pkgName) {
t.Errorf("missing import %q", pkgName)
}
}
})
}
}

View File

@ -97,6 +97,11 @@ func (it *ImportTracker) Import(pkg string) {
}
}
// Has reports whether the specified package has been imported.
func (it *ImportTracker) Has(pkg string) bool {
return it.packages[pkg]
}
func (it *ImportTracker) qualifier(pkg *types.Package) string {
if it.thisPkg == pkg {
return ""