-
-
Notifications
You must be signed in to change notification settings - Fork 24
/
methods.rkt
181 lines (167 loc) · 6.37 KB
/
methods.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#lang racket/base
(require json
racket/contract/base
racket/exn
racket/match
"error-codes.rkt"
"msg-io.rkt"
"responses.rkt"
"struct.rkt"
(prefix-in text-document/ "text-document.rkt"))
;; TextDocumentSynKind enumeration
(define TextDocSync-None 0)
(define TextDocSync-Full 1)
(define TextDocSync-Incremental 2)
;; Mutable variables
(define already-initialized? #f)
(define already-shutdown? #f)
;;
;; Dispatch
;;;;;;;;;;;;;
;; Processes a message. This displays any repsonse it generates
;; and should always return void.
(define (process-message msg)
(match msg
;; Request
[(hash-table ['id (? (or/c number? string?) id)]
['method (? string? method)])
(define params (hash-ref msg 'params hasheq))
(define response (process-request id method params))
;; the result can be a response or a procedure which returns
;; a response. If it's a procedure, then it's expected to run
;; concurrently.
(thread (λ ()
(display-message/flush
(if (procedure? response)
(response)
response))))
(void)]
;; Notification
[(hash-table ['method (? string? method)])
(define params (hash-ref msg 'params hasheq))
(process-notification method params)]
;; Batch Request
[(? (non-empty-listof (and/c hash? jsexpr?)))
(for-each process-message msg)]
;; Invalid Message
[_
(define id-ref (hash-ref msg 'id void))
(define id (if ((or/c number? string?) id-ref) id-ref (json-null)))
(define err "The JSON sent is not a valid request object.")
(display-message/flush (error-response id INVALID-REQUEST err))]))
(define ((report-request-error id method) exn)
(eprintf "Caught exn in request ~v\n~a\n" method (exn->string exn))
(define err (format "internal error in method ~v" method))
(error-response id INTERNAL-ERROR err))
;; Processes a request. This procedure should always return a jsexpr
;; which is a suitable response object.
;; (-> (or/c integer? string?) string? jsexpr? jsexpr?)
(define (process-request id method params)
(with-handlers ([exn:fail? (report-request-error id method)])
(match method
["initialize"
(initialize id params)]
["shutdown"
(shutdown id)]
["textDocument/hover"
(text-document/hover id params)]
["textDocument/codeAction"
(text-document/code-action id params)]
["textDocument/completion"
(text-document/completion id params)]
["textDocument/signatureHelp"
(text-document/signatureHelp id params)]
["textDocument/definition"
(text-document/definition id params)]
["textDocument/documentHighlight"
(text-document/document-highlight id params)]
["textDocument/references"
(text-document/references id params)]
["textDocument/documentSymbol"
(text-document/document-symbol id params)]
["textDocument/inlayHint"
(text-document/inlay-hint id params)]
["textDocument/rename"
(text-document/rename id params)]
["textDocument/prepareRename"
(text-document/prepareRename id params)]
["textDocument/formatting"
(text-document/formatting! id params)]
["textDocument/rangeFormatting"
(text-document/range-formatting! id params)]
["textDocument/onTypeFormatting"
(text-document/on-type-formatting! id params)]
["textDocument/semanticTokens/full"
(text-document/full-semantic-tokens id params)]
["textDocument/semanticTokens/range"
(text-document/range-semantic-tokens id params)]
[_
(eprintf "invalid request for method ~v\n" method)
(define err (format "The method ~v was not found" method))
(error-response id METHOD-NOT-FOUND err)])))
;; Processes a notification. Because notifications do not require
;; a response, this procedure always returns void.
(define (process-notification method params)
(match method
["exit"
(exit (if already-shutdown? 0 1))]
["textDocument/didOpen"
(text-document/did-open! params)]
["textDocument/didClose"
(text-document/did-close! params)]
["textDocument/didChange"
(text-document/did-change! params)]
[_ (void)]))
;;
;; Requests
;;;;;;;;;;;;;
(define (initialize id params)
(match params
[(hash-table ['processId (? (or/c number? (json-null)) process-id)]
['capabilities (? jsexpr? capabilities)])
(define sync-options
(hasheq 'openClose #t
'change TextDocSync-Incremental
'willSave #f
'willSaveWaitUntil #f))
(define renameProvider
(match capabilities
[(hash-table ['textDocument
(hash-table ['rename
(hash-table ['prepareSupport #t])])])
(hasheq 'prepareProvider #t)]
[_ #t]))
(define semantic-provider
(hasheq 'legend (hasheq 'tokenTypes (map symbol->string *semantic-token-types*)
'tokenModifiers (map symbol->string *semantic-token-modifiers*))
'full #t
'range #t))
(define server-capabilities
(hasheq 'textDocumentSync sync-options
'hoverProvider #t
'codeActionProvider #t
'definitionProvider #t
'referencesProvider #t
'completionProvider (hasheq 'triggerCharacters (list "("))
'signatureHelpProvider (hasheq 'triggerCharacters (list " " ")" "]"))
'inlayHintProvider #t
'renameProvider renameProvider
'semanticTokensProvider semantic-provider
'documentHighlightProvider #t
'documentSymbolProvider #t
'documentFormattingProvider #t
'documentRangeFormattingProvider #t
'documentOnTypeFormattingProvider (hasheq 'firstTriggerCharacter ")" 'moreTriggerCharacter (list "\n" "]"))))
(define resp (success-response id (hasheq 'capabilities server-capabilities)))
(set! already-initialized? #t)
resp]
[_
(error-response id INVALID-PARAMS "initialize failed")]))
(define (shutdown id)
(set! already-shutdown? #t)
(success-response id (json-null)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(provide
(contract-out
[process-message
(jsexpr? . -> . void?)]))