diff --git a/tsc/internal/jsonrpc/jsonrpc.go b/tsc/internal/jsonrpc/jsonrpc.go index 24438ccac5cc9..dad6a4f5d2dad 100644 --- a/tsc/internal/jsonrpc/jsonrpc.go +++ b/tsc/internal/jsonrpc/jsonrpc.go @@ -106,8 +106,8 @@ func (r *ResponseError) String() string { return "" } data, err := json.Marshal(r.Data) - if err != nil { - return fmt.Sprintf("[%d]: %s\n%v", r.Code, r.Message, data) + if err == nil && r.Data != nil { + return fmt.Sprintf("[%d]: %s\n%s", r.Code, r.Message, data) } return fmt.Sprintf("[%d]: %s", r.Code, r.Message) } diff --git a/tsc/internal/lsp/lsproto/jsonrpc_test.go b/tsc/internal/lsp/lsproto/jsonrpc_test.go index 8f8825128433b..63f7b2aa2a320 100644 --- a/tsc/internal/lsp/lsproto/jsonrpc_test.go +++ b/tsc/internal/lsp/lsproto/jsonrpc_test.go @@ -36,6 +36,49 @@ func TestMarshalMessage(t *testing.T) { } } +func TestResponseErrorString(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + err *jsonrpc.ResponseError + want string + }{ + { + name: "JSON details", + err: &jsonrpc.ResponseError{ + Code: jsonrpc.CodeInvalidParams, + Message: "invalid params", + Data: struct { + Details []string `json:"details"` + }{Details: []string{`expected "name"`, "line\nbreak"}}, + }, + want: "[-32602]: invalid params\n" + `{"details":["expected \"name\"","line\nbreak"]}`, + }, + { + name: "nil receiver", + want: "", + }, + { + name: "nil data", + err: &jsonrpc.ResponseError{Code: jsonrpc.CodeInternalError, Message: "failed"}, + want: "[-32603]: failed", + }, + { + name: "unmarshalable data", + err: &jsonrpc.ResponseError{Code: jsonrpc.CodeInternalError, Message: "failed", Data: make(chan int)}, + want: "[-32603]: failed", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + assert.Equal(t, tt.err.String(), tt.want) + assert.Equal(t, tt.err.Error(), tt.want) + }) + } +} + func BenchmarkMarshalCompletionResponse(b *testing.B) { items := make([]*CompletionItem, 2000) for i := range items {