protocol
protocol copied to clipboard
How to implement
How do you implement a language server using this repository?
I tried the following and it creates nilpointer exceptions because "Server" is empty
func NewLangServer(logger *zap.Logger) *LangServer {
server := new(LangServer)
return server
}
type LangServer struct {
protocol.Server
}
Initialized like this:
f, _ := os.Create("lsp-log.txt")
logr, _ := zap.NewDevelopment(zap.ErrorOutput(f))
srv := NewLangServer(logr)
conn, cl := protocol.NewServer(ctx,
srv,
jsonrpc2.NewStream(os.Stdin, os.Stdout),
logr,
jsonrpc2.WithLogger(logr))
if err := conn.Run(ctx); err != nil {
// ...
}
if err := cl.Run(ctx); err != nil {
// ...
}
produces
2019-06-22T14:57:45.363+0200 DEBUG jsonrpc2/jsonrpc2.go:346 deliver
panic: runtime error: invalid memory address or nil pointer dereference
which happens in server_json.go
func ServerHandler(ctx context.Context, server ServerInterface, logger *zap.Logger) jsonrpc2.Handler {
return func(ctx context.Context, conn *jsonrpc2.Conn, r *jsonrpc2.Request) {
dec := json.NewDecoder(bytes.NewReader(*r.Params))
switch r.Method {
case MethodInitialize:
var params InitializeParams
if err := dec.Decode(¶ms); err != nil {
ReplyError(ctx, err, conn, r, logger)
return
}
// error here: server....
resp, err := server.Initialize(ctx, ¶ms)
if err := conn.Reply(ctx, r, resp, err); err != nil {
logger.Error(MethodInitialize, zap.Error(err))
}
// .... more
}
}
}
@Kirides I'll describe later :)
@Kirides BTW, Now I develop client side (still private) So I didn't checks server side code for now, sorry :(
But I planned asm-language-server using this package, so I'll adding more testcase and checks server side code correctly.
Did you get any further on developing this?
I'm interested in developing a language server for a language that's implemented in Go. Having a base platform would be very useful.
@a-h will reply, and write example as much as possible :)
Thanks, I did find something that worked for me, so don't feel any pressure! I've put together an example here in case it's useful for you: https://github.com/a-h/qt-lsp
It's my first attempt at getting an LSP going.
@a-h for now, I'll invite you to my private repository which is lsp client side.
Did you get any further on developing this?
I'm interested in developing a language server for a language that's implemented in Go. Having a base platform would be very useful.
You can take a look at my language server implementation for daedalus (a scripting language) https://github.com/Kirides/DaedalusLanguageServer
the important code for initialization and handling of commands is in
initialization: https://github.com/Kirides/DaedalusLanguageServer/blob/master/main.go handling commands: https://github.com/Kirides/DaedalusLanguageServer/blob/master/langserver/lsphandler.go
This approach works fine for my current use case
@Kirides Hi! Will you continue to support a low-level interface jsonrpc2.StreamServer? I want to get jsonrpc2.Conn in order that send notification\request from server to the client. My LSP server is remote, hacks to sync files.
I initialize the server like this.
srv := &myServer{}
err := jsonrpc2.ListenAndServe(ctx, "tcp", "127.0.0.1:10001", jsonrpc2.HandlerServer(srv.Handler), 0)
...
type myServer struct {}
func (s *myServer) Handler(ctx context.Context, reply jsonrpc2.Replier, r jsonrpc2.Request) error { ... }
But I has to convert into anything... I haven’t come up with a beautiful solution yet.
Please advice for get jsonrpc2.Conn into handler?
@gebv in my current implementation, you could take connectLanguageServers return value (the underlying *jsonrpc2.Conn and store that in your handler for further use. (if that works, haven't checked that)