diff --git a/go-lsp/jsonrpc/server.go b/go-lsp/jsonrpc/server.go index 55e91fb..1becd1d 100644 --- a/go-lsp/jsonrpc/server.go +++ b/go-lsp/jsonrpc/server.go @@ -53,3 +53,13 @@ func (s *Server) newSession(conn ReaderWriter) *Session { s.session[id] = session return session } + +func (s *Server) SendMsg(resp interface{}) error { + for _, session := range s.session { + if session != nil { + session.SendMsg(resp) + break + } + } + return nil +} diff --git a/go-lsp/jsonrpc/session.go b/go-lsp/jsonrpc/session.go index 9067180..65e3594 100644 --- a/go-lsp/jsonrpc/session.go +++ b/go-lsp/jsonrpc/session.go @@ -236,6 +236,26 @@ func (s *Session) handlerRequest(req RequestMessage) error { return nil } +func (s *Session) SendMsg(resp interface{}) error { + s.writeLock.Lock() + defer s.writeLock.Unlock() + res, err := jsoniter.Marshal(resp) + if err != nil { + return err + } + logs.Printf("SendMsg: [%v]\n", string(res)) + totalLen := len(res) + err = s.mustWrite([]byte(fmt.Sprintf("Content-Length: %d\r\n\r\n", totalLen))) + if err != nil { + return err + } + err = s.mustWrite(res) + if err != nil { + return err + } + return nil +} + func (s *Session) write(resp ResponseMessage) error { s.writeLock.Lock() defer s.writeLock.Unlock() diff --git a/go-lsp/lsp/server.go b/go-lsp/lsp/server.go index 7c739de..b30be47 100644 --- a/go-lsp/lsp/server.go +++ b/go-lsp/lsp/server.go @@ -80,3 +80,7 @@ func isNil(i interface{}) bool { } return false } + +func (s *Server) SendMsg(resp interface{}) error { + return s.rpcServer.SendMsg(resp) +} diff --git a/proto/view/view.go b/proto/view/view.go index 7e2bb05..eac0a3a 100644 --- a/proto/view/view.go +++ b/proto/view/view.go @@ -8,6 +8,8 @@ import ( "os" "path" "path/filepath" + "regexp" + "strconv" "strings" "sync" "unicode/utf8" @@ -33,6 +35,7 @@ type view struct { openFileMu *sync.RWMutex pbHeaders map[defines.DocumentUri][]string + Server *lsp.Server } func (v *view) GetFile(document_uri defines.DocumentUri) (ProtoFile, error) { @@ -51,6 +54,11 @@ func (v *view) GetFile(document_uri defines.DocumentUri) (ProtoFile, error) { return nil, fmt.Errorf("%v not found", document_uri) } +type Diagnositcs struct { + Method string `json:"method"` + Params defines.PublishDiagnosticsParams `json:"params"` +} + // setContent sets the file contents for a file. func (v *view) setContent(ctx context.Context, document_uri defines.DocumentUri, data []byte) { @@ -77,6 +85,7 @@ func (v *view) setContent(ctx context.Context, document_uri defines.DocumentUri, // Currently it parses every time of file change. proto, err := parseProto(document_uri, data) + defer v.sendDiagnose(document_uri, err) if err != nil { return } @@ -134,6 +143,58 @@ func (v *view) isOpen(document_uri defines.DocumentUri) bool { return open } +func (v *view) sendDiagnose(document_uri defines.DocumentUri, err error) { + res := Diagnositcs{ + Method: "textDocument/publishDiagnostics", + Params: defines.PublishDiagnosticsParams{ + Uri: document_uri, + Diagnostics: []defines.Diagnostic{}, + }, + } + defer func() { + ViewManager.Server.SendMsg(res) + }() + if err == nil { + return + } + input := err.Error() + re := regexp.MustCompile(`:(\d+):(\d+)`) + matches := re.FindStringSubmatch(input) + + line, row := 0, 0 + if len(matches) == 3 { + line, err = strconv.Atoi(matches[1]) + if err != nil { + logs.Printf("Error:%v\n", err) + return + } + row, err = strconv.Atoi(matches[2]) + if err != nil { + logs.Printf("Error:%v\n", err) + return + } + } + if line == 0 || row == 0 { + return + } + logs.Println(row) + severity := defines.DiagnosticSeverityError + res.Params.Diagnostics = append(res.Params.Diagnostics, defines.Diagnostic{ + Message: input, + Severity: &severity, + Range: defines.Range{ + Start: defines.Position{ + Line: uint(line - 1), + Character: uint(row - 1), + }, + End: defines.Position{ + Line: uint(line - 1), + Character: uint(row), + }, + }, + }) +} + func (v *view) openFile(document_uri defines.DocumentUri, data []byte) { v.fileMu.Lock() defer v.fileMu.Unlock() @@ -147,6 +208,7 @@ func (v *view) openFile(document_uri defines.DocumentUri, data []byte) { } proto, err := parseProto(document_uri, data) + defer v.sendDiagnose(document_uri, err) if err != nil { return } @@ -249,7 +311,6 @@ func didOpen(ctx context.Context, params *defines.DidOpenTextDocumentParams) err text := []byte(params.TextDocument.Text) ViewManager.didOpen(document_uri, text) - return nil } @@ -309,7 +370,9 @@ func onDidChangeConfiguration(ctx context.Context, req *defines.DidChangeConfigu } func Init(server *lsp.Server) { + ViewManager = newView() + ViewManager.Server = server server.OnInitialized(onInitialized) server.OnDidChangeConfiguration(onDidChangeConfiguration)