protocol icon indicating copy to clipboard operation
protocol copied to clipboard

How to implement

Open kirides opened this issue 6 years ago • 9 comments
trafficstars

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(&params); err != nil {
				ReplyError(ctx, err, conn, r, logger)
				return
			}
			// error here: server....
			resp, err := server.Initialize(ctx, &params)
			if err := conn.Reply(ctx, r, resp, err); err != nil {
				logger.Error(MethodInitialize, zap.Error(err))
			}
			// .... more
		}
	}
}

kirides avatar Jun 22 '19 13:06 kirides

@Kirides I'll describe later :)

zchee avatar Jun 24 '19 18:06 zchee

@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.

zchee avatar Jun 24 '19 18:06 zchee

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 avatar Apr 04 '21 18:04 a-h

@a-h will reply, and write example as much as possible :)

zchee avatar Apr 05 '21 06:04 zchee

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 avatar Apr 05 '21 09:04 a-h

@a-h for now, I'll invite you to my private repository which is lsp client side.

zchee avatar Apr 05 '21 13:04 zchee

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 avatar Apr 12 '21 08:04 kirides

@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 avatar Jun 13 '21 23:06 gebv

@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)

kirides avatar Jun 15 '21 07:06 kirides