Skip to content

Commit 0ee020f

Browse files
authored
Merge pull request #4 from myleshyson/update-interfaces
Update interfaces
2 parents d25f7e0 + 8c66bae commit 0ee020f

File tree

6 files changed

+483
-235
lines changed

6 files changed

+483
-235
lines changed

README.md

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,49 @@ var request protocol.InitializeRequest
1414

1515
All lsprotocol types are in the `protocol` package.
1616

17-
## TODO
18-
- Currently only types are provided. Would be nice to also provide utility functions for creating a request/response.
19-
- the microsoft tests only test for proper unmarshalling. probably should add tests to make sure structs marshal correctly as well.
20-
- I'm not a golang expert. There may be more efficient ways to do things like validation or tagged unions.
17+
## Utilities
18+
This package provides a limited number of utility functions for dealing with jsonrpc messages.
19+
20+
**DecodeMessage**
21+
This is a helper that takes in a full jsonrpc message and returns a message object.
22+
23+
```golang
24+
var content = []byte("Content-Length: 20\r\n\r\n{...etc}")
25+
message, err := protocol.DecodeMessage(content)
26+
```
27+
28+
**SplitMessage**
29+
This is a helper that takes in a full jsonrpc message and returns information about the message.
30+
31+
```golang
32+
var content = []byte("Content-Length: 20\r\n\r\n{...etc}")
33+
messageLengthIncludingTheHeader, contentLength, content, err := protocol.SplitMessage(content)
34+
```
35+
36+
**Split**
37+
This is a helper you can use with scanner to read jsonrpc messages from a stream.
38+
39+
```golang
40+
var scanner = bufio.NewScanner(reader)
41+
scanner.Split(protocol.Split)
42+
for scanner.Scan() {
43+
msg := scanner.Bytes()
44+
// handle message
45+
}
46+
```
47+
48+
**Error**
49+
This is a tiny helper that takes in an error coe and an `error` instance, and returns a `ResponseError`
50+
51+
```golang
52+
responseError := protocol.Error(someErrorCode, err)
53+
```
54+
55+
## Interfaces
56+
The following interfaces are provided by this package:
57+
58+
- `Request` - represents a jsonrpc request
59+
- `Response` - represents a jsonrpc response
60+
- `Notification` - represents a jsonrpc notification
61+
- `Message` - represents a jsonrpc message
62+
- `IncomingMessage` - notification or request. not in the spec but super helpful.

lspgenerator/go/base_types.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,17 @@ def generate_base_types(
120120
],
121121
),
122122
)
123+
result.append("type MethodKind string")
123124
result.append(
124125
join(
125126
[
126127
"type Message interface {",
127128
" isMessage()",
128129
"}",
130+
"type IncomingMessage interface {",
131+
" GetMethod() MethodKind",
132+
" GetParams() any",
133+
"}",
129134
"type Request interface {",
130135
" isRequest()",
131136
"}",

lspgenerator/go/notifications.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,18 @@ def generate_notifications(
99
type_resolver: TypeResolver,
1010
) -> list[str]:
1111
notifications = sorted(spec.notifications, key=lambda x: x.method)
12-
result = [
13-
"type NotificationMethod string\n",
14-
]
12+
result = []
1513
constants = "const (\n"
16-
constants += '\tUnknownNotificationMethod = ""\n'
14+
constants += '\tUnknownNotificationMethod MethodKind = ""\n'
1715

1816
for notification in notifications:
1917
method = notification.method.replace("$", "Optional")
2018
camel_case_method = method_to_camel_case(method)
21-
constants += f'\t{camel_case_method}Method NotificationMethod = "{notification.method}"\n'
19+
constants += f'\t{camel_case_method}Method MethodKind = "{notification.method}"\n'
2220
constants += ")\n"
2321
result.append(constants)
2422
result.append(
25-
"var NotificationMethodMap = map[string]NotificationMethod{",
23+
"var NotificationMethodMap = map[string]MethodKind{",
2624
)
2725
for notification in notifications:
2826
method = notification.method.replace("$", "Optional")
@@ -42,14 +40,20 @@ def generate_notifications(
4240
lines_to_comments(notification.documentation),
4341
f"type {notification.typeName} struct {{",
4442
'\tJsonRPC string `json:"jsonrpc"`',
45-
'\tMethod string `json:"method"`',
43+
'\tMethod MethodKind `json:"method"`',
4644
f'\tParams {param_type} `json:"params"`',
4745
]
4846
struct.append("}")
4947
struct.append(f"func (t {notification.typeName}) isMessage() {{}}")
5048
struct.append(
5149
f"func (t {notification.typeName}) isNotification() {{}}",
5250
)
51+
struct.append(
52+
f"func (t {notification.typeName}) GetMethod() MethodKind {{ return t.Method }}",
53+
)
54+
struct.append(
55+
f"func (t {notification.typeName}) GetParams() any {{ return t.Params }}",
56+
)
5357
struct += [
5458
f"func (t *{notification.typeName}) UnmarshalJSON(x []byte) error {{",
5559
" var m map[string]any",

lspgenerator/go/requests.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,19 @@ def generate_requests(
1414
) -> list[str]:
1515
requests = sorted(spec.requests, key=lambda x: x.method)
1616

17-
result = [
18-
"type RequestMethod string\n",
19-
]
17+
result = []
2018
constants = "const (\n"
21-
constants += '\tUnknownRequestMethod RequestMethod = ""\n'
19+
constants += '\tUnknownRequestMethod MethodKind = ""\n'
2220

2321
for request in requests:
2422
camel_case_method = method_to_camel_case(request.method)
2523
constants += (
26-
f'\t{camel_case_method}Method RequestMethod = "{request.method}"\n'
24+
f'\t{camel_case_method}Method MethodKind = "{request.method}"\n'
2725
)
2826
constants += ")\n"
2927
result.append(constants)
3028

31-
result.append("var RequestMethodMap = map[string]RequestMethod{")
29+
result.append("var RequestMethodMap = map[string]MethodKind{")
3230
for request in requests:
3331
camel_case_method = method_to_camel_case(request.method)
3432
result.append(
@@ -45,13 +43,19 @@ def generate_requests(
4543
f"type {request.typeName} struct {{",
4644
'\tJsonRPC string `json:"jsonrpc"`',
4745
'\tID Or2[string, int32] `json:"id"`',
48-
'\tMethod RequestMethod `json:"method"`',
46+
'\tMethod MethodKind `json:"method"`',
4947
f'\tParams {param_type} `json:"params"`',
5048
]
5149

5250
struct.append("}")
5351
struct.append(f"func (t {request.typeName}) isMessage() {{}}")
5452
struct.append(f"func (t {request.typeName}) isRequest() {{}}")
53+
struct.append(
54+
f"func (t {request.typeName}) GetMethod() MethodKind {{ return t.Method }}",
55+
)
56+
struct.append(
57+
f"func (t {request.typeName}) GetParams() any {{ return t.Params }}",
58+
)
5559
struct += [
5660
f"func (t *{request.typeName}) UnmarshalJSON(x []byte) error {{",
5761
" var m map[string]any",

protocol/interfaces_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package protocol
22

33
// Compile-time interface compliance checks
44
var (
5-
_ Message = (*InitializeRequest)(nil)
6-
_ Message = (*InitializedNotification)(nil)
7-
_ Message = (*InitializeResponse)(nil)
8-
_ Request = (*InitializeRequest)(nil)
9-
_ Notification = (*InitializedNotification)(nil)
10-
_ Response = (*InitializeResponse)(nil)
5+
_ Message = (*InitializeRequest)(nil)
6+
_ Message = (*InitializedNotification)(nil)
7+
_ Message = (*InitializeResponse)(nil)
8+
_ Request = (*InitializeRequest)(nil)
9+
_ Notification = (*InitializedNotification)(nil)
10+
_ Response = (*InitializeResponse)(nil)
11+
_ IncomingMessage = (*InitializeRequest)(nil)
12+
_ IncomingMessage = (*InitializedNotification)(nil)
1113
)

0 commit comments

Comments
 (0)