1
0
mirror of https://github.com/golang/go synced 2024-11-18 10:14:45 -07:00

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>
This commit is contained in:
Ian Cottrell 2020-04-16 21:12:43 -04:00
parent ca8a290ca5
commit 9f075f7bfe

View File

@ -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)
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, "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)
}
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()))
}