Expand Gotlin language and tooling

This commit is contained in:
pavel 2026-08-27 01:46:57 +02:00
commit de1262b4cf
41 changed files with 6059 additions and 379 deletions

View file

@ -1,12 +1,104 @@
package main
import (
"os"
"path/filepath"
"strings"
"testing"
"gotlin/internal/lang"
)
func TestPackageWideDiagnosticsAndDefinition(t *testing.T) {
root := t.TempDir()
if err := os.WriteFile(filepath.Join(root, "go.mod"), []byte("module example\n\ngo 1.25\n"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.Mkdir(filepath.Join(root, "model"), 0o755); err != nil {
t.Fatal(err)
}
modelPath := filepath.Join(root, "model", "command.gt")
modelText := "package main\n\ndata class CreateAccountCommand(var name: String)\n"
if err := os.WriteFile(modelPath, []byte(modelText), 0o644); err != nil {
t.Fatal(err)
}
mainPath := filepath.Join(root, "main.gt")
mainText := "package main\n\nfun main() {\n val command = CreateAccountCommand(\"demo\")\n println(command)\n}\n"
if err := os.WriteFile(mainPath, []byte(mainText), 0o644); err != nil {
t.Fatal(err)
}
uri := fileURI(mainPath)
s := server{docs: map[string]documentState{}}
state := s.buildDocumentState(uri, mainText)
for _, d := range state.diagnostics {
if strings.Contains(d.Message, "undefined identifier CreateAccountCommand") {
t.Fatalf("unexpected cross-file diagnostic: %+v", d)
}
}
s.docs[uri] = state
character := strings.Index(strings.Split(mainText, "\n")[3], "CreateAccountCommand")
result, ok := s.definition(uri, position{Line: 3, Character: character + 2}).([]location)
if !ok || len(result) != 1 {
t.Fatalf("expected cross-file definition, got %#v", s.definition(uri, position{Line: 3, Character: character + 2}))
}
if result[0].URI != fileURI(modelPath) {
t.Fatalf("definition URI = %s, want %s", result[0].URI, fileURI(modelPath))
}
}
func TestPackageIndexStopsAtNearestGoModule(t *testing.T) {
root := t.TempDir()
first := filepath.Join(root, "first")
second := filepath.Join(root, "second")
for _, dir := range []string{first, second} {
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module example\n\ngo 1.25\n"), 0o644); err != nil {
t.Fatal(err)
}
}
if err := os.WriteFile(filepath.Join(second, "other.gt"), []byte("package main\ndata class OtherRootType(var id: String)\n"), 0o644); err != nil {
t.Fatal(err)
}
mainPath := filepath.Join(first, "main.gt")
mainText := "package main\nfun main() { OtherRootType(\"x\") }\n"
if err := os.WriteFile(mainPath, []byte(mainText), 0o644); err != nil {
t.Fatal(err)
}
s := server{docs: map[string]documentState{}}
state := s.buildDocumentState(fileURI(mainPath), mainText)
found := false
for _, d := range state.diagnostics {
if strings.Contains(d.Message, "undefined identifier OtherRootType") {
found = true
}
}
if !found {
t.Fatalf("expected module-isolated undefined diagnostic, got %+v", state.diagnostics)
}
}
func TestCurrentBuiltinsDoNotProduceUndefinedDiagnostics(t *testing.T) {
state := buildDocumentState(`package demo
fun main() {
val bytes = ByteSlice("hello")
var values: MutableList<String> = mutableListOf<String>()
values = append(values, string(bytes))
println(len(values))
}`)
for _, diagnostic := range state.diagnostics {
if strings.Contains(diagnostic.Message, "undefined identifier") {
t.Fatalf("unexpected builtin diagnostic: %+v", diagnostic)
}
}
for _, name := range []string{"ByteSlice", "append", "len", "sql", "set", "now"} {
if !isBuiltin(name) {
t.Fatalf("%s is not registered as builtin", name)
}
}
}
func TestResolveStdlibTarget(t *testing.T) {
text := strings.TrimSpace(`
package examples.http
@ -668,7 +760,7 @@ func TestBuildDocumentStateWorkerSemantics(t *testing.T) {
package demo
worker Counter {
val counter = 0
var counter = 0
fun getCount(): Int {
return counter