Move LSP semantics into typed analysis
This commit is contained in:
parent
f4cd4f4458
commit
bac1183593
26 changed files with 1232 additions and 637 deletions
72
internal/lang/generics_test.go
Normal file
72
internal/lang/generics_test.go
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue