Skip to content
This repository was archived by the owner on Jul 28, 2022. It is now read-only.

Commit 1228a1f

Browse files
committed
Add hack to send didOpen notifications as flag
1 parent eb060bd commit 1228a1f

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

proxy.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
"encoding/json"
66
"flag"
77
"fmt"
8+
"io/ioutil"
89
"log"
910
"net"
11+
"net/url"
1012
"os"
1113
"os/signal"
1214
"path/filepath"
@@ -21,9 +23,10 @@ import (
2123
)
2224

2325
var (
24-
proxyAddr = flag.String("proxyAddress", "127.0.0.1:8080", "proxy server listen address (tcp)")
25-
cacheDir = flag.String("cacheDirectory", filepath.Join(os.TempDir(), "proxy-cache"), "cache directory location")
26-
trace = flag.Bool("trace", false, "trace logs to stderr")
26+
proxyAddr = flag.String("proxyAddress", "127.0.0.1:8080", "proxy server listen address (tcp)")
27+
cacheDir = flag.String("cacheDirectory", filepath.Join(os.TempDir(), "proxy-cache"), "cache directory location")
28+
didOpenLanguage = flag.String("didOpenLanguage", "", "(HACK) If non-empty, send 'textDocument/didOpen' notifications with the specified language field (e.x. 'python') to the language server for every file.")
29+
trace = flag.Bool("trace", false, "trace logs to stderr")
2730
)
2831

2932
type cloneProxy struct {
@@ -35,6 +38,10 @@ type cloneProxy struct {
3538

3639
ready chan struct{} // barrier to block handling requests until the proxy is fully initalized
3740
ctx context.Context
41+
42+
// HACK
43+
didOpenMu sync.Mutex
44+
didOpen map[string]bool
3845
}
3946

4047
func (p *cloneProxy) start() {
@@ -114,6 +121,7 @@ func main() {
114121
ctx: ctx,
115122
sessionID: uuid.New(),
116123
lastRequestID: newAtomicCounter(),
124+
didOpen: map[string]bool{},
117125
}
118126

119127
var serverConnOpts []jsonrpc2.ConnOpt
@@ -177,7 +185,53 @@ func (p *cloneProxy) handleClientRequest(ctx context.Context, conn *jsonrpc2.Con
177185
src: p.client,
178186
dest: p.server,
179187

180-
updateURIFromSrc: func(uri lsp.DocumentURI) lsp.DocumentURI { return clientToServerURI(uri, p.workspaceCacheDir()) },
188+
updateURIFromSrc: func(uri lsp.DocumentURI) lsp.DocumentURI {
189+
uri = clientToServerURI(uri, p.workspaceCacheDir())
190+
191+
// HACK
192+
//
193+
// Some language servers don't follow LSP correctly, and refuse to handle requests that
194+
// operate on files that the language server hasn't received a a 'textDocument/didOpen'
195+
// request for yet.
196+
//
197+
// See this issue for more context: https://github.com/Microsoft/language-server-protocol/issues/177
198+
// There is also a corresponding PR to officialy put this clarification in the text:
199+
// https://github.com/Microsoft/language-server-protocol/pull/431
200+
//
201+
// This hack is necessary to get those offending language servers to work at all.
202+
//
203+
// This is not indended to be a robust implementation, so there is no attempt to send
204+
// matching 'textDocument/didClose' requests / etc.
205+
if *didOpenLanguage != "" {
206+
if parsedURI, err := url.Parse(string(uri)); err == nil && probablyFileURI(parsedURI) {
207+
p.didOpenMu.Lock()
208+
sent := p.didOpen[parsedURI.Path]
209+
if !sent {
210+
p.didOpen[parsedURI.Path] = true
211+
}
212+
p.didOpenMu.Unlock()
213+
214+
if !sent {
215+
b, err := ioutil.ReadFile(parsedURI.Path)
216+
if err == nil {
217+
err = p.server.Notify(ctx, "textDocument/didOpen", &lsp.DidOpenTextDocumentParams{
218+
TextDocument: lsp.TextDocumentItem{
219+
URI: uri,
220+
LanguageID: *didOpenLanguage,
221+
Version: 1,
222+
Text: string(b),
223+
},
224+
})
225+
if err != nil {
226+
log.Println("error sending didOpen", err)
227+
}
228+
}
229+
}
230+
}
231+
}
232+
233+
return uri
234+
},
181235
updateURIFromDest: func(uri lsp.DocumentURI) lsp.DocumentURI { return serverToClientURI(uri, p.workspaceCacheDir()) },
182236
}
183237

0 commit comments

Comments
 (0)