The first step is to create a type that will handle communication with the client, and a factory function that creates an instance of this type, and returns a pointer to the instance. The function should accept three parameters:
protocol.ClientCloser
that represents the client;context.Context
is the context in which the server runs;func()
is the context cancellation function that you can call to cancel the context.
Here's a minimal implementation:
package lsp
import (
"context"
"github.com/peske/lsp-srv/lsp/protocol"
)
// Server is the type mentioned in the instructions above.
type Server struct {
client protocol.ClientCloser
ctx context.Context
cancel func()
}
// NewServer is the factory function mentioned in the instructions above.
func NewServer(client protocol.ClientCloser, ctx context.Context, cancel func()) *Server {
return &Server{
client: client,
ctx: ctx,
cancel: cancel,
}
}
The type that you've created in the previous step must implement protocol.Server
interface. You can create all the
methods manually, but it will be much faster if you use generator.
If you want your server to use stdio
for the communication with the client, you don't have to configure anything, and
you can skip creating lsp_srv.Config
instance. But if you want communication to go via TCP for
example, you will have to create it.
Here's an example file that starts the server:
package main
import (
"log"
"github.com/peske/lsp-srv/server"
"github.com/yourgh/yourmodule/lsp"
)
func main() {
var cfg *server.Config
// Optionally create the config
// Here we assume that your factory function resides in `lsp` package, thus `lsp.NewServer`.
if err := server.Run(lsp.NewServer, cfg); err != nil {
log.Fatal(err)
}
}
You can find a few usage examples in https://github.com/peske/lsp-example repository.