mirror of https://github.com/golang/go.git
218 lines
4.1 KiB
Go
218 lines
4.1 KiB
Go
// Copyright 2019 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 cache
|
|
|
|
import (
|
|
"bytes"
|
|
"go/ast"
|
|
"go/format"
|
|
"go/parser"
|
|
"go/token"
|
|
"go/types"
|
|
"reflect"
|
|
"sort"
|
|
"testing"
|
|
|
|
"golang.org/x/tools/go/packages"
|
|
)
|
|
|
|
func TestArrayLength(t *testing.T) {
|
|
tests := []struct {
|
|
expr string
|
|
length int
|
|
}{
|
|
{`[...]int{0,1,2,3,4,5,6,7,8,9}`, 10},
|
|
{`[...]int{9:0}`, 10},
|
|
{`[...]int{19-10:0}`, 10},
|
|
{`[...]int{19-10:0, 17-10:0, 18-10:0}`, 10},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
expr, err := parser.ParseExpr(tt.expr)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
l, ok := arrayLength(expr.(*ast.CompositeLit))
|
|
if !ok {
|
|
t.Errorf("arrayLength did not recognize expression %#v", expr)
|
|
}
|
|
if l != tt.length {
|
|
t.Errorf("arrayLength(%#v) = %v, want %v", expr, l, tt.length)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTrim(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
file string
|
|
kept []string
|
|
}{
|
|
{
|
|
name: "delete_unused",
|
|
file: `
|
|
type x struct{}
|
|
func y()
|
|
var z int
|
|
`,
|
|
kept: []string{},
|
|
},
|
|
{
|
|
// From the common type in testing.
|
|
name: "unexported_embedded",
|
|
file: `
|
|
type x struct {}
|
|
type Exported struct { x }
|
|
`,
|
|
kept: []string{"Exported", "x"},
|
|
},
|
|
{
|
|
// From the d type in unicode.
|
|
name: "exported_field_unexported_type",
|
|
file: `
|
|
type x struct {}
|
|
type Exported struct {
|
|
X x
|
|
}
|
|
`,
|
|
kept: []string{"Exported", "x"},
|
|
},
|
|
{
|
|
// From errNotExist in io/fs.
|
|
name: "exported_var_function_call",
|
|
file: `
|
|
func x() int { return 0 }
|
|
var Exported = x()
|
|
`,
|
|
kept: []string{"Exported", "x"},
|
|
},
|
|
{
|
|
// From DefaultServeMux in net/http.
|
|
name: "exported_pointer_to_unexported_var",
|
|
file: `
|
|
var Exported = &x
|
|
var x int
|
|
`,
|
|
kept: []string{"Exported", "x"},
|
|
},
|
|
{
|
|
// From DefaultWriter in goldmark/renderer/html.
|
|
name: "exported_pointer_to_composite_lit",
|
|
file: `
|
|
var Exported = &x{}
|
|
type x struct{}
|
|
`,
|
|
kept: []string{"Exported", "x"},
|
|
},
|
|
{
|
|
// From SelectDir in reflect.
|
|
name: "leave_constants",
|
|
file: `
|
|
type Enum int
|
|
const (
|
|
_ Enum = iota
|
|
EnumOne
|
|
)
|
|
`,
|
|
kept: []string{"Enum", "EnumOne"},
|
|
},
|
|
{
|
|
name: "constant_conversion",
|
|
file: `
|
|
type x int
|
|
const (
|
|
foo x = 0
|
|
)
|
|
`,
|
|
kept: []string{"x", "foo"},
|
|
},
|
|
{
|
|
name: "unexported_return",
|
|
file: `
|
|
type x int
|
|
func Exported() x {}
|
|
type y int
|
|
type Interface interface {
|
|
Exported() y
|
|
}
|
|
`,
|
|
kept: []string{"Exported", "Interface", "x", "y"},
|
|
},
|
|
{
|
|
name: "drop_composite_literals",
|
|
file: `
|
|
type x int
|
|
type Exported struct {
|
|
foo x
|
|
}
|
|
var Var = Exported{foo:1}
|
|
`,
|
|
kept: []string{"Exported", "Var", "x"},
|
|
},
|
|
{
|
|
name: "drop_function_literals",
|
|
file: `
|
|
type x int
|
|
var Exported = func() { return x(0) }
|
|
`,
|
|
kept: []string{"Exported"},
|
|
},
|
|
{
|
|
name: "missing_receiver_panic",
|
|
file: `
|
|
func() foo() {}
|
|
`,
|
|
kept: []string{},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
fset := token.NewFileSet()
|
|
file, err := parser.ParseFile(fset, "main.go", "package main\n\n"+tt.file, parser.AllErrors)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
filter := &unexportedFilter{uses: map[string]bool{}}
|
|
filter.Filter([]*ast.File{file})
|
|
pkg := types.NewPackage("main", "main")
|
|
checker := types.NewChecker(&types.Config{
|
|
DisableUnusedImportCheck: true,
|
|
}, fset, pkg, nil)
|
|
if err := checker.Files([]*ast.File{file}); err != nil {
|
|
t.Error(err)
|
|
}
|
|
names := pkg.Scope().Names()
|
|
sort.Strings(names)
|
|
sort.Strings(tt.kept)
|
|
if !reflect.DeepEqual(names, tt.kept) {
|
|
t.Errorf("package contains names %v, wanted %v", names, tt.kept)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPkg(t *testing.T) {
|
|
t.Skip("for manual debugging")
|
|
fset := token.NewFileSet()
|
|
pkgs, err := packages.Load(&packages.Config{
|
|
Mode: packages.NeedSyntax | packages.NeedFiles,
|
|
Fset: fset,
|
|
}, "io")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(pkgs[0].Errors) != 0 {
|
|
t.Fatal(pkgs[0].Errors)
|
|
}
|
|
filter := &unexportedFilter{uses: map[string]bool{}}
|
|
filter.Filter(pkgs[0].Syntax)
|
|
for _, file := range pkgs[0].Syntax {
|
|
buf := &bytes.Buffer{}
|
|
format.Node(buf, fset, file)
|
|
t.Log(buf.String())
|
|
}
|
|
}
|