From 9b9b4d83451eebe830f0e28c354b3f19823197c1 Mon Sep 17 00:00:00 2001 From: Julio Tain Sueiras Date: Tue, 25 Feb 2020 20:02:35 -0500 Subject: [PATCH] Added TCP Server mode(however need to find out how to push msgs) --- helper/file.go | 10 ++--- langserver/did_change.go | 10 +++-- langserver/did_open.go | 10 +++-- langserver/document_link.go | 50 ++++++++++----------- langserver/initialize.go | 14 +++--- langserver/main.go | 89 +++++++++++++++++++++++++++++++++---- langserver/temp.go | 4 +- main.go | 20 +++------ 8 files changed, 140 insertions(+), 67 deletions(-) diff --git a/helper/file.go b/helper/file.go index 12453b6..8a2f4a6 100644 --- a/helper/file.go +++ b/helper/file.go @@ -88,11 +88,11 @@ func FindOffset(fileText string, line, column int) int { } func DumpLog(res interface{}) { - result := spew.Sdump(res) - strSlice:=strings.Split(result, "\n") - for _, s := range strSlice { - log.Debug(s) - } + result := spew.Sdump(res) + strSlice := strings.Split(result, "\n") + for _, s := range strSlice { + log.Debug(s) + } } func ParseVariables(vars hcl.Traversal, configVars map[string]*configs.Variable, completionItems []lsp.CompletionItem) []lsp.CompletionItem { diff --git a/langserver/did_change.go b/langserver/did_change.go index 2d48941..eed6243 100644 --- a/langserver/did_change.go +++ b/langserver/did_change.go @@ -19,9 +19,11 @@ func TextDocumentDidChange(ctx context.Context, vs lsp.DidChangeTextDocumentPara DiagsFiles[fileURL] = tfstructs.GetDiagnostics(tempFile.Name(), fileURL) - TextDocumentPublishDiagnostics(Server, ctx, lsp.PublishDiagnosticsParams{ - URI: vs.TextDocument.URI, - Diagnostics: DiagsFiles[fileURL], - }) + if !isTCP { + TextDocumentPublishDiagnostics(StdioServer, ctx, lsp.PublishDiagnosticsParams{ + URI: vs.TextDocument.URI, + Diagnostics: DiagsFiles[fileURL], + }) + } return nil } diff --git a/langserver/did_open.go b/langserver/did_open.go index 7eae969..c6b92eb 100644 --- a/langserver/did_open.go +++ b/langserver/did_open.go @@ -15,10 +15,12 @@ func TextDocumentDidOpen(ctx context.Context, vs lsp.DidOpenTextDocumentParams) DiagsFiles[fileURL] = tfstructs.GetDiagnostics(fileURL, fileURL) - TextDocumentPublishDiagnostics(Server, ctx, lsp.PublishDiagnosticsParams{ - URI: vs.TextDocument.URI, - Diagnostics: DiagsFiles[fileURL], - }) + if !isTCP { + TextDocumentPublishDiagnostics(StdioServer, ctx, lsp.PublishDiagnosticsParams{ + URI: vs.TextDocument.URI, + Diagnostics: DiagsFiles[fileURL], + }) + } tempFile.Write([]byte(vs.TextDocument.Text)) return nil } diff --git a/langserver/document_link.go b/langserver/document_link.go index 5cfb4fc..2051fab 100644 --- a/langserver/document_link.go +++ b/langserver/document_link.go @@ -2,42 +2,42 @@ package langserver import ( "context" - lsp "github.com/sourcegraph/go-lsp" log "github.com/sirupsen/logrus" + lsp "github.com/sourcegraph/go-lsp" ) type documentLinkParams struct { - TextDocument lsp.TextDocumentItem `json:"textDocument"` + TextDocument lsp.TextDocumentItem `json:"textDocument"` } type DocumentLink struct { - Range lsp.Range `json:"range"` + Range lsp.Range `json:"range"` - /** - * The uri this link points to. If missing a resolve request is sent later. - */ - Target string `json:"target"` + /** + * The uri this link points to. If missing a resolve request is sent later. + */ + Target string `json:"target"` - Tooltip string `json:"tooltip"` + Tooltip string `json:"tooltip"` } func TextDocumentDocumentLink(ctx context.Context, vs documentLinkParams) ([]DocumentLink, error) { - log.Info(vs) + log.Info(vs) - return []DocumentLink{ - DocumentLink{ - Range: lsp.Range{ - Start: lsp.Position{ - Line: 1, - Character: 1, - }, - End: lsp.Position{ - Line: 1, - Character: 10, - }, - }, - Target: "https://github.com", - Tooltip: "https://github.com", - }, - }, nil + return []DocumentLink{ + DocumentLink{ + Range: lsp.Range{ + Start: lsp.Position{ + Line: 1, + Character: 1, + }, + End: lsp.Position{ + Line: 1, + Character: 10, + }, + }, + Target: "https://github.com", + Tooltip: "https://github.com", + }, + }, nil } diff --git a/langserver/initialize.go b/langserver/initialize.go index d7628fd..5a8825a 100644 --- a/langserver/initialize.go +++ b/langserver/initialize.go @@ -9,18 +9,18 @@ import ( ) type DocumentLinkOptions struct { - ResolveProvider bool `json:"resolveProvider,omitempty"` + ResolveProvider bool `json:"resolveProvider,omitempty"` } type ExtendedServerCapabilities struct { - TextDocumentSync *lsp.TextDocumentSyncOptionsOrKind `json:"textDocumentSync,omitempty"` - CompletionProvider *lsp.CompletionOptions `json:"completionProvider,omitempty"` - HoverProvider bool `json:"hoverProvider,omitempty"` - DocumentLinkProvider *DocumentLinkOptions `json:"documentLinkProvider,omitempty"` + TextDocumentSync *lsp.TextDocumentSyncOptionsOrKind `json:"textDocumentSync,omitempty"` + CompletionProvider *lsp.CompletionOptions `json:"completionProvider,omitempty"` + HoverProvider bool `json:"hoverProvider,omitempty"` + DocumentLinkProvider *DocumentLinkOptions `json:"documentLinkProvider,omitempty"` } type ExtendedInitializeResult struct { - Capabilities ExtendedServerCapabilities `json:"capabilities"` + Capabilities ExtendedServerCapabilities `json:"capabilities"` } func Initialize(ctx context.Context, vs lsp.InitializeParams) (ExtendedInitializeResult, error) { @@ -45,7 +45,7 @@ func Initialize(ctx context.Context, vs lsp.InitializeParams) (ExtendedInitializ }, HoverProvider: false, DocumentLinkProvider: &DocumentLinkOptions{ - ResolveProvider: false, + ResolveProvider: false, }, }, }, nil diff --git a/langserver/main.go b/langserver/main.go index aabbbfb..6f895ee 100644 --- a/langserver/main.go +++ b/langserver/main.go @@ -1,17 +1,25 @@ package langserver import ( + "context" "github.com/creachadair/jrpc2" + "github.com/creachadair/jrpc2/channel" "github.com/creachadair/jrpc2/handler" + "github.com/creachadair/jrpc2/server" + log "github.com/sirupsen/logrus" + "net" + "os" ) -func CreateServer() *jrpc2.Server { - Server = jrpc2.NewServer(handler.Map{ - "initialize": handler.New(Initialize), - "textDocument/completion": handler.New(TextDocumentComplete), - "textDocument/didChange": handler.New(TextDocumentDidChange), - "textDocument/didOpen": handler.New(TextDocumentDidOpen), - "textDocument/didClose": handler.New(TextDocumentDidClose), +func RunStdioServer() { + isTCP = false + + StdioServer = jrpc2.NewServer(handler.Map{ + "initialize": handler.New(Initialize), + "textDocument/completion": handler.New(TextDocumentComplete), + "textDocument/didChange": handler.New(TextDocumentDidChange), + "textDocument/didOpen": handler.New(TextDocumentDidOpen), + "textDocument/didClose": handler.New(TextDocumentDidClose), "textDocument/documentLink": handler.New(TextDocumentDocumentLink), //"textDocument/hover": handler.New(TextDocumentHover), //"textDocument/references": handler.New(TextDocumentReferences), @@ -23,5 +31,70 @@ func CreateServer() *jrpc2.Server { AllowPush: true, }) - return Server + StdioServer.Start(channel.Header("")(os.Stdin, os.Stdout)) + + log.Info("Server started") + + // Wait for the server to exit, and report any errors. + if err := StdioServer.Wait(); err != nil { + log.Printf("Server exited: %v", err) + } + + log.Info("Server Finish") +} + +func RunTCPServer(port int) { + isTCP = true + + ServiceMap = handler.Map{ + "initialize": handler.New(Initialize), + "textDocument/completion": handler.New(TextDocumentComplete), + "textDocument/didChange": handler.New(TextDocumentDidChange), + "textDocument/didOpen": handler.New(TextDocumentDidOpen), + "textDocument/didClose": handler.New(TextDocumentDidClose), + "textDocument/documentLink": handler.New(TextDocumentDocumentLink), + //"textDocument/hover": handler.New(TextDocumentHover), + //"textDocument/references": handler.New(TextDocumentReferences), + //"textDocument/codeLens": handler.New(TextDocumentCodeLens), + "exit": handler.New(Exit), + "shutdown": handler.New(Shutdown), + "$/cancelRequest": handler.New(CancelRequest), + } + + // Start the server on a channel comprising stdin/stdout. + + lst, err := net.Listen("tcp", "127.0.0.1:9900") + if err != nil { + log.Fatalf("Listen: %v", err) + } + + newChan := channel.Header("") + + ctx := context.Background() + + ctx, cancelFunc := context.WithCancel(ctx) + + go func() { + if err := server.Loop(lst, ServiceMap, &server.LoopOptions{ + Framing: newChan, + ServerOptions: &jrpc2.ServerOptions{ + AllowPush: true, + }, + }); err != nil { + log.Errorf("Loop: unexpected failure: %v", err) + cancelFunc() + return + } + }() + + select { + case <-ctx.Done(): + log.Info("Server Finish") + err := lst.Close() + if err != nil { + log.Info("Server Finish") + log.Info(ctx.Err()) + return + } + } } diff --git a/langserver/temp.go b/langserver/temp.go index 104acd8..f1ce567 100644 --- a/langserver/temp.go +++ b/langserver/temp.go @@ -8,4 +8,6 @@ import ( var tempFile afero.File var DiagsFiles = make(map[string][]lsp.Diagnostic) -var Server *jrpc2.Server +var StdioServer *jrpc2.Server +var ServiceMap jrpc2.Assigner +var isTCP bool diff --git a/main.go b/main.go index e3fa8af..5feac4c 100644 --- a/main.go +++ b/main.go @@ -4,15 +4,16 @@ import ( "flag" "fmt" log "github.com/sirupsen/logrus" + "io/ioutil" oldLog "log" "os" "strings" - "github.com/creachadair/jrpc2/channel" "github.com/juliosueiras/terraform-lsp/langserver" - "io/ioutil" ) +var tcp = flag.Bool("tcp", false, "Use TCP instead of Stdio(which is default)") +var port = flag.Int("port", 9900, "Port for TCP Server") var location = flag.String("log-location", "", "Location of the lsp log") var debug = flag.Bool("debug", false, "Enable debug output") var enableLogFile = flag.Bool("enable-log-file", false, "Enable log file") @@ -34,8 +35,6 @@ func main() { return } - Server := langserver.CreateServer() - log.Infof("Log Level is Debug: %t", *debug) if *debug { @@ -53,14 +52,9 @@ func main() { log.SetOutput(f) } - // Start the server on a channel comprising stdin/stdout. - Server.Start(channel.Header("")(os.Stdin, os.Stdout)) - log.Info("Server started") - - // Wait for the server to exit, and report any errors. - if err := Server.Wait(); err != nil { - log.Printf("Server exited: %v", err) + if *tcp { + langserver.RunTCPServer(*port) + } else { + langserver.RunStdioServer() } - - log.Info("Server Finish") }