gotlin/internal/lang/generics_test.go

72 lines
2.1 KiB
Go

package lang
import (
"strings"
"testing"
)
func TestGenerateGenericFunctionsAndClasses(t *testing.T) {
program, err := Parse(`package demo
data class Box<T>(var value: T) {
fun get(): T { return value }
}
fun identity<T>(value: T): T { return value }
fun wrap<T>(value: T): Box<T> { return Box(value) }
fun main() {
val inferred = identity(42)
val explicit = identity<String>("value")
val box = wrap("boxed")
println(box.get())
}`)
if err != nil {
t.Fatal(err)
}
output, err := GenerateGo(program)
if err != nil {
t.Fatal(err)
}
code := string(output)
for _, expected := range []string{
"type Box[T any] struct",
"func NewBox[T any](value T) *Box[T]",
"func (self *Box[T]) get() T",
"func identity[T any](value T) T",
"func wrap[T any](value T) *Box[T]",
"identity(42)",
`identity[string]("value")`,
`wrap("boxed")`,
} {
if !strings.Contains(code, expected) {
t.Fatalf("missing %q:\n%s", expected, code)
}
}
main := program.Functions[2]
inferred := main.Body[0].(VarDecl)
if got := ResolvedType(inferred.Value).String(); got != "Int" {
t.Fatalf("inferred generic type = %s", got)
}
box := main.Body[2].(VarDecl)
if got := ResolvedType(box.Value).String(); got != "Box<String>" {
t.Fatalf("generic class type = %s", got)
}
}
func TestRejectInvalidGenericDeclarationsAndCalls(t *testing.T) {
for _, test := range []struct{ source, message string }{
{`package demo fun identity<T, T>(value: T): T { return value }`, "duplicate type parameter T"},
{`package demo fun identity<T>(value: T): T { return value } fun main() { identity<String, Int>("x") }`, "expects 1 type arguments, got 2"},
{`package demo class Box<T>(val value: T) { fun convert<R>(): T { return value } }`, "generic methods are not supported"},
} {
program, err := Parse(test.source)
if err != nil {
if strings.Contains(err.Error(), test.message) {
continue
}
t.Fatalf("unexpected parse error: %v", err)
}
_, err = GenerateGo(program)
if err == nil || !strings.Contains(err.Error(), test.message) {
t.Fatalf("error = %v, want %q", err, test.message)
}
}
}