diff options
Diffstat (limited to 'internal/typeparams/coretype_test.go')
-rw-r--r-- | internal/typeparams/coretype_test.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/internal/typeparams/coretype_test.go b/internal/typeparams/coretype_test.go new file mode 100644 index 000000000..288439952 --- /dev/null +++ b/internal/typeparams/coretype_test.go @@ -0,0 +1,105 @@ +// 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_test + +import ( + "go/ast" + "go/parser" + "go/token" + "go/types" + "testing" + + "golang.org/x/tools/internal/typeparams" +) + +func TestCoreType(t *testing.T) { + if !typeparams.Enabled { + t.Skip("TestCoreType requires type parameters.") + } + + const source = ` + package P + + type Named int + + type A any + type B interface{~int} + type C interface{int} + type D interface{Named} + type E interface{~int|interface{Named}} + type F interface{~int|~float32} + type G interface{chan int|interface{chan int}} + type H interface{chan int|chan float32} + type I interface{chan<- int|chan int} + type J interface{chan int|chan<- int} + type K interface{<-chan int|chan int} + type L interface{chan int|<-chan int} + type M interface{chan int|chan Named} + type N interface{<-chan int|chan<- int} + type O interface{chan int|bool} + type P struct{ Named } + type Q interface{ Foo() } + type R interface{ Foo() ; Named } + type S interface{ Foo() ; ~int } + + type T interface{chan int|interface{chan int}|<-chan int} +` + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, "hello.go", source, 0) + if err != nil { + t.Fatal(err) + } + + var conf types.Config + pkg, err := conf.Check("P", fset, []*ast.File{f}, nil) + if err != nil { + t.Fatal(err) + } + + for _, test := range []struct { + expr string // type expression of Named type + want string // expected core type (or "<nil>" if none) + }{ + {"Named", "int"}, // Underlying type is not interface. + {"A", "<nil>"}, // Interface has no terms. + {"B", "int"}, // Tilde term. + {"C", "int"}, // Non-tilde term. + {"D", "int"}, // Named term. + {"E", "int"}, // Identical underlying types. + {"F", "<nil>"}, // Differing underlying types. + {"G", "chan int"}, // Identical Element types. + {"H", "<nil>"}, // Element type int has differing underlying type to float32. + {"I", "chan<- int"}, // SendRecv followed by SendOnly + {"J", "chan<- int"}, // SendOnly followed by SendRecv + {"K", "<-chan int"}, // RecvOnly followed by SendRecv + {"L", "<-chan int"}, // SendRecv followed by RecvOnly + {"M", "<nil>"}, // Element type int is not *identical* to Named. + {"N", "<nil>"}, // Differing channel directions + {"O", "<nil>"}, // A channel followed by a non-channel. + {"P", "struct{P.Named}"}, // Embedded type. + {"Q", "<nil>"}, // interface type with no terms and functions + {"R", "int"}, // interface type with both terms and functions. + {"S", "int"}, // interface type with a tilde term + {"T", "<-chan int"}, // Prefix of 2 terms that are identical before switching to channel. + } { + // Eval() expr for its type. + tv, err := types.Eval(fset, pkg, 0, test.expr) + if err != nil { + t.Fatalf("Eval(%s) failed: %v", test.expr, err) + } + + ct := typeparams.CoreType(tv.Type) + var got string + if ct == nil { + got = "<nil>" + } else { + got = ct.String() + } + if got != test.want { + t.Errorf("coreType(%s) = %v, want %v", test.expr, got, test.want) + } + } +} |