aboutsummaryrefslogtreecommitdiff
path: root/internal/lsp
diff options
context:
space:
mode:
authorIan Cottrell <iancottrell@google.com>2020-04-16 21:12:43 -0400
committerIan Cottrell <iancottrell@google.com>2020-04-20 21:06:19 +0000
commit9f075f7bfe741c212db778aed6ce67397ec4060a (patch)
tree6681c2dda9cea11e98f4916a7ab3a9a87ec99a7b /internal/lsp
parentca8a290ca5733015fd8f7b87caca2cc7490afdb7 (diff)
downloadgolang-x-tools-9f075f7bfe741c212db778aed6ce67397ec4060a.tar.gz
internal/lsp: switch the protocol logger to use the new jsonrpc2 message types
This saves it from having to know the wire format and understand the decoding tricks. Change-Id: I1f3ef3345ffee736a9d104f8ebfb436404d737c0 Reviewed-on: https://go-review.googlesource.com/c/tools/+/228721 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'internal/lsp')
-rw-r--r--internal/lsp/protocol/log.go151
1 files changed, 43 insertions, 108 deletions
diff --git a/internal/lsp/protocol/log.go b/internal/lsp/protocol/log.go
index f7cb076ce..afc037c95 100644
--- a/internal/lsp/protocol/log.go
+++ b/internal/lsp/protocol/log.go
@@ -2,7 +2,6 @@ package protocol
import (
"context"
- "encoding/json"
"fmt"
"io"
"strings"
@@ -41,23 +40,6 @@ func (s *loggingStream) Write(ctx context.Context, data []byte) (int64, error) {
return count, err
}
-// wireCombined has all the fields of both Request and Response.
-// We can decode this and then work out which it is.
-type wireCombined struct {
- VersionTag interface{} `json:"jsonrpc"`
- ID *jsonrpc2.ID `json:"id,omitempty"`
- Method string `json:"method"`
- Params *json.RawMessage `json:"params,omitempty"`
- Result *json.RawMessage `json:"result,omitempty"`
- Error *wireError `json:"error,omitempty"`
-}
-
-type wireError struct {
- Code int64 `json:"code"`
- Message string `json:"message"`
- Data *json.RawMessage `json:"data"`
-}
-
type req struct {
method string
start time.Time
@@ -112,19 +94,18 @@ func (m *mapped) setServer(id string, r req) {
const eor = "\r\n\r\n\r\n"
-func logCommon(outfd io.Writer, data []byte) (*wireCombined, time.Time, string) {
+func logCommon(outfd io.Writer, data []byte) (jsonrpc2.Message, time.Time, string) {
if outfd == nil {
return nil, time.Time{}, ""
}
- var v wireCombined
- err := json.Unmarshal(data, &v)
+ v, err := jsonrpc2.DecodeMessage(data)
if err != nil {
fmt.Fprintf(outfd, "Unmarshal %v\n", err)
panic(err) // do better
}
tm := time.Now()
tmfmt := tm.Format("15:04:05.000 PM")
- return &v, tm, tmfmt
+ return v, tm, tmfmt
}
// logOut and logIn could be combined. "received"<->"Sending", serverCalls<->clientCalls
@@ -132,111 +113,65 @@ func logCommon(outfd io.Writer, data []byte) (*wireCombined, time.Time, string)
// Writing a message to the client, log it
func logOut(outfd io.Writer, data []byte) {
- v, tm, tmfmt := logCommon(outfd, data)
- if v == nil {
- return
- }
- id := fmt.Sprint(v.ID)
- if v.Error != nil {
- fmt.Fprintf(outfd, "[Error - %s] Received #%s %s%s", tmfmt, id, v.Error.Message, eor)
+ msg, tm, tmfmt := logCommon(outfd, data)
+ if msg == nil {
return
}
+
buf := strings.Builder{}
fmt.Fprintf(&buf, "[Trace - %s] ", tmfmt) // common beginning
- if v.ID != nil && v.Method != "" && v.Params != nil {
- fmt.Fprintf(&buf, "Received request '%s - (%s)'.\n", v.Method, id)
- fmt.Fprintf(&buf, "Params: %s%s", *v.Params, eor)
- maps.setServer(id, req{method: v.Method, start: tm})
- } else if v.ID != nil && v.Method == "" && v.Params == nil {
+ switch msg := msg.(type) {
+ case *jsonrpc2.Call:
+ id := fmt.Sprint(msg.ID())
+ fmt.Fprintf(&buf, "Received request '%s - (%s)'.\n", msg.Method(), id)
+ fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
+ maps.setServer(id, req{method: msg.Method(), start: tm})
+ case *jsonrpc2.Notification:
+ fmt.Fprintf(&buf, "Received notification '%s'.\n", msg.Method())
+ fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
+ case *jsonrpc2.Response:
+ id := fmt.Sprint(msg.ID())
+ if err := msg.Err(); err != nil {
+ fmt.Fprintf(outfd, "[Error - %s] Received #%s %s%s", tmfmt, id, err, eor)
+ return
+ }
cc := maps.client(id, true)
elapsed := tm.Sub(cc.start)
fmt.Fprintf(&buf, "Received response '%s - (%s)' in %dms.\n",
cc.method, id, elapsed/time.Millisecond)
- if v.Result == nil {
- fmt.Fprintf(&buf, "Result: {}%s", eor)
- } else {
- fmt.Fprintf(&buf, "Result: %s%s", string(*v.Result), eor)
- }
- } else if v.ID == nil && v.Method != "" && v.Params != nil {
- p := "null"
- if v.Params != nil {
- p = string(*v.Params)
- }
- fmt.Fprintf(&buf, "Received notification '%s'.\n", v.Method)
- fmt.Fprintf(&buf, "Params: %s%s", p, eor)
- } else { // for completeness, as it should never happen
- buf = strings.Builder{} // undo common Trace
- fmt.Fprintf(&buf, "[Error - %s] on write ID?%v method:%q Params:%v Result:%v Error:%v%s",
- tmfmt, v.ID != nil, v.Method, v.Params != nil,
- v.Result != nil, v.Error != nil, eor)
- p := "null"
- if v.Params != nil {
- p = string(*v.Params)
- }
- r := "null"
- if v.Result != nil {
- r = string(*v.Result)
- }
- fmt.Fprintf(&buf, "%s\n%s\n%s%s", p, r, v.Error.Message, eor)
+ fmt.Fprintf(&buf, "Result: %s%s", msg.Result(), eor)
}
outfd.Write([]byte(buf.String()))
}
// Got a message from the client, log it
func logIn(outfd io.Writer, data []byte) {
- v, tm, tmfmt := logCommon(outfd, data)
- if v == nil {
- return
- }
- id := fmt.Sprint(v.ID)
- // ID Method Params => Sending request
- // ID !Method Result(might be null, but !Params) => Sending response (could we get an Error?)
- // !ID Method Params => Sending notification
- if v.Error != nil { // does this ever happen?
- fmt.Fprintf(outfd, "[Error - %s] Sent #%s %s%s", tmfmt, id, v.Error.Message, eor)
+ msg, tm, tmfmt := logCommon(outfd, data)
+ if msg == nil {
return
}
buf := strings.Builder{}
fmt.Fprintf(&buf, "[Trace - %s] ", tmfmt) // common beginning
- if v.ID != nil && v.Method != "" && (v.Params != nil || v.Method == "shutdown") {
- fmt.Fprintf(&buf, "Sending request '%s - (%s)'.\n", v.Method, id)
- x := "{}"
- if v.Params != nil {
- x = string(*v.Params)
- }
- fmt.Fprintf(&buf, "Params: %s%s", x, eor)
- maps.setClient(id, req{method: v.Method, start: tm})
- } else if v.ID != nil && v.Method == "" && v.Params == nil {
- sc := maps.server(id, true)
- elapsed := tm.Sub(sc.start)
- fmt.Fprintf(&buf, "Sending response '%s - (%s)' took %dms.\n",
- sc.method, id, elapsed/time.Millisecond)
- if v.Result == nil {
- fmt.Fprintf(&buf, "Result: {}%s", eor)
- } else {
- fmt.Fprintf(&buf, "Result: %s%s", string(*v.Result), eor)
- }
- } else if v.ID == nil && v.Method != "" {
- p := "null"
- if v.Params != nil {
- p = string(*v.Params)
+ switch msg := msg.(type) {
+ case *jsonrpc2.Call:
+ id := fmt.Sprint(msg.ID())
+ fmt.Fprintf(&buf, "Sending request '%s - (%s)'.\n", msg.Method(), id)
+ fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
+ maps.setServer(id, req{method: msg.Method(), start: tm})
+ case *jsonrpc2.Notification:
+ fmt.Fprintf(&buf, "Sending notification '%s'.\n", msg.Method())
+ fmt.Fprintf(&buf, "Params: %s%s", msg.Params(), eor)
+ case *jsonrpc2.Response:
+ id := fmt.Sprint(msg.ID())
+ if err := msg.Err(); err != nil {
+ fmt.Fprintf(outfd, "[Error - %s] Sent #%s %s%s", tmfmt, id, err, eor)
+ return
}
- fmt.Fprintf(&buf, "Sending notification '%s'.\n", v.Method)
- fmt.Fprintf(&buf, "Params: %s%s", p, eor)
- } else { // for completeness, as it should never happen
- buf = strings.Builder{} // undo common Trace
- fmt.Fprintf(&buf, "[Error - %s] on read ID?%v method:%q Params:%v Result:%v Error:%v%s",
- tmfmt, v.ID != nil, v.Method, v.Params != nil,
- v.Result != nil, v.Error != nil, eor)
- p := "null"
- if v.Params != nil {
- p = string(*v.Params)
- }
- r := "null"
- if v.Result != nil {
- r = string(*v.Result)
- }
- fmt.Fprintf(&buf, "%s\n%s\n%s%s", p, r, v.Error.Message, eor)
+ cc := maps.client(id, true)
+ elapsed := tm.Sub(cc.start)
+ fmt.Fprintf(&buf, "Sending response '%s - (%s)' in %dms.\n",
+ cc.method, id, elapsed/time.Millisecond)
+ fmt.Fprintf(&buf, "Result: %s%s", msg.Result(), eor)
}
outfd.Write([]byte(buf.String()))
}