use rpc instead of notify
[hiphop-php.git] / hphp / hack / src / client / ide_service / clientIdeMessage.ml
blob85bdc72ae919ae309d94bb3dc425a1b9532d39e8
1 (*
2 * Copyright (c) 2019, 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 open Hh_prelude
12 module Initialize_from_saved_state = struct
13 type t = {
14 root: Path.t;
15 naming_table_saved_state_path: Path.t option;
16 use_ranked_autocomplete: bool;
17 config: (string * string) list;
18 open_files: Path.t list;
21 type result = { num_changed_files_to_process: int }
22 end
24 type document_location = {
25 file_path: Path.t;
26 file_contents: string option;
27 (* if absent, should read from file on disk *)
28 line: int;
29 column: int;
32 type document_and_path = {
33 file_path: Path.t;
34 file_contents: string;
37 (** Denotes a location of the cursor in a document at which an IDE request is
38 being executed (e.g. hover). *)
40 module Ide_file_opened = struct
41 type request = document_and_path
42 end
44 module Ide_file_changed = struct
45 type request = { file_path: Path.t }
46 end
48 module Hover = struct
49 type request = document_location
51 type result = HoverService.result
52 end
54 module Definition = struct
55 type request = document_location
57 type result = ServerCommandTypes.Go_to_definition.result
58 end
60 (* Handles "textDocument/typeDefinition" LSP messages *)
61 module Type_definition = struct
62 type request = document_location
64 type result = ServerCommandTypes.Go_to_type_definition.result
65 end
67 (* Handles "textDocument/completion" LSP messages *)
68 module Completion = struct
69 type request = {
70 document_location: document_location;
71 is_manually_invoked: bool;
74 type result = AutocompleteTypes.ide_result
75 end
77 (* "completionItem/resolve" LSP messages - if we have symbol name *)
78 module Completion_resolve = struct
79 type request = {
80 symbol: string;
81 kind: SearchUtils.si_kind;
84 type result = DocblockService.result
85 end
87 (* "completionItem/resolve" LSP messages - if we have file/line/column *)
88 module Completion_resolve_location = struct
89 type request = {
90 kind: SearchUtils.si_kind;
91 document_location: document_location;
94 type result = DocblockService.result
95 end
97 (* Handles "textDocument/documentHighlight" LSP messages *)
98 module Document_highlight = struct
99 type request = document_location
101 type result = Ide_api_types.range list
104 (* Handles "textDocument/signatureHelp" LSP messages *)
105 module Signature_help = struct
106 type request = document_location
108 type result = Lsp.SignatureHelp.result
111 (* Handles "textDocument/documentSymbol" LSP messages *)
112 module Document_symbol = struct
113 type request = document_location
115 type result = FileOutline.outline
118 module Type_coverage = struct
119 type request = document_and_path
121 type result = Coverage_level_defs.result
124 (* GADT for request/response types. See [ServerCommandTypes] for a discussion on
125 using GADTs in this way. *)
126 type _ t =
127 | Initialize_from_saved_state :
128 Initialize_from_saved_state.t
129 -> Initialize_from_saved_state.result t
130 | Shutdown : unit -> unit t
131 | Disk_files_changed : Path.t list -> unit t
132 | Ide_file_opened : Ide_file_opened.request -> unit t
133 | Ide_file_changed : Ide_file_changed.request -> unit t
134 | Ide_file_closed : Path.t -> unit t
135 | Verbose : bool -> unit t
136 | Hover : Hover.request -> Hover.result t
137 | Definition : Definition.request -> Definition.result t
138 | Completion : Completion.request -> Completion.result t
139 | Completion_resolve :
140 Completion_resolve.request
141 -> Completion_resolve.result t
142 | Completion_resolve_location :
143 Completion_resolve_location.request
144 -> Completion_resolve_location.result t
145 | Document_highlight :
146 Document_highlight.request
147 -> Document_highlight.result t
148 | Document_symbol : Document_symbol.request -> Document_symbol.result t
149 | Type_definition : Type_definition.request -> Type_definition.result t
150 | Type_coverage : Type_coverage.request -> Type_coverage.result t
151 | Signature_help : Signature_help.request -> Signature_help.result t
153 let t_to_string : type a. a t -> string = function
154 | Initialize_from_saved_state _ -> "Initialize_from_saved_state"
155 | Shutdown () -> "Shutdown"
156 | Disk_files_changed files ->
157 let files = List.map files ~f:Path.to_string in
158 let (files, remainder) = List.split_n files 10 in
159 let remainder =
160 if List.is_empty remainder then
162 else
163 ",..."
165 Printf.sprintf "Disk_file_changed(%s%s)" (String.concat files) remainder
166 | Ide_file_opened { file_path; _ } ->
167 Printf.sprintf "Ide_file_opened(%s)" (Path.to_string file_path)
168 | Ide_file_changed { Ide_file_changed.file_path; _ } ->
169 Printf.sprintf "Ide_file_changed(%s)" (Path.to_string file_path)
170 | Ide_file_closed file_path ->
171 Printf.sprintf "Ide_file_closed(%s)" (Path.to_string file_path)
172 | Verbose verbose -> Printf.sprintf "Verbose(%b)" verbose
173 | Hover { file_path; _ } ->
174 Printf.sprintf "Hover(%s)" (Path.to_string file_path)
175 | Definition { file_path; _ } ->
176 Printf.sprintf "Definition(%s)" (Path.to_string file_path)
177 | Completion { Completion.document_location = { file_path; _ }; _ } ->
178 Printf.sprintf "Completion(%s)" (Path.to_string file_path)
179 | Completion_resolve { Completion_resolve.symbol; _ } ->
180 Printf.sprintf "Completion_resolve(%s)" symbol
181 | Completion_resolve_location
182 { Completion_resolve_location.document_location = { file_path; _ }; _ } ->
183 Printf.sprintf "Completion_resolve_location(%s)" (Path.to_string file_path)
184 | Document_highlight { file_path; _ } ->
185 Printf.sprintf "Document_highlight(%s)" (Path.to_string file_path)
186 | Document_symbol { file_path; _ } ->
187 Printf.sprintf "Document_symbol(%s)" (Path.to_string file_path)
188 | Type_definition { file_path; _ } ->
189 Printf.sprintf "Type_definition(%s)" (Path.to_string file_path)
190 | Type_coverage { file_path; _ } ->
191 Printf.sprintf "Type_coverage(%s)" (Path.to_string file_path)
192 | Signature_help { file_path; _ } ->
193 Printf.sprintf "Signature_help(%s)" (Path.to_string file_path)
195 type 'a tracked_t = {
196 tracking_id: string;
197 message: 'a t;
200 let tracked_t_to_string : type a. a tracked_t -> string =
201 fun { tracking_id; message } ->
202 Printf.sprintf "#%s: %s" tracking_id (t_to_string message)
204 module Processing_files = struct
205 type t = {
206 processed: int;
207 total: int;
210 let to_string (t : t) : string = Printf.sprintf "%d/%d" t.processed t.total
213 type notification =
214 | Initializing
215 | Processing_files of Processing_files.t
216 | Done_processing
218 let notification_to_string (n : notification) : string =
219 match n with
220 | Initializing -> "Initializing"
221 | Processing_files p ->
222 Printf.sprintf "Processing_file(%s)" (Processing_files.to_string p)
223 | Done_processing -> "Done_processing"
225 type error_data = {
226 (* max 20 chars, for status bar. Will be prepended by "Hack:" *)
227 short_user_message: string;
228 (* max 10 words, for tooltip and alert. Will be postpended by " See <log>" *)
229 medium_user_message: string;
230 (* should we have window/showMessage, i.e. an alert? *)
231 is_actionable: bool;
232 (* max 5 lines, for window/logMessage, i.e. Output>Hack window. Will be postpended by "\nDetails: <url>" *)
233 long_user_message: string;
234 (* for experts. Will go in Hh_logger.log, and will be uploaded *)
235 debug_details: string;
238 (** make_error_data is for reporting internal bugs, invariant
239 violations, unexpected exceptions, ... *)
240 let make_error_data (debug_details : string) ~(stack : string) : error_data =
242 short_user_message = "failed";
243 medium_user_message = "Hack IDE has failed.";
244 long_user_message =
245 "Hack IDE has failed.\nThis is unexpected.\nPlease file a bug within your IDE.";
246 debug_details = debug_details ^ "\nSTACK:\n" ^ stack;
247 is_actionable = false;
250 type 'a timed_response = {
251 unblocked_time: float;
252 response: ('a, error_data) result;
255 type message_from_daemon =
256 | Notification of notification
257 | Response : 'a timed_response -> message_from_daemon
259 let message_from_daemon_to_string (m : message_from_daemon) : string =
260 match m with
261 | Notification n -> notification_to_string n
262 | Response { response = Error { short_user_message; _ }; _ } ->
263 Printf.sprintf "Response_error(%s)" short_user_message
264 | Response { response = Ok _; _ } -> Printf.sprintf "Response_ok"
266 type daemon_args = {
267 init_id: string;
268 verbose: bool;