this repo has no description
at main 345 lines 11 kB view raw
1(* Unix worker *) 2open Js_top_worker 3open Impl 4 5let capture : (unit -> 'a) -> unit -> Impl.captured * 'a = 6 fun f () -> 7 let stdout_buff = Buffer.create 1024 in 8 let stderr_buff = Buffer.create 1024 in 9 Js_of_ocaml.Sys_js.set_channel_flusher stdout (Buffer.add_string stdout_buff); 10 11 let x = f () in 12 let captured = 13 { 14 Impl.stdout = Buffer.contents stdout_buff; 15 stderr = Buffer.contents stderr_buff; 16 } 17 in 18 (captured, x) 19 20module S : Impl.S = struct 21 type findlib_t = Js_top_worker_web.Findlibish.t 22 23 let capture = capture 24 25 let sync_get f = 26 let f = Fpath.v ("_opam/" ^ f) in 27 Logs.info (fun m -> m "sync_get: %a" Fpath.pp f); 28 try Some (In_channel.with_open_bin (Fpath.to_string f) In_channel.input_all) 29 with e -> 30 Logs.err (fun m -> 31 m "Error reading file %a: %s" Fpath.pp f (Printexc.to_string e)); 32 None 33 34 let async_get f = 35 let f = Fpath.v ("_opam/" ^ f) in 36 Logs.info (fun m -> m "async_get: %a" Fpath.pp f); 37 (* For Node.js, we use synchronous file reading wrapped in Lwt *) 38 try 39 let content = 40 In_channel.with_open_bin (Fpath.to_string f) In_channel.input_all 41 in 42 Lwt.return (Ok content) 43 with e -> 44 Logs.err (fun m -> 45 m "Error reading file %a: %s" Fpath.pp f (Printexc.to_string e)); 46 Lwt.return (Error (`Msg (Printexc.to_string e))) 47 48 let create_file = Js_of_ocaml.Sys_js.create_file 49 50 let import_scripts urls = 51 let open Js_of_ocaml.Js in 52 let import_scripts_fn = Unsafe.get Unsafe.global (string "importScripts") in 53 List.iter 54 (fun url -> 55 let (_ : 'a) = 56 Unsafe.fun_call import_scripts_fn [| Unsafe.inject (string url) |] 57 in 58 ()) 59 urls 60 61 let init_function _ () = failwith "Not implemented" 62 let findlib_init = Js_top_worker_web.Findlibish.init async_get 63 64 let get_stdlib_dcs uri = 65 Js_top_worker_web.Findlibish.fetch_dynamic_cmis sync_get uri 66 |> Result.to_list 67 68 let find_stdlib_dcs v = 69 let pkg = match Js_top_worker_web.Findlibish.find_dcs_url v "stdlib" with 70 | Some _ as r -> r 71 | None -> Js_top_worker_web.Findlibish.find_dcs_url v "ocaml" 72 in 73 match pkg with 74 | Some url -> 75 Js_top_worker_web.Findlibish.fetch_dynamic_cmis sync_get url 76 |> Result.to_list 77 | None -> [] 78 79 let require b v = function 80 | [] -> [] 81 | packages -> Js_top_worker_web.Findlibish.require ~import_scripts sync_get b v packages 82 83 let path = "/static/cmis" 84end 85 86module U = Impl.Make (S) 87 88let _ = 89 Logs.set_reporter (Logs_fmt.reporter ()); 90 Logs.set_level (Some Logs.Info); 91 Logs.info (fun m -> m "Starting server..."); 92 let ( let* ) m f = 93 let open Lwt in 94 m >>= function 95 | Ok x -> f x 96 | Error e -> return (Error e) 97 in 98 let init_config = 99 { stdlib_dcs = None; findlib_requires = [ "base" ]; findlib_index = None; execute = true } 100 in 101 let x = 102 let* _ = U.init init_config in 103 let* o = U.setup "" in 104 Logs.info (fun m -> 105 m "setup output: %s" (Option.value ~default:"" o.stdout)); 106 let* _ = U.query_errors "" (Some "c1") [] false "type xxxx = int;;\n" in 107 let* o1 = 108 U.query_errors "" (Some "c2") [ "c1" ] false "type yyy = xxx;;\n" 109 in 110 Logs.info (fun m -> m "Number of errors: %d (should be 1)" (List.length o1)); 111 let* _ = U.query_errors "" (Some "c1") [] false "type xxx = int;;\n" in 112 let* o2 = 113 U.query_errors "" (Some "c2") [ "c1" ] false "type yyy = xxx;;\n" 114 in 115 Logs.info (fun m -> 116 m "Number of errors1: %d (should be 1)" (List.length o1)); 117 Logs.info (fun m -> 118 m "Number of errors2: %d (should be 0)" (List.length o2)); 119 120 (* Test completion for List.leng *) 121 let* completions1 = 122 let text = "let _ = List.leng" in 123 U.complete_prefix "" (Some "c_comp1") [] false text 124 (Offset (String.length text)) 125 in 126 Logs.info (fun m -> 127 m "Completions for 'List.leng': %d entries" 128 (List.length completions1.entries)); 129 List.iter 130 (fun entry -> 131 Logs.info (fun m -> 132 m " - %s (%s): %s" entry.name 133 (match entry.kind with 134 | Constructor -> "Constructor" 135 | Keyword -> "Keyword" 136 | Label -> "Label" 137 | MethodCall -> "MethodCall" 138 | Modtype -> "Modtype" 139 | Module -> "Module" 140 | Type -> "Type" 141 | Value -> "Value" 142 | Variant -> "Variant") 143 entry.desc)) 144 completions1.entries; 145 146 (* Test completion for List. (should show all List module functions) *) 147 let* completions2 = 148 let text = "# let _ = List." in 149 U.complete_prefix "" (Some "c_comp2") [] true text 150 (Offset (String.length text)) 151 in 152 Logs.info (fun m -> 153 m "Completions for 'List.': %d entries" 154 (List.length completions2.entries)); 155 List.iter 156 (fun entry -> 157 Logs.info (fun m -> 158 m " - %s (%s): %s" entry.name 159 (match entry.kind with 160 | Constructor -> "Constructor" 161 | Keyword -> "Keyword" 162 | Label -> "Label" 163 | MethodCall -> "MethodCall" 164 | Modtype -> "Modtype" 165 | Module -> "Module" 166 | Type -> "Type" 167 | Value -> "Value" 168 | Variant -> "Variant") 169 entry.desc)) 170 completions2.entries; 171 172 (* Test completion for partial identifier *) 173 let* completions3 = 174 let text = "# let _ = ma" in 175 U.complete_prefix "" (Some "c_comp3") [] true text 176 (Offset (String.length text)) 177 in 178 Logs.info (fun m -> 179 m "Completions for 'ma': %d entries" (List.length completions3.entries)); 180 List.iter 181 (fun entry -> 182 Logs.info (fun m -> 183 m " - %s (%s): %s" entry.name 184 (match entry.kind with 185 | Constructor -> "Constructor" 186 | Keyword -> "Keyword" 187 | Label -> "Label" 188 | MethodCall -> "MethodCall" 189 | Modtype -> "Modtype" 190 | Module -> "Module" 191 | Type -> "Type" 192 | Value -> "Value" 193 | Variant -> "Variant") 194 entry.desc)) 195 completions3.entries; 196 197 (* Test completion in non-toplevel context *) 198 let* completions4 = 199 let text = "let _ = List.leng" in 200 U.complete_prefix "" (Some "c_comp4") [] false text 201 (Offset (String.length text)) 202 in 203 Logs.info (fun m -> 204 m "Completions for 'List.leng' (non-toplevel): %d entries" 205 (List.length completions4.entries)); 206 List.iter 207 (fun entry -> 208 Logs.info (fun m -> 209 m " - %s (%s): %s" entry.name 210 (match entry.kind with 211 | Constructor -> "Constructor" 212 | Keyword -> "Keyword" 213 | Label -> "Label" 214 | MethodCall -> "MethodCall" 215 | Modtype -> "Modtype" 216 | Module -> "Module" 217 | Type -> "Type" 218 | Value -> "Value" 219 | Variant -> "Variant") 220 entry.desc)) 221 completions4.entries; 222 223 (* Test completion using Logical position constructor *) 224 let* completions5 = 225 let text = "# let _ = List.leng\n let foo=1.0;;" in 226 U.complete_prefix "" (Some "c_comp5") [] true text 227 (Logical (1, 16)) 228 in 229 Logs.info (fun m -> 230 m "Completions for 'List.leng' (Logical position): %d entries" 231 (List.length completions5.entries)); 232 List.iter 233 (fun entry -> 234 Logs.info (fun m -> 235 m " - %s (%s): %s" entry.name 236 (match entry.kind with 237 | Constructor -> "Constructor" 238 | Keyword -> "Keyword" 239 | Label -> "Label" 240 | MethodCall -> "MethodCall" 241 | Modtype -> "Modtype" 242 | Module -> "Module" 243 | Type -> "Type" 244 | Value -> "Value" 245 | Variant -> "Variant") 246 entry.desc)) 247 completions5.entries; 248 249 (* Test toplevel completion with variable binding *) 250 let* completions6 = 251 let s = "# let my_var = 42;;\n# let x = 1 + my_v" in 252 U.complete_prefix "" (Some "c_comp6") [] true 253 s 254 (Offset (String.length s)) 255 in 256 Logs.info (fun m -> 257 m "Completions for 'my_v' (toplevel variable): %d entries" 258 (List.length completions6.entries)); 259 List.iter 260 (fun entry -> 261 Logs.info (fun m -> 262 m " - %s (%s): %s" entry.name 263 (match entry.kind with 264 | Constructor -> "Constructor" 265 | Keyword -> "Keyword" 266 | Label -> "Label" 267 | MethodCall -> "MethodCall" 268 | Modtype -> "Modtype" 269 | Module -> "Module" 270 | Type -> "Type" 271 | Value -> "Value" 272 | Variant -> "Variant") 273 entry.desc)) 274 completions6.entries; 275 276 (* Test toplevel completion with function definition *) 277 let* completions7 = 278 U.complete_prefix "" (Some "c_comp7") [] true 279 "# let rec factorial n = if n <= 1 then 1 else n * facto" 280 (Offset 55) 281 in 282 Logs.info (fun m -> 283 m "Completions for 'facto' (recursive function): %d entries" 284 (List.length completions7.entries)); 285 List.iter 286 (fun entry -> 287 Logs.info (fun m -> 288 m " - %s (%s): %s" entry.name 289 (match entry.kind with 290 | Constructor -> "Constructor" 291 | Keyword -> "Keyword" 292 | Label -> "Label" 293 | MethodCall -> "MethodCall" 294 | Modtype -> "Modtype" 295 | Module -> "Module" 296 | Type -> "Type" 297 | Value -> "Value" 298 | Variant -> "Variant") 299 entry.desc)) 300 completions7.entries; 301 302 (* Test toplevel completion with module paths *) 303 let* completions8 = 304 U.complete_prefix "" (Some "c_comp8") [] true 305 "# String.lengt" 306 (Offset 14) 307 in 308 Logs.info (fun m -> 309 m "Completions for 'String.lengt' (module path): %d entries" 310 (List.length completions8.entries)); 311 List.iter 312 (fun entry -> 313 Logs.info (fun m -> 314 m " - %s (%s): %s" entry.name 315 (match entry.kind with 316 | Constructor -> "Constructor" 317 | Keyword -> "Keyword" 318 | Label -> "Label" 319 | MethodCall -> "MethodCall" 320 | Modtype -> "Modtype" 321 | Module -> "Module" 322 | Type -> "Type" 323 | Value -> "Value" 324 | Variant -> "Variant") 325 entry.desc)) 326 completions8.entries; 327 328 (* let* o3 = 329 Client.exec_toplevel rpc 330 "# Stringext.of_list ['a';'b';'c'];;\n" in 331 Logs.info (fun m -> m "Exec toplevel output: %s" o3.script); *) 332 Lwt.return (Ok ()) 333 in 334 (* The operations are actually synchronous in this test context *) 335 let promise = x in 336 match Lwt.state promise with 337 | Lwt.Return (Ok ()) -> Logs.info (fun m -> m "Success") 338 | Lwt.Return (Error (InternalError s)) -> Logs.err (fun m -> m "Error: %s" s) 339 | Lwt.Fail e -> 340 Logs.err (fun m -> m "Unexpected failure: %s" (Printexc.to_string e)) 341 | Lwt.Sleep -> 342 Logs.err (fun m -> 343 m 344 "Error: Promise is still pending (should not happen in sync \ 345 context)")