1// Copyright 2018 The Go Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package protocol
16
17import (
18	"context"
19	"encoding/json"
20	"log"
21
22	"../jsonrpc2"
23)
24
25const (
26	// RequestCancelledError should be used when a request is cancelled early.
27	RequestCancelledError = -32800
28)
29
30type DocumentUri = string
31
32type canceller struct{ jsonrpc2.EmptyHandler }
33
34type clientHandler struct {
35	canceller
36	client Client
37}
38
39type serverHandler struct {
40	canceller
41	server Server
42}
43
44func (canceller) Request(ctx context.Context, conn *jsonrpc2.Conn, direction jsonrpc2.Direction, r *jsonrpc2.WireRequest) context.Context {
45	if direction == jsonrpc2.Receive && r.Method == "$/cancelRequest" {
46		var params CancelParams
47		if err := json.Unmarshal(*r.Params, &params); err != nil {
48			log.Printf("%v", err)
49		} else {
50			conn.Cancel(params.ID)
51		}
52	}
53	return ctx
54}
55
56func (canceller) Cancel(ctx context.Context, conn *jsonrpc2.Conn, id jsonrpc2.ID, cancelled bool) bool {
57	if cancelled {
58		return false
59	}
60	conn.Notify(ctx, "$/cancelRequest", &CancelParams{ID: id})
61	return true
62}
63
64func NewClient(ctx context.Context, stream jsonrpc2.Stream, client Client) (context.Context, *jsonrpc2.Conn, Server) {
65	ctx = WithClient(ctx, client)
66	conn := jsonrpc2.NewConn(stream)
67	conn.AddHandler(&clientHandler{client: client})
68	return ctx, conn, &serverDispatcher{Conn: conn}
69}
70
71func NewServer(ctx context.Context, stream jsonrpc2.Stream, server Server) (context.Context, *jsonrpc2.Conn, Client) {
72	conn := jsonrpc2.NewConn(stream)
73	client := &clientDispatcher{Conn: conn}
74	ctx = WithClient(ctx, client)
75	conn.AddHandler(&serverHandler{server: server})
76	return ctx, conn, client
77}
78
79func sendParseError(ctx context.Context, req *jsonrpc2.Request, err error) {
80	if _, ok := err.(*jsonrpc2.Error); !ok {
81		err = jsonrpc2.NewErrorf(jsonrpc2.CodeParseError, "%v", err)
82	}
83	if err := req.Reply(ctx, nil, err); err != nil {
84		log.Printf("%v", err)
85	}
86}
87