Skip to content

Commit d929df4

Browse files
authored
Fix handling of non-file URIs (#1167)
1 parent e475191 commit d929df4

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

internal/ls/converters.go

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,34 +81,30 @@ func LanguageKindToScriptKind(languageID lsproto.LanguageKind) core.ScriptKind {
8181
}
8282

8383
func DocumentURIToFileName(uri lsproto.DocumentUri) string {
84-
parsed := core.Must(url.Parse(string(uri)))
85-
if parsed.Scheme == "file" {
84+
if strings.HasPrefix(string(uri), "file://") {
85+
parsed := core.Must(url.Parse(string(uri)))
8686
if parsed.Host != "" {
8787
return "//" + parsed.Host + parsed.Path
8888
}
8989
return fixWindowsURIPath(parsed.Path)
9090
}
9191

92-
authority := parsed.Host
93-
if authority == "" {
94-
authority = "ts-nul-authority"
95-
}
96-
path := parsed.Path
97-
if path == "" {
98-
path = parsed.Opaque
99-
}
100-
if !strings.HasPrefix(path, "/") {
101-
path = "/" + path
102-
}
103-
path = fixWindowsURIPath(path)
104-
if !strings.HasPrefix(path, "/") {
105-
path = "/" + path
92+
// Leave all other URIs escaped so we can round-trip them.
93+
94+
scheme, path, ok := strings.Cut(string(uri), ":")
95+
if !ok {
96+
panic(fmt.Sprintf("invalid URI: %s", uri))
10697
}
107-
fragment := parsed.Fragment
108-
if fragment != "" {
109-
fragment = "#" + fragment
98+
99+
authority := "ts-nul-authority"
100+
if rest, ok := strings.CutPrefix(path, "//"); ok {
101+
authority, path, ok = strings.Cut(rest, "/")
102+
if !ok {
103+
panic(fmt.Sprintf("invalid URI: %s", uri))
104+
}
110105
}
111-
return fmt.Sprintf("^/%s/%s%s%s", parsed.Scheme, authority, path, fragment)
106+
107+
return "^/" + scheme + "/" + authority + "/" + path
112108
}
113109

114110
func fixWindowsURIPath(path string) string {
@@ -154,7 +150,18 @@ var extraEscapeReplacer = strings.NewReplacer(
154150

155151
func FileNameToDocumentURI(fileName string) lsproto.DocumentUri {
156152
if strings.HasPrefix(fileName, "^/") {
157-
return lsproto.DocumentUri(strings.Replace(fileName[2:], "/ts-nul-authority/", ":", 1))
153+
scheme, rest, ok := strings.Cut(fileName[2:], "/")
154+
if !ok {
155+
panic("invalid file name: " + fileName)
156+
}
157+
authority, path, ok := strings.Cut(rest, "/")
158+
if !ok {
159+
panic("invalid file name: " + fileName)
160+
}
161+
if authority == "ts-nul-authority" {
162+
return lsproto.DocumentUri(scheme + ":" + path)
163+
}
164+
return lsproto.DocumentUri(scheme + "://" + authority + "/" + path)
158165
}
159166

160167
volume, fileName, _ := splitVolumePath(fileName)

internal/ls/converters_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ func TestDocumentURIToFileName(t *testing.T) {
3434
{"untitled:Untitled-1", "^/untitled/ts-nul-authority/Untitled-1"},
3535
{"untitled:Untitled-1#fragment", "^/untitled/ts-nul-authority/Untitled-1#fragment"},
3636
{"untitled:c:/Users/jrieken/Code/abc.txt", "^/untitled/ts-nul-authority/c:/Users/jrieken/Code/abc.txt"},
37-
{"untitled:C:/Users/jrieken/Code/abc.txt", "^/untitled/ts-nul-authority/c:/Users/jrieken/Code/abc.txt"},
37+
{"untitled:C:/Users/jrieken/Code/abc.txt", "^/untitled/ts-nul-authority/C:/Users/jrieken/Code/abc.txt"},
38+
{"untitled://wsl%2Bubuntu/home/jabaile/work/TypeScript-go/newfile.ts", "^/untitled/wsl%2Bubuntu/home/jabaile/work/TypeScript-go/newfile.ts"},
3839
}
3940

4041
for _, test := range tests {
@@ -70,6 +71,7 @@ func TestFileNameToDocumentURI(t *testing.T) {
7071

7172
{"^/untitled/ts-nul-authority/Untitled-1", "untitled:Untitled-1"},
7273
{"^/untitled/ts-nul-authority/c:/Users/jrieken/Code/abc.txt", "untitled:c:/Users/jrieken/Code/abc.txt"},
74+
{"^/untitled/ts-nul-authority///wsl%2Bubuntu/home/jabaile/work/TypeScript-go/newfile.ts", "untitled://wsl%2Bubuntu/home/jabaile/work/TypeScript-go/newfile.ts"},
7375
}
7476

7577
for _, test := range tests {

0 commit comments

Comments
 (0)