Improve error message on misplaced async modifiers
[hiphop-php.git] / hphp / hack / src / utils / lsp.ml
blobc999250bbd6be016ce7854597864cce9fcb19952
1 (**
2 * Copyright (c) 2016, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
8 *)
10 (**
11 * This file is an OCaml representation of the Language Server Protocol
12 * https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md
13 * based on the current v3.
15 * Changes to make it more natural in OCaml:
16 * - We don't represent the common base types of Requests/Errors/Notifications
17 * because base types don't naturally mix with abstract data types, and
18 * because code for these things is done more naturally at the JSON layer
19 * - We avoid option types where we can. The idea is to follow the internet
20 * "robustness" rule of being liberal in what we accept, conservative in
21 * what we emit: if we're parsing a message and it lacks a field, and if
22 * the spec tells us how to interpret absence, then we do that interpretation
23 * at the JSON->LSP parsing level (so long as the interpretation is lossless).
24 * On the emitting side, we might as well emit all fields.
25 * - For every request, like Initialize or workspace/Symbol, we've invented
26 * "Initialize.response = (Initialize.result, Initialize.error) Result"
27 * or "Symbol.response = (Symbol.result, Error.error) Result" to show
28 * the two possible return types from this request. Note that each different
29 * request can have its own custom error type, although most don't.
30 * - Most datatypes go in modules since there are so many name-clashes in
31 * the protocol and OCaml doesn't like name-clashes. Only exceptions are
32 * the really primitive types like location and documentUri.
33 * The few places where we still had to rename fields to avoid OCaml name
34 * clashes I've noted in the comments with the word "wire" to indicate the
35 * over-the-wire form of the name.
36 * - Names have been translated from jsonConvention into ocaml convention
37 * only where necessary, e.g. because ocaml uses lowercase for types.
38 * - The spec has space for extra fields like "experimental". It obviously
39 * doesn't make sense to encode them in a type system. I've omitted them
40 * entirely.
43 type lsp_id =
44 | NumberId of int
45 | StringId of string
47 type documentUri = string
49 (* A position is between two characters like an 'insert' cursor in a editor *)
50 type position = {
51 line: int; (* line position in a document [zero-based] *)
52 character: int; (* character offset on a line in a document [zero-based] *)
55 (* A range is comparable to a selection in an editor *)
56 type range = {
57 start: position; (* the range's start position *)
58 end_: position; (* the range's end position [exclusive] *)
61 (* Represents a location inside a resource, such as a line inside a text file *)
62 module Location = struct
63 type t = {
64 uri: documentUri;
65 range: range;
67 end
69 (* Represents a location inside a resource which also wants to display a
70 friendly name to the user. *)
71 module DefinitionLocation = struct
72 type t = {
73 location: Location.t;
74 title: string option;
76 end
78 (* markedString can be used to render human readable text. It is either a
79 * markdown string or a code-block that provides a language and a code snippet.
80 * Note that markdown strings will be sanitized by the client - including
81 * escaping html *)
82 type markedString =
83 | MarkedString of string
84 | MarkedCode of string * string (* lang, value *)
86 (* Represents a reference to a command. Provides a title which will be used to
87 * represent a command in the UI. Commands are identitifed using a string
88 * identifier and the protocol currently doesn't specify a set of well known
89 * commands. So executing a command requires some tool extension code. *)
90 module Command = struct
91 type t = {
92 title: string; (* title of the command, like `save` *)
93 command: string; (* the identifier of the actual command handler *)
94 arguments: Hh_json.json list; (* wire: it can be omitted *)
96 end
98 (* A textual edit applicable to a text document. If n textEdits are applied
99 to a text document all text edits describe changes to the initial document
100 version. Execution wise text edits should applied from the bottom to the
101 top of the text document. Overlapping text edits are not supported. *)
102 module TextEdit = struct
103 type t = {
104 range: range; (* to insert text, use a range where start = end *)
105 newText: string; (* for delete operations, use an empty string *)
109 (* Text documents are identified using a URI. *)
110 module TextDocumentIdentifier = struct
111 type t = {
112 uri: documentUri; (* the text document's URI *)
116 (* An identifier to denote a specific version of a text document. *)
117 module VersionedTextDocumentIdentifier = struct
118 type t = {
119 uri: documentUri; (* the text document's URI *)
120 version: int; (* the version number of this document *)
124 (* Describes textual changes on a single text document. The text document is
125 referred to as a VersionedTextDocumentIdentifier to allow clients to check
126 the text document version before an edit is applied. *)
127 module TextDocumentEdit = struct
128 type t = {
129 textDocument: VersionedTextDocumentIdentifier.t;
130 edits: TextEdit.t list;
134 (* A workspace edit represents changes to many resources managed in the
135 workspace. A workspace edit consists of a mapping from a URI to an
136 array of TextEdits to be applied to the document with that URI. *)
137 module WorkspaceEdit = struct
138 type t = {
139 changes: TextEdit.t list SMap.t; (* holds changes to existing docs *)
143 (* An item to transfer a text document from the client to the server. The
144 version number strictly increases after each change, including undo/redo. *)
145 module TextDocumentItem = struct
146 type t = {
147 uri: documentUri; (* the text document's URI *)
148 languageId: string; (* the text document's language identifier *)
149 version: int; (* the version of the document *)
150 text: string; (* the content of the opened text document *)
154 (* A parameter literal used in requests to pass a text document and a position
155 inside that document. *)
156 module TextDocumentPositionParams = struct
157 type t = {
158 textDocument: TextDocumentIdentifier.t; (* the text document *)
159 position: position; (* the position inside the text document *)
163 (* A document filter denotes a document through properties like language,
164 schema or pattern. E.g. language:"typescript",scheme:"file"
165 or language:"json",pattern:"**/package.json" *)
166 module DocumentFilter = struct
167 type t = {
168 language: string option; (* a language id, like "typescript" *)
169 scheme: string option; (* a uri scheme, like "file" or "untitled" *)
170 pattern: string option; (* a glob pattern, like "*.{ts,js}" *)
174 (* A document selector is the combination of one or many document filters. *)
175 module DocumentSelector = struct
176 type t = DocumentFilter.t list
180 (* Represents information about programming constructs like variables etc. *)
181 module SymbolInformation = struct
182 type t = {
183 name: string;
184 kind: symbolKind;
185 location: Location.t; (* the span of the symbol including its contents *)
186 containerName: string option; (* the symbol containing this symbol *)
189 and symbolKind =
190 | File (* 1 *)
191 | Module (* 2 *)
192 | Namespace (* 3 *)
193 | Package (* 4 *)
194 | Class (* 5 *)
195 | Method (* 6 *)
196 | Property (* 7 *)
197 | Field (* 8 *)
198 | Constructor (* 9 *)
199 | Enum (* 10 *)
200 | Interface (* 11 *)
201 | Function (* 12 *)
202 | Variable (* 13 *)
203 | Constant (* 14 *)
204 | String (* 15 *)
205 | Number (* 16 *)
206 | Boolean (* 17 *)
207 | Array (* 18 *)
211 (* For showing messages (not diagnostics) in the user interface. *)
212 module MessageType = struct
213 type t =
214 | ErrorMessage (* 1 *)
215 | WarningMessage (* 2 *)
216 | InfoMessage (* 3 *)
217 | LogMessage (* 4 *)
221 (* Cancellation notification, method="$/cancelRequest" *)
222 module CancelRequest = struct
223 type params = cancelParams
225 and cancelParams = {
226 id: lsp_id; (* the request id to cancel *)
230 (* Initialize request, method="initialize" *)
231 module Initialize = struct
232 type params = {
233 processId: int option; (* pid of parent process *)
234 rootPath: string option; (* deprecated *)
235 rootUri: documentUri option; (* the root URI of the workspace *)
236 initializationOptions: initializationOptions;
237 client_capabilities: client_capabilities; (* "capabilities" over wire *)
238 trace: trace; (* the initial trace setting, default="off" *)
241 and result = {
242 server_capabilities: server_capabilities; (* "capabilities" over wire *)
245 and errorData = {
246 retry: bool; (* should client retry the initialize request *)
249 and trace =
250 | Off
251 | Messages
252 | Verbose
254 (* Following initialization options are unfortunately a mix of Hack
255 * and Flow. We should find a way to separate them.
256 * Anyway, they're all optional in the source json, but we pick
257 * a default if necessary while parsing. *)
258 and initializationOptions = {
259 useTextEditAutocomplete: bool; (* only supported for Hack so far *)
260 liveSyntaxErrors: bool; (* implicitly true for Hack; supported in Flow *)
263 and client_capabilities = {
264 workspace: workspaceClientCapabilities;
265 textDocument: textDocumentClientCapabilities;
266 window: windowClientCapabilities;
267 telemetry: telemetryClientCapabilities;
268 (* omitted: experimental *)
271 and workspaceClientCapabilities = {
272 applyEdit: bool; (* client supports appling batch edits *)
273 workspaceEdit: workspaceEdit;
275 didChangeWatchedFiles: dynamicRegistration;
276 (* omitted: other dynamic-registration fields *)
279 and dynamicRegistration = {
280 dynamicRegistration: bool; (* client supports dynamic registration for this capability *)
283 and workspaceEdit = {
284 documentChanges: bool; (* client supports versioned doc changes *)
287 and textDocumentClientCapabilities = {
288 synchronization: synchronization;
289 completion: completion; (* textDocument/completion *)
290 (* omitted: dynamic-registration fields *)
293 (* synchronization capabilities say what messages the client is capable
294 * of sending, should be be so asked by the server.
295 * We use the "can_" prefix for OCaml naming reasons; it's absent in LSP *)
296 and synchronization = {
297 can_willSave: bool; (* client can send textDocument/willSave *)
298 can_willSaveWaitUntil: bool; (* textDoc.../willSaveWaitUntil *)
299 can_didSave: bool; (* textDocument/didSave *)
302 and completion = {
303 completionItem: completionItem;
306 and completionItem = {
307 snippetSupport: bool; (* client can do snippets as insert text *)
310 and windowClientCapabilities = {
311 status: bool; (* Nuclide-specific: client supports window/showStatusRequest *)
312 progress: bool; (* Nuclide-specific: client supports window/progress *)
313 actionRequired: bool; (* Nuclide-specific: client supports window/actionRequired *)
316 and telemetryClientCapabilities = {
317 connectionStatus: bool; (* Nuclide-specific: client supports telemetry/connectionStatus *)
320 (* What capabilities the server provides *)
321 and server_capabilities = {
322 textDocumentSync: textDocumentSyncOptions; (* how to sync *)
323 hoverProvider: bool;
324 completionProvider: completionOptions option;
325 signatureHelpProvider: signatureHelpOptions option;
326 definitionProvider: bool;
327 typeDefinitionProvider: bool;
328 referencesProvider: bool;
329 documentHighlightProvider: bool;
330 documentSymbolProvider: bool; (* ie. document outline *)
331 workspaceSymbolProvider: bool; (* ie. find-symbol-in-project *)
332 codeActionProvider: bool;
333 codeLensProvider: codeLensOptions option;
334 documentFormattingProvider: bool;
335 documentRangeFormattingProvider: bool;
336 documentOnTypeFormattingProvider: documentOnTypeFormattingOptions option;
337 renameProvider: bool;
338 documentLinkProvider: documentLinkOptions option;
339 executeCommandProvider: executeCommandOptions option;
340 typeCoverageProvider: bool; (* Nuclide-specific feature *)
341 rageProvider: bool;
342 (* omitted: experimental *)
345 and completionOptions = {
346 resolveProvider: bool; (* server resolves extra info on demand *)
347 completion_triggerCharacters: string list; (* wire "triggerCharacters" *)
350 and signatureHelpOptions = {
351 sighelp_triggerCharacters: string list; (* wire "triggerCharacters" *)
354 and codeLensOptions = {
355 codelens_resolveProvider: bool; (* wire "resolveProvider" *)
358 and documentOnTypeFormattingOptions = {
359 firstTriggerCharacter: string; (* e.g. "}" *)
360 moreTriggerCharacter: string list;
363 and documentLinkOptions = {
364 doclink_resolveProvider: bool; (* wire "resolveProvider" *)
367 and executeCommandOptions = {
368 commands: string list; (* the commands to be executed on the server *)
371 (* text document sync options say what messages the server requests the
372 * client to send. We use the "want_" prefix for OCaml naming reasons;
373 * this prefix is absent in LSP. *)
374 and textDocumentSyncOptions = {
375 want_openClose: bool; (* textDocument/didOpen+didClose *)
376 want_change: textDocumentSyncKind;
377 want_willSave: bool; (* textDocument/willSave *)
378 want_willSaveWaitUntil: bool; (* textDoc.../willSaveWaitUntil *)
379 want_didSave: saveOptions option; (* textDocument/didSave *)
382 and textDocumentSyncKind =
383 | NoSync (* 0 *) (* docs should not be synced at all. Wire "None" *)
384 | FullSync (* 1 *) (* synced by always sending full content. Wire "Full" *)
385 | IncrementalSync (* 2 *) (* full only on open. Wire "Incremental" *)
387 and saveOptions = {
388 includeText: bool; (* the client should include content on save *)
392 (* Shutdown request, method="shutdown" *)
393 module Shutdown = struct
396 (* Exit notification, method="exit" *)
397 module Exit = struct
400 (* Rage request, method="telemetry/rage" *)
401 module Rage = struct
402 type result = rageItem list
404 and rageItem = {
405 title: string option;
406 data: string;
411 (* Hover request, method="textDocument/hover" *)
412 module Hover = struct
413 type params = TextDocumentPositionParams.t
415 and result = hoverResult option
417 and hoverResult = {
418 contents: markedString list; (* wire: either a single one or an array *)
419 range: range option;
423 (* PublishDiagnostics notification, method="textDocument/PublishDiagnostics" *)
424 module PublishDiagnostics = struct
425 type params = publishDiagnosticsParams
427 and publishDiagnosticsParams = {
428 uri: documentUri;
429 diagnostics: diagnostic list;
432 and diagnostic = {
433 range: range; (* the range at which the message applies *)
434 severity: diagnosticSeverity option; (* if omitted, client decides *)
435 code: diagnosticCode; (* the diagnostic's code. *)
436 source: string option; (* human-readable string, eg. typescript/lint *)
437 message: string; (* the diagnostic's message *)
438 relatedInformation: diagnosticRelatedInformation list;
439 relatedLocations: relatedLocation list; (* legacy FB extension *)
442 and diagnosticCode =
443 | IntCode of int
444 | StringCode of string
445 | NoCode
447 and diagnosticSeverity =
448 | Error (* 1 *)
449 | Warning (* 2 *)
450 | Information (* 3 *)
451 | Hint (* 4 *)
453 and diagnosticRelatedInformation = {
454 relatedLocation: Location.t; (* wire: just "location" *)
455 relatedMessage: string; (* wire: just "message" *)
458 (* legacy FB extension *)
459 and relatedLocation = diagnosticRelatedInformation
462 (* DidOpenTextDocument notification, method="textDocument/didOpen" *)
463 module DidOpen = struct
464 type params = didOpenTextDocumentParams
466 and didOpenTextDocumentParams = {
467 textDocument: TextDocumentItem.t; (* the document that was opened *)
471 (* DidCloseTextDocument notification, method="textDocument/didClose" *)
472 module DidClose = struct
473 type params = didCloseTextDocumentParams
475 and didCloseTextDocumentParams = {
476 textDocument: TextDocumentIdentifier.t; (* the doc that was closed *)
480 (* DidSaveTextDocument notification, method="textDocument/didSave" *)
481 module DidSave = struct
482 type params = didSaveTextDocumentParams
484 and didSaveTextDocumentParams = {
485 textDocument: TextDocumentIdentifier.t; (* the doc that was saved *)
486 text: string option; (* content when saved; depends on includeText *)
490 (* DidChangeTextDocument notification, method="textDocument/didChange" *)
491 module DidChange = struct
492 type params = didChangeTextDocumentParams
494 and didChangeTextDocumentParams = {
495 textDocument: VersionedTextDocumentIdentifier.t;
496 contentChanges: textDocumentContentChangeEvent list;
499 and textDocumentContentChangeEvent = {
500 range: range option; (* the range of the document that changed *)
501 rangeLength: int option; (* the length that got replaced *)
502 text: string; (* the new text of the range/document *)
506 (* Watched files changed notification, method="workspace/didChangeWatchedFiles" *)
507 module DidChangeWatchedFiles = struct
508 type registerOptions = {
509 watchers: fileSystemWatcher list;
512 and fileSystemWatcher = {
513 globPattern: string;
516 type fileChangeType =
517 | Created [@value 1]
518 | Updated [@value 2]
519 | Deleted [@value 3]
520 [@@deriving enum]
522 type params = {
523 changes: fileEvent list;
526 and fileEvent = {
527 uri: documentUri;
528 type_: fileChangeType;
532 (* Goto Definition request, method="textDocument/definition" *)
533 module Definition = struct
534 type params = TextDocumentPositionParams.t
536 and result = DefinitionLocation.t list (* wire: either a single one or an array *)
539 (* Goto TypeDefinition request, method="textDocument/typeDefinition" *)
540 module TypeDefinition = struct
541 type params = TextDocumentPositionParams.t
543 and result = DefinitionLocation.t list
546 (* Completion request, method="textDocument/completion" *)
547 module Completion = struct
548 type params = completionParams
550 and completionParams = {
551 loc: TextDocumentPositionParams.t;
552 context: completionContext option;
555 and completionContext = {
556 triggerKind: completionTriggerKind;
559 and completionTriggerKind =
560 | Invoked (* 1 *)
561 | TriggerCharacter (* 2 *)
562 | TriggerForIncompleteCompletions (* 3 *)
564 and result = completionList (* wire: can also be 'completionItem list' *)
566 and completionList = {
567 isIncomplete: bool; (* further typing should result in recomputing *)
568 items: completionItem list;
571 and completionItem = {
572 label: string; (* the label in the UI *)
573 kind: completionItemKind option; (* tells editor which icon to use *)
574 detail: string option; (* human-readable string like type/symbol info *)
575 inlineDetail: string option; (* nuclide-specific, right column *)
576 itemType: string option; (* nuclide-specific, left column *)
577 documentation: string option; (* human-readable doc-comment *)
578 sortText: string option; (* used for sorting; if absent, uses label *)
579 filterText: string option; (* used for filtering; if absent, uses label *)
580 insertText: string option; (* used for inserting; if absent, uses label *)
581 insertTextFormat: insertTextFormat option;
582 textEdits: TextEdit.t list; (* wire: split into hd and tl *)
583 command: Command.t option; (* if present, is executed after completion *)
584 data: Hh_json.json option;
587 and completionItemKind =
588 | Text (* 1 *)
589 | Method (* 2 *)
590 | Function (* 3 *)
591 | Constructor (* 4 *)
592 | Field (* 5 *)
593 | Variable (* 6 *)
594 | Class (* 7 *)
595 | Interface (* 8 *)
596 | Module (* 9 *)
597 | Property (* 10 *)
598 | Unit (* 11 *)
599 | Value (* 12 *)
600 | Enum (* 13 *)
601 | Keyword (* 14 *)
602 | Snippet (* 15 *)
603 | Color (* 16 *)
604 | File (* 17 *)
605 | Reference (* 18 *)
606 | Folder (* 19 *)
607 | EnumMember (* 20 *)
608 | Constant (* 21 *)
609 | Struct (* 22 *)
610 | Event (* 23 *)
611 | Operator (* 24 *)
612 | TypeParameter (* 25 *)
614 (** Keep this in sync with `int_of_completionItemKind`. *)
615 and insertTextFormat =
616 | PlainText (* 1 *) (* the insertText/textEdits are just plain strings *)
617 | SnippetFormat (* 2 *) (* wire: just "Snippet" *)
619 (** Once we get better PPX support we can use [@@deriving enum].
620 Keep in sync with completionItemKind_of_int_opt. *)
621 let int_of_completionItemKind = function
622 | Text -> 1
623 | Method -> 2
624 | Function -> 3
625 | Constructor -> 4
626 | Field -> 5
627 | Variable -> 6
628 | Class -> 7
629 | Interface -> 8
630 | Module -> 9
631 | Property -> 10
632 | Unit -> 11
633 | Value -> 12
634 | Enum -> 13
635 | Keyword -> 14
636 | Snippet -> 15
637 | Color -> 16
638 | File -> 17
639 | Reference -> 18
640 | Folder -> 19
641 | EnumMember -> 20
642 | Constant -> 21
643 | Struct -> 22
644 | Event -> 23
645 | Operator -> 24
646 | TypeParameter -> 25
648 (** Once we get better PPX support we can use [@@deriving enum].
649 Keep in sync with int_of_completionItemKind. *)
650 let completionItemKind_of_int_opt = function
651 | 1 -> Some Text
652 | 2 -> Some Method
653 | 3 -> Some Function
654 | 4 -> Some Constructor
655 | 5 -> Some Field
656 | 6 -> Some Variable
657 | 7 -> Some Class
658 | 8 -> Some Interface
659 | 9 -> Some Module
660 | 10 -> Some Property
661 | 11 -> Some Unit
662 | 12 -> Some Value
663 | 13 -> Some Enum
664 | 14 -> Some Keyword
665 | 15 -> Some Snippet
666 | 16 -> Some Color
667 | 17 -> Some File
668 | 18 -> Some Reference
669 | 19 -> Some Folder
670 | 20 -> Some EnumMember
671 | 21 -> Some Constant
672 | 22 -> Some Struct
673 | 23 -> Some Event
674 | 24 -> Some Operator
675 | 25 -> Some TypeParameter
676 | _ -> None
678 (** Once we get better PPX support we can use [@@deriving enum].
679 Keep in sync with insertFormat_of_int_opt. *)
680 let int_of_insertFormat = function
681 | PlainText -> 1
682 | SnippetFormat -> 2
684 (** Once we get better PPX support we can use [@@deriving enum].
685 Keep in sync with int_of_insertFormat. *)
686 let insertFormat_of_int_opt = function
687 | 1 -> Some PlainText
688 | 2 -> Some SnippetFormat
689 | _ -> None
693 (* Completion Item Resolve request, method="completionItem/resolve" *)
694 module CompletionItemResolve = struct
695 type params = Completion.completionItem
697 and result = Completion.completionItem
701 (* Workspace Symbols request, method="workspace/symbol" *)
702 module WorkspaceSymbol = struct
703 type params = workspaceSymbolParams
705 and result = SymbolInformation.t list
707 and workspaceSymbolParams = {
708 query: string; (* a non-empty query string *)
713 (* Document Symbols request, method="textDocument/documentSymbols" *)
714 module DocumentSymbol = struct
715 type params = documentSymbolParams
717 and result = SymbolInformation.t list
719 and documentSymbolParams = {
720 textDocument: TextDocumentIdentifier.t;
725 (* Find References request, method="textDocument/references" *)
726 module FindReferences = struct
727 type params = referenceParams
729 and result = Location.t list
731 and referenceParams = {
732 loc: TextDocumentPositionParams.t; (* wire: loc's members are part of referenceParams *)
733 context: referenceContext;
736 and referenceContext = {
737 includeDeclaration: bool; (* include declaration of current symbol *)
738 includeIndirectReferences: bool;
743 (* Document Highlights request, method="textDocument/documentHighlight" *)
744 module DocumentHighlight = struct
745 type params = TextDocumentPositionParams.t
747 and result = documentHighlight list
749 and documentHighlight = {
750 range: range; (* the range this highlight applies to *)
751 kind: documentHighlightKind option;
754 and documentHighlightKind =
755 | Text (* 1 *) (* a textual occurrence *)
756 | Read (* 2 *) (* read-access of a symbol, like reading a variable *)
757 | Write (* 3 *) (* write-access of a symbol, like writing a variable *)
761 (* Type Coverage request, method="textDocument/typeCoverage" *)
762 (* THIS IS A NUCLIDE-SPECIFIC EXTENSION TO LSP. *)
763 module TypeCoverage = struct
764 type params = typeCoverageParams
766 and result = {
767 coveredPercent: int;
768 uncoveredRanges: uncoveredRange list;
769 defaultMessage: string;
772 and typeCoverageParams = {
773 textDocument: TextDocumentIdentifier.t;
776 and uncoveredRange = {
777 range: range;
778 message: string option;
783 (* Document Formatting request, method="textDocument/formatting" *)
784 module DocumentFormatting = struct
785 type params = documentFormattingParams
787 and result = TextEdit.t list
789 and documentFormattingParams = {
790 textDocument: TextDocumentIdentifier.t;
791 options: formattingOptions;
794 and formattingOptions = {
795 tabSize: int; (* size of a tab in spaces *)
796 insertSpaces: bool; (* prefer spaces over tabs *)
797 (* omitted: signature for further properties *)
802 (* Document Range Formatting request, method="textDocument/rangeFormatting" *)
803 module DocumentRangeFormatting = struct
804 type params = documentRangeFormattingParams
806 and result = TextEdit.t list
808 and documentRangeFormattingParams = {
809 textDocument: TextDocumentIdentifier.t;
810 range: range;
811 options: DocumentFormatting.formattingOptions;
816 (* Document On Type Formatting req., method="textDocument/onTypeFormatting" *)
817 module DocumentOnTypeFormatting = struct
818 type params = documentOnTypeFormattingParams
820 and result = TextEdit.t list
822 and documentOnTypeFormattingParams = {
823 textDocument: TextDocumentIdentifier.t;
824 position: position; (* the position at which this request was sent *)
825 ch: string; (* the character that has been typed *)
826 options: DocumentFormatting.formattingOptions;
831 (* Document Signature Help request, method="textDocument/signatureHelp" *)
832 module SignatureHelp = struct
833 type params = TextDocumentPositionParams.t
835 and result = t option
837 and t = {
838 signatures: signature_information list;
839 activeSignature: int;
840 activeParameter: int;
843 and signature_information = {
844 siginfo_label: string;
845 siginfo_documentation: string option;
846 parameters: parameter_information list;
849 and parameter_information = {
850 parinfo_label: string;
851 parinfo_documentation: string option;
855 (* Workspace Rename request, method="textDocument/rename" *)
856 module Rename = struct
857 type params = renameParams
859 and result = WorkspaceEdit.t
861 and renameParams = {
862 textDocument: TextDocumentIdentifier.t;
863 position: position;
864 newName: string;
869 (* LogMessage notification, method="window/logMessage" *)
870 module LogMessage = struct
871 type params = logMessageParams
873 and logMessageParams = {
874 type_: MessageType.t;
875 message: string;
880 (* ShowMessage notification, method="window/showMessage" *)
881 module ShowMessage = struct
882 type params = showMessageParams
884 and showMessageParams = {
885 type_: MessageType.t;
886 message: string;
891 (* ShowMessage request, method="window/showMessageRequest" *)
892 module ShowMessageRequest = struct
893 type t = Present of {id: lsp_id;} | Absent
895 and params = showMessageRequestParams
897 and result = messageActionItem option
899 and showMessageRequestParams = {
900 type_: MessageType.t;
901 message: string;
902 actions: messageActionItem list;
905 and messageActionItem = {
906 title: string;
911 (* ShowStatus request, method="window/showStatus" *)
912 module ShowStatus = struct
913 type params = showStatusParams
915 and result = ShowMessageRequest.messageActionItem option
917 and showStatusParams = {
918 request: ShowMessageRequest.showMessageRequestParams;
919 progress: int option;
920 total: int option;
921 shortMessage: string option;
926 (* Progress notification, method="window/progress" *)
927 module Progress = struct
928 type t = Present of {id: int; label: string;} | Absent
930 and params = progressParams
932 and progressParams = {
933 (* LSP progress notifications have a lifetime that starts with their 1st *)
934 (* window/progress update message and ends with an update message with *)
935 (* label = None. They use an ID number (not JsonRPC id) to associate *)
936 (* multiple messages to a single lifetime stream. *)
937 id: int;
938 label: string option;
943 (* ActionRequired notification, method="window/actionRequired" *)
944 module ActionRequired = struct
945 type t = Present of {id: int; label: string;} | Absent
947 and params = actionRequiredParams
949 and actionRequiredParams = {
950 (* See progressParams.id for an explanation of this field. *)
951 id: int;
952 label: string option;
957 (* ConnectionStatus notification, method="telemetry/connectionStatus" *)
958 module ConnectionStatus = struct
959 type params = connectionStatusParams
961 and connectionStatusParams = {
962 isConnected: bool;
967 (* Module for dynamic view, method="workspace/toggleTypeCoverage" *)
968 module ToggleTypeCoverage = struct
969 type params = toggleTypeCoverageParams
970 and toggleTypeCoverageParams = {
971 toggle: bool;
975 (* ErrorResponse *)
976 module Error = struct
977 type t = {code: int; message: string; data: Hh_json.json option}
979 (* Legacy: some code uses exceptions instead of Error.t. *)
980 (* Be careful with that since if you unmarshal one then you can't pattern-match it. *)
982 (* Defined by JSON-RPC. *)
983 exception Parse of string (* -32700 *)
984 exception InvalidRequest of string (* -32600 *)
985 exception MethodNotFound of string (* -32601 *)
986 exception InvalidParams of string (* -32602 *)
987 exception InternalError of string (* -32603 *)
988 exception ServerErrorStart of string * Initialize.errorData (* -32099 *)
989 exception ServerErrorEnd of string (* -32000 *)
990 exception ServerNotInitialized of string (* -32002 *)
991 exception Unknown of string (* -32001 *)
993 (* Defined by the protocol. *)
994 exception RequestCancelled of string (* -32800 *)
996 module Code = struct
997 (* Defined by JSON RPC *)
998 let parseError = -32700
999 let invalidRequest = -32600
1000 let methodNotFound = -32601
1001 let invalidParams = -32602
1002 let internalError = -32603
1003 let serverErrorStart = -32099
1004 let serverErrorEnd = -32000
1005 let serverNotInitialized = -32002
1006 let unknownErrorCode = -32001
1008 (* Defined by the protocol. *)
1009 let requestCancelled = -32800
1010 let contentModified = -32801
1014 type lsp_registration_options =
1015 | DidChangeWatchedFilesRegistrationOptions of
1016 DidChangeWatchedFiles.registerOptions
1018 (* Register capability request, method="client/registerCapability" *)
1019 module RegisterCapability = struct
1020 type params = {
1021 registrations: registration list;
1024 and registration = {
1025 id: string;
1026 method_: string;
1027 registerOptions: lsp_registration_options;
1030 let make_registration
1031 (registerOptions: lsp_registration_options)
1032 : registration =
1033 (* The ID field is arbitrary but unique per type of capability (for future
1034 deregistering, which we don't do). *)
1035 let (id, method_) =
1036 match registerOptions with
1037 | DidChangeWatchedFilesRegistrationOptions _ ->
1038 ("did-change-watched-files", "workspace/didChangeWatchedFiles")
1040 { id; method_; registerOptions }
1045 * Here are gathered-up ADTs for all the messages we handle
1048 type lsp_request =
1049 | InitializeRequest of Initialize.params
1050 | RegisterCapabilityRequest of RegisterCapability.params
1051 | ShutdownRequest
1052 | HoverRequest of Hover.params
1053 | DefinitionRequest of Definition.params
1054 | TypeDefinitionRequest of TypeDefinition.params
1055 | CompletionRequest of Completion.params
1056 | CompletionItemResolveRequest of CompletionItemResolve.params
1057 | WorkspaceSymbolRequest of WorkspaceSymbol.params
1058 | DocumentSymbolRequest of DocumentSymbol.params
1059 | FindReferencesRequest of FindReferences.params
1060 | DocumentHighlightRequest of DocumentHighlight.params
1061 | TypeCoverageRequest of TypeCoverage.params
1062 | DocumentFormattingRequest of DocumentFormatting.params
1063 | DocumentRangeFormattingRequest of DocumentRangeFormatting.params
1064 | DocumentOnTypeFormattingRequest of DocumentOnTypeFormatting.params
1065 | ShowMessageRequestRequest of ShowMessageRequest.params
1066 | ShowStatusRequest of ShowStatus.params
1067 | RageRequest
1068 | RenameRequest of Rename.params
1069 | UnknownRequest of string * Hh_json.json option
1071 type lsp_result =
1072 | InitializeResult of Initialize.result
1073 | ShutdownResult
1074 | HoverResult of Hover.result
1075 | DefinitionResult of Definition.result
1076 | TypeDefinitionResult of TypeDefinition.result
1077 | CompletionResult of Completion.result
1078 | CompletionItemResolveResult of CompletionItemResolve.result
1079 | WorkspaceSymbolResult of WorkspaceSymbol.result
1080 | DocumentSymbolResult of DocumentSymbol.result
1081 | FindReferencesResult of FindReferences.result
1082 | DocumentHighlightResult of DocumentHighlight.result
1083 | TypeCoverageResult of TypeCoverage.result
1084 | DocumentFormattingResult of DocumentFormatting.result
1085 | DocumentRangeFormattingResult of DocumentRangeFormatting.result
1086 | DocumentOnTypeFormattingResult of DocumentOnTypeFormatting.result
1087 | ShowMessageRequestResult of ShowMessageRequest.result
1088 | ShowStatusResult of ShowStatus.result
1089 | RageResult of Rage.result
1090 | RenameResult of Rename.result
1091 | ErrorResult of Error.t * string (* the string is a stacktrace *)
1093 type lsp_notification =
1094 | ExitNotification
1095 | CancelRequestNotification of CancelRequest.params
1096 | PublishDiagnosticsNotification of PublishDiagnostics.params
1097 | DidOpenNotification of DidOpen.params
1098 | DidCloseNotification of DidClose.params
1099 | DidSaveNotification of DidSave.params
1100 | DidChangeNotification of DidChange.params
1101 | DidChangeWatchedFilesNotification of DidChangeWatchedFiles.params
1102 | LogMessageNotification of LogMessage.params
1103 | TelemetryNotification of LogMessage.params (* LSP allows 'any' but we only send these *)
1104 | ShowMessageNotification of ShowMessage.params
1105 | ProgressNotification of Progress.params
1106 | ActionRequiredNotification of ActionRequired.params
1107 | ConnectionStatusNotification of ConnectionStatus.params
1108 | InitializedNotification
1109 | SetTraceNotification (* $/setTraceNotification *)
1110 | LogTraceNotification (* $/logTraceNotification *)
1111 | UnknownNotification of string * Hh_json.json option
1113 type lsp_message =
1114 | RequestMessage of lsp_id * lsp_request
1115 | ResponseMessage of lsp_id * lsp_result
1116 | NotificationMessage of lsp_notification
1118 type 'a lsp_handler = 'a lsp_result_handler * 'a lsp_error_handler
1120 and 'a lsp_error_handler = (Error.t * string) -> 'a -> 'a
1122 and 'a lsp_result_handler =
1123 | ShowMessageHandler of (ShowMessageRequest.result -> 'a -> 'a)
1124 | ShowStatusHandler of (ShowStatus.result -> 'a -> 'a)
1126 module IdKey = struct
1127 type t = lsp_id
1129 let compare (x: t) (y:t) =
1130 match x, y with
1131 | NumberId x, NumberId y -> x - y
1132 | NumberId _, StringId _ -> -1
1133 | StringId x, StringId y -> String.compare x y
1134 | StringId _, NumberId _ -> 1
1137 module IdSet = Set.Make (IdKey)
1138 module IdMap = MyMap.Make (IdKey)