Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to implement #1

Open
kirides opened this issue Jun 22, 2019 · 9 comments
Open

How to implement #1

kirides opened this issue Jun 22, 2019 · 9 comments
Labels

Comments

@kirides
Copy link

kirides commented Jun 22, 2019

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
		}
	}
}
@zchee
Copy link
Member

zchee commented Jun 24, 2019

@kirides I'll describe later :)

@zchee
Copy link
Member

zchee commented Jun 24, 2019

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

@a-h
Copy link
Contributor

a-h commented Apr 4, 2021

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.

@zchee
Copy link
Member

zchee commented Apr 5, 2021

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

@a-h
Copy link
Contributor

a-h commented Apr 5, 2021

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.

@zchee
Copy link
Member

zchee commented Apr 5, 2021

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

@kirides
Copy link
Author

kirides commented Apr 12, 2021

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

@gebv
Copy link

gebv commented Jun 13, 2021

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

@kirides
Copy link
Author

kirides commented Jun 15, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants