turbo-editors/turbo-gopublic Fork 0
v1.0.1
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-go.git
git clone ssh://git@rickub.com/turbo-editors/turbo-go.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

gopls_test.go · 93 lines · 2.8 KBGo Blame HistoryRaw
📦 Turbo Go 3d7798b k33g 10h ago1package golang_test
2
3import (
4 "context"
5 "errors"
6 "path/filepath"
7 "strings"
8 "testing"
9
10 "rickub.com/turbo-editors/turbo-core/lsp"
11
12 "rickub.com/turbo-editors/turbo-go/internal/golang"
13)
14
15// TestAgainstRealGopls drives turbo-core's LSP client against an actual
16// language server: process, pipes, handshake, completion and shutdown.
17//
18// It lives here rather than in turbo-core because gopls is Turbo Go's server;
19// the library has no language server of its own to test against.
20//
21// The original comment follows.
22//
23// It drives the whole client against an actual language
24// server: process, pipes, handshake, completion and shutdown.
25//
26// It is skipped when gopls is not installed and under -short, so a checkout
27// with no language server still has a green suite — which is exactly the
28// situation the editor itself is built to cope with.
29func TestAgainstRealGopls(t *testing.T) {
30 if testing.Short() {
31 t.Skip("-short: not starting a language server")
32 }
33 if _, err := lsp.FindServer(golang.Profile().Server); errors.Is(err, lsp.ErrServerNotFound) {
34 t.Skipf("%s is not installed; %s", golang.ServerCommand, golang.InstallHint)
35 }
36
37 root := t.TempDir()
38 writeFile(t, filepath.Join(root, "go.mod"), "module example.test\n\ngo 1.24\n")
39 source := "package main\n\nimport \"strings\"\n\nfunc main() {\n\tstrings.\n}\n"
40 path := filepath.Join(root, "main.go")
41 writeFile(t, path, source)
42
43 server, err := lsp.StartServer(t.Context(), golang.Profile().Server, root, golang.Name)
44 if err != nil {
45 t.Fatalf("StartServer() error = %v", err)
46 }
47 client := server.Client()
48 t.Cleanup(func() {
49 // Not t.Context(): that one is already cancelled by the time cleanups
50 // run, and shutting a server down needs a context that is still alive.
51 if err := server.Stop(context.Background()); err != nil {
52 t.Errorf("Stop() error = %v", err)
53 }
54 })
55
56 if !client.Ready() {
57 t.Fatal("the client is not ready after StartServer returned")
58 }
59 if err := client.DidOpen(path, source); err != nil {
60 t.Fatalf("DidOpen() error = %v", err)
61 }
62
63 // Line 5, just after "strings." — the column counts the leading tab as one
64 // rune, as the editor does everywhere.
65 items, err := client.Complete(t.Context(), path, 5, 9, "\tstrings.")
66 if err != nil {
67 t.Fatalf("Complete() error = %v", err)
68 }
69 if len(items) == 0 {
70 t.Fatal("gopls offered no completions after \"strings.\"")
71 }
72
73 if !containsLabel(items, "Contains") {
74 t.Errorf("the completions do not include strings.Contains: %v", labelsOf(items))
75 }
76}
77
78func containsLabel(items []lsp.CompletionItem, want string) bool {
79 for _, item := range items {
80 if strings.HasPrefix(item.Label, want) {
81 return true
82 }
83 }
84 return false
85}
86
87func labelsOf(items []lsp.CompletionItem) []string {
88 labels := make([]string, 0, min(len(items), 10))
89 for _, item := range items[:min(len(items), 10)] {
90 labels = append(labels, item.Label)
91 }
92 return labels
93}