Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Commit

Permalink
Implement gnopls server with basic handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
harry-hov committed Sep 22, 2023
1 parent cba417e commit 4914686
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 0 deletions.
11 changes: 11 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"fmt"
"log/slog"
"os"

"github.com/harry-hov/gnopls/internal/env"
"github.com/harry-hov/gnopls/internal/lsp"
"github.com/spf13/cobra"
)

Expand All @@ -15,6 +18,14 @@ func GnoplsCmd() *cobra.Command {
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
slog.Info("Initializing Server...")
env := &env.Env{
GNOROOT: os.Getenv("GNOROOT"),
GNOHOME: env.GnoHome(),
}
err := lsp.RunServer(cmd.Context(), env)
if err != nil {
return err
}

return nil
},
Expand Down
15 changes: 15 additions & 0 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package cmd

import (
"log/slog"
"os"

"github.com/harry-hov/gnopls/internal/env"
"github.com/harry-hov/gnopls/internal/lsp"
"github.com/spf13/cobra"
)

Expand All @@ -13,6 +17,17 @@ func CmdServe() *cobra.Command {
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
slog.Info("Initializing Server...")
env := &env.Env{
GNOROOT: gnoroot,
GNOHOME: env.GnoHome(),
}
if env.GNOROOT == "" {
env.GNOROOT = os.Getenv("GNOROOT")
}
err := lsp.RunServer(cmd.Context(), env)
if err != nil {
return err
}

return nil
},
Expand Down
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@ go 1.21.1
require (
github.com/google/go-github v17.0.0+incompatible
github.com/spf13/cobra v1.5.0
go.lsp.dev/jsonrpc2 v0.10.0
go.lsp.dev/pkg v0.0.0-20210717090340-384b27a52fb2
go.lsp.dev/protocol v0.12.0
)

require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/segmentio/asm v1.1.3 // indirect
github.com/segmentio/encoding v0.3.4 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.4 // indirect
go.lsp.dev/uri v0.3.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/sys v0.12.0 // indirect
)
49 changes: 49 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,59 @@
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc=
github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
github.com/segmentio/encoding v0.3.4 h1:WM4IBnxH8B9TakiM2QD5LyNl9JSndh88QbHqVC+Pauc=
github.com/segmentio/encoding v0.3.4/go.mod h1:n0JeuIqEQrQoPDGsjo8UNd1iA0U8d8+oHAA4E3G3OxM=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.lsp.dev/jsonrpc2 v0.10.0 h1:Pr/YcXJoEOTMc/b6OTmcR1DPJ3mSWl/SWiU1Cct6VmI=
go.lsp.dev/jsonrpc2 v0.10.0/go.mod h1:fmEzIdXPi/rf6d4uFcayi8HpFP1nBF99ERP1htC72Ac=
go.lsp.dev/pkg v0.0.0-20210717090340-384b27a52fb2 h1:hCzQgh6UcwbKgNSRurYWSqh8MufqRRPODRBblutn4TE=
go.lsp.dev/pkg v0.0.0-20210717090340-384b27a52fb2/go.mod h1:gtSHRuYfbCT0qnbLnovpie/WEmqyJ7T4n6VXiFMBtcw=
go.lsp.dev/protocol v0.12.0 h1:tNprUI9klQW5FAFVM4Sa+AbPFuVQByWhP1ttNUAjIWg=
go.lsp.dev/protocol v0.12.0/go.mod h1:Qb11/HgZQ72qQbeyPfJbu3hZBH23s1sr4st8czGeDMQ=
go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo=
go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
12 changes: 12 additions & 0 deletions internal/lsp/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package lsp

import (
"context"
"fmt"

"go.lsp.dev/jsonrpc2"
)

func sendParseError(ctx context.Context, reply jsonrpc2.Replier, err error) error {
return reply(ctx, nil, fmt.Errorf("%w: %s", jsonrpc2.ErrParse, err))
}
23 changes: 23 additions & 0 deletions internal/lsp/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package lsp

import (
"context"
"errors"
"io"
"os"

"github.com/harry-hov/gnopls/internal/env"
"go.lsp.dev/jsonrpc2"
"go.lsp.dev/pkg/fakenet"
)

func RunServer(ctx context.Context, env *env.Env) error {
conn := jsonrpc2.NewConn(jsonrpc2.NewStream(fakenet.NewConn("stdio", os.Stdin, os.Stdout)))
handler := BuildServerHandler(conn, env)
stream := jsonrpc2.HandlerServer(handler)
err := stream.ServeStream(ctx, conn)
if errors.Is(err, io.EOF) {
return nil
}
return err
}
102 changes: 102 additions & 0 deletions internal/lsp/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package lsp

import (
"context"
"encoding/json"
"log/slog"
"os"
"path/filepath"

"go.lsp.dev/jsonrpc2"
"go.lsp.dev/protocol"

"github.com/harry-hov/gnopls/internal/env"
"github.com/harry-hov/gnopls/internal/version"
)

type server struct {
conn jsonrpc2.Conn
env *env.Env

}

func BuildServerHandler(conn jsonrpc2.Conn, env *env.Env) jsonrpc2.Handler {
dirs := []string{}
if env.GNOROOT != "" {
dirs = append(dirs, filepath.Join(env.GNOROOT, "examples"))
dirs = append(dirs, filepath.Join(env.GNOROOT, "gnovm/stdlibs"))
}
server := &server{
conn: conn,

env: env,

}

return jsonrpc2.ReplyHandler(server.ServerHandler)
}

func (s *server) ServerHandler(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {
switch req.Method() {
case "exit":
return s.Exit(ctx, reply, req)
case "initialize":
return s.Initialize(ctx, reply, req)
case "initialized":
return s.Initialized(ctx, reply, req)
case "shutdown":
return s.Shutdown(ctx, reply, req)
default:
return jsonrpc2.MethodNotFoundHandler(ctx, reply, req)
}
}

func (s *server) Initialize(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error {
var params protocol.InitializeParams
if err := json.Unmarshal(req.Params(), &params); err != nil {
return sendParseError(ctx, reply, err)
}

return reply(ctx, protocol.InitializeResult{
ServerInfo: &protocol.ServerInfo{
Name: "gnopls",
Version: version.Version,
},
Capabilities: protocol.ServerCapabilities{
TextDocumentSync: protocol.TextDocumentSyncOptions{
Change: protocol.TextDocumentSyncKindFull,
OpenClose: true,
Save: &protocol.SaveOptions{
IncludeText: true,
},
},
CompletionProvider: &protocol.CompletionOptions{
TriggerCharacters: []string{"."},
ResolveProvider: false,
},
HoverProvider: true,
ExecuteCommandProvider: &protocol.ExecuteCommandOptions{
Commands: []string{
"gnopls.version",
},
},
DocumentFormattingProvider: true,
},
}, nil)
}

func (s *server) Initialized(ctx context.Context, reply jsonrpc2.Replier, _ jsonrpc2.Request) error {
slog.Info("initialized")
return reply(ctx, nil, nil)
}

func (s *server) Shutdown(ctx context.Context, reply jsonrpc2.Replier, _ jsonrpc2.Request) error {
slog.Info("shutdown")
return reply(ctx, nil, s.conn.Close())
}

func (s *server) Exit(ctx context.Context, reply jsonrpc2.Replier, _ jsonrpc2.Request) error {
slog.Info("exit")
os.Exit(1)
return nil
}

0 comments on commit 4914686

Please sign in to comment.