1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
package app
import (
"os"
"path/filepath"
"testing"
"rickub.com/turbo-editors/turbo-core/lsp"
)
func TestDiagnosticsAreFoundForAFileOpenedByARelativePath(t *testing.T) {
// Found by driving the real editor against a real gopls: the Problems
// window listed two errors and the gutter showed none, because the two
// sides spell the file differently. A server publishes absolute URIs; a
// buffer opened as "turbo-go main.go" holds the relative path it was
// given. The status bar had been failing the same way since long before
// the marks existed, silently, because an editor with no error to show and
// an editor that cannot find the error look identical.
project := t.TempDir()
t.Chdir(project)
t.Setenv(testProfile().SnippetDirEnvVar(), t.TempDir())
a, _ := newTestApp(t)
writeTestFile(t, filepath.Join(project, "main.go"), "package main\n\nfunc main() { x }\n")
a.Open("main.go") // relative, as the command line gives it
a.language.receiveDiagnostics(filepath.Join(project, "main.go"), []lsp.Diagnostic{
{Message: "undefined: x", Severity: lsp.SeverityError, Range: lsp.Range{Start: lsp.Position{Line: 2}}},
})
a.Tick()
if _, found := a.language.FirstError(a.ActiveView().Buffer().Path()); !found {
t.Errorf("no error found for %q, though one was published for the same file",
a.ActiveView().Buffer().Path())
}
if got := a.ActiveView().Marks()[2]; got == 0 {
t.Errorf("line 3 is unmarked, though an error was published for it")
}
}
func TestDiagnosticsAreFoundWhicheverWaySpelt(t *testing.T) {
// Both directions, since either side may be the relative one.
project := t.TempDir()
t.Chdir(project)
a, _ := newTestApp(t)
a.language.receiveDiagnostics("main.go", []lsp.Diagnostic{{Message: "relative in"}})
if got := a.language.Diagnostics(filepath.Join(project, "main.go")); len(got) != 1 {
t.Errorf("published relative, read absolute: got %d diagnostics", len(got))
}
a.language.receiveDiagnostics(filepath.Join(project, "other.go"), []lsp.Diagnostic{{Message: "absolute in"}})
if got := a.language.Diagnostics("other.go"); len(got) != 1 {
t.Errorf("published absolute, read relative: got %d diagnostics", len(got))
}
}
func TestKnowsDoesNotDependOnTheSpellingOfThePath(t *testing.T) {
// The map of open documents is keyed the same way as the diagnostics:
// absolute. Keyed by whatever string DidOpen was given, a file opened as
// "main.go" would not be known as "/project/main.go" — and saving, which
// asks Knows to decide between announcing a document and reporting a
// write, would announce the same document twice.
project := t.TempDir()
t.Chdir(project)
a, _ := newTestApp(t)
client, _ := newFakeLanguage(t, a)
connectLanguage(a, client)
a.language.DidOpen("main.go", "package main\n")
absolute := filepath.Join(project, "main.go")
if !a.language.Knows(absolute) {
t.Errorf("opened as %q, not known as %q", "main.go", absolute)
}
if !a.language.Knows("main.go") {
t.Errorf("opened as %q, not known under that very spelling", "main.go")
}
a.language.DidClose(absolute)
if a.language.Knows("main.go") {
t.Errorf("closed as %q, still known as %q", absolute, "main.go")
}
}
func TestDiagnosticsPublishedUnderTheRealPathReachAFileOpenedThroughALink(t *testing.T) {
// Found on macOS, the first time Turbo MoonBit's suite ran there: every
// temporary directory is /var/folders/…, a link to /private/var/…, and
// moon-lsp canonicalises paths. It published the file's problems under
// /private/var and answered no completion about a buffer announced as
// /var — to it, a file that belonged to no package. Absolute was not
// enough; the key has to be canonical, and so has the URI the server is
// sent, or the two sides spell the same file differently again.
real := t.TempDir()
link := filepath.Join(t.TempDir(), "link")
if err := os.Symlink(real, link); err != nil {
t.Skipf("cannot create a symbolic link here: %v", err)
}
a, _ := newTestApp(t)
client, fake := newFakeLanguage(t, a)
connectLanguage(a, client)
throughLink := filepath.Join(link, "main.mbt")
a.language.DidOpen(throughLink, "fn main {}\n")
resolvedReal, err := filepath.EvalSymlinks(real)
if err != nil {
t.Fatal(err)
}
if !a.language.Knows(filepath.Join(resolvedReal, "main.mbt")) {
t.Errorf("opened through the link, not known under the real path")
}
if got, want := fake.lastOpenedURI(), lsp.PathToURI(filepath.Join(resolvedReal, "main.mbt")); got != want {
t.Errorf("the server was told %q, want the real path's %q", got, want)
}
a.language.receiveDiagnostics(filepath.Join(resolvedReal, "main.mbt"), []lsp.Diagnostic{
{Message: "published under the real path", Severity: lsp.SeverityError},
})
if got := a.language.Diagnostics(throughLink); len(got) != 1 {
t.Errorf("published under the real path, read through the link: got %d diagnostics", len(got))
}
}
func TestWindowForFindsAFileOpenedThroughALink(t *testing.T) {
// A location the server sends back names the file as the server spells
// it. Compared as spelt, a jump to a definition in a file already on
// screen opened it a second time, and the references list quoted the disk
// instead of the unsaved window — both seen on macOS, where every
// temporary directory is a link.
real := t.TempDir()
link := filepath.Join(t.TempDir(), "link")
if err := os.Symlink(real, link); err != nil {
t.Skipf("cannot create a symbolic link here: %v", err)
}
t.Setenv(testProfile().SnippetDirEnvVar(), t.TempDir())
a, _ := newTestApp(t)
writeTestFile(t, filepath.Join(real, "main.go"), "package main\n")
a.Open(filepath.Join(link, "main.go"))
resolvedReal, err := filepath.EvalSymlinks(real)
if err != nil {
t.Fatal(err)
}
if a.windowFor(filepath.Join(resolvedReal, "main.go")) == nil {
t.Errorf("opened through the link, the window is not found under the real path")
}
if a.windowFor(filepath.Join(link, "main.go")) == nil {
t.Errorf("opened through the link, the window is not found under the link either")
}
}
|