├── .github └── workflows │ └── js.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── dune-project ├── example ├── app.ml ├── dune ├── dynamic.html ├── dynamic.ml ├── index.html ├── stdlib └── worker │ ├── dune │ └── merlin_worker.ml ├── merlin-js.opam └── src ├── client ├── dune └── merlin_client.ml ├── extension ├── dune ├── merlin_codemirror.ml ├── merlin_codemirror.mli └── utils.ml ├── protocol ├── dune └── protocol.ml └── worker ├── dune ├── static ├── dune ├── gen_static.ml └── stdlib │ ├── arith_status.cmi │ ├── big_int.cmi │ ├── bigarray.cmi │ ├── camlinternalAtomic.cmi │ ├── camlinternalFormat.cmi │ ├── camlinternalFormatBasics.cmi │ ├── camlinternalLazy.cmi │ ├── camlinternalMod.cmi │ ├── camlinternalOO.cmi │ ├── dynlink.cmi │ ├── event.cmi │ ├── profiling.cmi │ ├── ratio.cmi │ ├── runtime_events.cmi │ ├── std_exit.cmi │ ├── stdlib.cmi │ ├── stdlib__Arg.cmi │ ├── stdlib__Array.cmi │ ├── stdlib__ArrayLabels.cmi │ ├── stdlib__Atomic.cmi │ ├── stdlib__Bigarray.cmi │ ├── stdlib__Bool.cmi │ ├── stdlib__Buffer.cmi │ ├── stdlib__Bytes.cmi │ ├── stdlib__BytesLabels.cmi │ ├── stdlib__Callback.cmi │ ├── stdlib__Char.cmi │ ├── stdlib__Complex.cmi │ ├── stdlib__Condition.cmi │ ├── stdlib__Digest.cmi │ ├── stdlib__Domain.cmi │ ├── stdlib__Dynarray.cmi │ ├── stdlib__Effect.cmi │ ├── stdlib__Either.cmi │ ├── stdlib__Ephemeron.cmi │ ├── stdlib__Filename.cmi │ ├── stdlib__Float.cmi │ ├── stdlib__Format.cmi │ ├── stdlib__Fun.cmi │ ├── stdlib__Gc.cmi │ ├── stdlib__Genlex.cmi │ ├── stdlib__Hashtbl.cmi │ ├── stdlib__In_channel.cmi │ ├── stdlib__Int.cmi │ ├── stdlib__Int32.cmi │ ├── stdlib__Int64.cmi │ ├── stdlib__Lazy.cmi │ ├── stdlib__Lexing.cmi │ ├── stdlib__List.cmi │ ├── stdlib__ListLabels.cmi │ ├── stdlib__Map.cmi │ ├── stdlib__Marshal.cmi │ ├── stdlib__MoreLabels.cmi │ ├── stdlib__Mutex.cmi │ ├── stdlib__Nativeint.cmi │ ├── stdlib__Obj.cmi │ ├── stdlib__Oo.cmi │ ├── stdlib__Option.cmi │ ├── stdlib__Out_channel.cmi │ ├── stdlib__Parsing.cmi │ ├── stdlib__Pervasives.cmi │ ├── stdlib__Printexc.cmi │ ├── stdlib__Printf.cmi │ ├── stdlib__Queue.cmi │ ├── stdlib__Random.cmi │ ├── stdlib__Result.cmi │ ├── stdlib__Scanf.cmi │ ├── stdlib__Semaphore.cmi │ ├── stdlib__Seq.cmi │ ├── stdlib__Set.cmi │ ├── stdlib__Stack.cmi │ ├── stdlib__StdLabels.cmi │ ├── stdlib__Stream.cmi │ ├── stdlib__String.cmi │ ├── stdlib__StringLabels.cmi │ ├── stdlib__Sys.cmi │ ├── stdlib__Type.cmi │ ├── stdlib__Uchar.cmi │ ├── stdlib__Unit.cmi │ ├── stdlib__Weak.cmi │ ├── str.cmi │ ├── thread.cmi │ ├── topdirs.cmi │ ├── unix.cmi │ └── unixLabels.cmi ├── stubs.js ├── worker.ml └── worker.mli /.github/workflows/js.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ main ] 10 | pull_request: 11 | branches: [ main ] 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | build: 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | os: 21 | - ubuntu-latest 22 | ocaml-compiler: 23 | - 5.2.x 24 | # The type of runner that the job will run on 25 | runs-on: ${{ matrix.os }} 26 | 27 | # Steps represent a sequence of tasks that will be executed as part of the job 28 | steps: 29 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 30 | - uses: actions/checkout@v4 31 | 32 | - name: Set up OCaml ${{ matrix.ocaml-compiler }} 33 | uses: ocaml/setup-ocaml@v3 34 | with: 35 | # Version of the OCaml compiler to initialise 36 | ocaml-compiler: ${{ matrix.ocaml-compiler }} 37 | 38 | - name: Install dependencies 39 | run: opam install . --deps-only --with-test 40 | 41 | - name: Build and test in release mode 42 | run: opam exec -- make js 43 | 44 | - name: Deploy 45 | if: ${{ github.event_name == 'push' }} 46 | uses: peaceiris/actions-gh-pages@v3 47 | with: 48 | github_token: ${{ secrets.GITHUB_TOKEN }} 49 | publish_dir: ./example 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | _opam 3 | .merlin 4 | jbuild-workspace 5 | dune-workspace 6 | *.install 7 | *.tar.gz 8 | *.pyc 9 | *.cmly 10 | *.elc 11 | 12 | /ocamlmerlin 13 | /ocamlmerlin-server 14 | /ocamlmerlin-lsp 15 | /dot-merlin-reader 16 | 17 | # Ignore garbage files from editors 18 | *.un~ 19 | *.swp 20 | *.swo 21 | 22 | # merlin js specific 23 | *.bc* 24 | node_modules 25 | index.js 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ulysse Gérard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | js: 2 | dune build @all-js --profile=release --ignore-promoted-rules 3 | 4 | js-dev: 5 | dune build @all-js --watch --terminal-persistence=clear-on-rebuild 6 | 7 | jsoo-node: 8 | cd vendor/jsoo-code-mirror && npm install 9 | 10 | .PHONY: js-dev js 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # merlin-js 2 | 3 | Try-it: [https://voodoos.github.io/merlin-js](https://voodoos.github.io/merlin-js) 4 | 5 | To run locally, run 'make' then launch an http server from the 'examples' directory. For example: 6 | 7 | ```sh 8 | make 9 | cd examples 10 | python3 -m http.server 11 | ``` 12 | 13 | 14 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 3.0) 2 | 3 | (name merlin-js) 4 | -------------------------------------------------------------------------------- /example/app.ml: -------------------------------------------------------------------------------- 1 | open Code_mirror 2 | 3 | module Merlin = 4 | Merlin_codemirror.Make (struct 5 | let worker_url = "merlin_worker.bc.js" 6 | let cmis = { Protocol.static_cmis = Static_files.stdlib_cmis; dynamic_cmis = None } 7 | end) 8 | 9 | let basic_setup = Jv.get Jv.global "__CM__basic_setup" |> Extension.of_jv 10 | 11 | let init ?doc ?(exts = [||]) () = 12 | let open Editor in 13 | let extensions = 14 | Array.append [| basic_setup; Merlin_codemirror.ocaml |] exts 15 | in 16 | let config = 17 | State.Config.create ?doc ~extensions () 18 | in 19 | let state = State.create ~config () in 20 | let opts = View.opts 21 | ~state 22 | ~parent:(Merlin_codemirror.Utils.get_el_by_id "editor") () 23 | in 24 | let view : View.t = View.create ~opts () in 25 | (state, view) 26 | 27 | let _editor = init ~exts:Merlin.all_extensions () 28 | -------------------------------------------------------------------------------- /example/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (name app) 3 | (modes js) 4 | (promote) 5 | (modules App) 6 | (libraries 7 | merlin_client 8 | code-mirror 9 | merlin-js.code-mirror 10 | merlin-js.worker.static)) 11 | 12 | (executable 13 | (name dynamic) 14 | (modes js) 15 | (promote) 16 | (modules Dynamic) 17 | (libraries 18 | merlin_client 19 | code-mirror 20 | merlin-js.code-mirror)) 21 | 22 | (copy_files 23 | (mode promote) 24 | (files worker/merlin_worker.bc.js)) 25 | 26 | (alias 27 | (name all-js) 28 | (deps 29 | merlin_worker.bc.js 30 | app.bc.js 31 | dynamic.bc.js)) 32 | -------------------------------------------------------------------------------- /example/dynamic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 |This example demonstrates merlin with dynamic loading of cmis. Load the 83 | 'Network' tab of the developer tools to see the requests and responses. 84 | See also the static example. 85 |
86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /example/dynamic.ml: -------------------------------------------------------------------------------- 1 | open Code_mirror 2 | 3 | module Merlin = 4 | Merlin_codemirror.Make (struct 5 | let worker_url = "merlin_worker.bc.js" 6 | let cmis = 7 | let dcs_toplevel_modules = [ 8 | "CamlinternalAtomic"; 9 | "CamlinternalFormat"; 10 | "CamlinternalFormatBasics"; 11 | "CamlinternalLazy"; 12 | "CamlinternalMod"; 13 | "CamlinternalOO"; 14 | "Std_exit"; 15 | "Stdlib"; 16 | "Unix"; 17 | "UnixLabels"; 18 | ] in 19 | let dcs_url = "stdlib/" in 20 | let dcs_file_prefixes = ["stdlib__"] in 21 | { Protocol.static_cmis = []; 22 | dynamic_cmis = Some { 23 | dcs_url; dcs_toplevel_modules; dcs_file_prefixes } } 24 | end) 25 | 26 | let basic_setup = Jv.get Jv.global "__CM__basic_setup" |> Extension.of_jv 27 | 28 | let init ?doc ?(exts = [||]) () = 29 | let open Editor in 30 | let extensions = 31 | Array.append [| basic_setup; Merlin_codemirror.ocaml |] exts 32 | in 33 | let config = 34 | State.Config.create ?doc ~extensions () 35 | in 36 | let state = State.create ~config () in 37 | let opts = View.opts 38 | ~state 39 | ~parent:(Merlin_codemirror.Utils.get_el_by_id "editor") () 40 | in 41 | let view : View.t = View.create ~opts () in 42 | (state, view) 43 | 44 | let _editor = init ~exts:Merlin.all_extensions () 45 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |This example demonstrates merlin with all cmis embedded. See dynamic.html 83 | for an example of dynamically loaded cmis.
84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/stdlib: -------------------------------------------------------------------------------- 1 | ../src/worker/static/stdlib -------------------------------------------------------------------------------- /example/worker/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (name merlin_worker) 3 | (modules merlin_worker) 4 | (promote (until-clean)) 5 | (modes js) 6 | (libraries worker)) 7 | -------------------------------------------------------------------------------- /example/worker/merlin_worker.ml: -------------------------------------------------------------------------------- 1 | let () = Worker.run () 2 | -------------------------------------------------------------------------------- /merlin-js.opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | maintainer: "thevoodoos@gmail.com" 3 | authors: "Ulysse Gérard" 4 | homepage: "https://github.com/voodoos/merlin-js" 5 | bug-reports: "https://github.com/voodoos/merlin-js/issues" 6 | dev-repo: "git+https://github.com/voodoos/merlin-js.git" 7 | license: "MIT" 8 | build: [ 9 | ["dune" "subst"] {dev} 10 | ["dune" "build" "-p" name "-j" jobs] 11 | ] 12 | depends: [ 13 | "ocaml" {>= "5.2" & < "5.3"} 14 | "dune" {>= "3.0"} 15 | "merlin-lib" 16 | "yojson" {>= "1.6.0"} 17 | "js_of_ocaml" {>= "5.0.0"} 18 | "js_of_ocaml-ppx" {>= "5.0.0"} 19 | "brr" {>= "0.0.4"} 20 | "ppx_blob" {>= "0.7.2"} 21 | "code-mirror" 22 | ] 23 | pin-depends: [ 24 | ["code-mirror.dev" "git+https://github.com/patricoferris/jsoo-code-mirror#8fe48910e265ff87f9fc94ceb7b3d19fac102a96"] 25 | ] 26 | synopsis: 27 | "Editor helper, provides completion, typing and source browsing for the web" 28 | description: 29 | "Merlin is an assistant for editing OCaml code. It aims to provide the features available in modern browsers: error reporting, auto completion, source browsing and much more." 30 | -------------------------------------------------------------------------------- /src/client/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name merlin_client) 3 | (public_name merlin-js.client) 4 | (libraries protocol brr)) 5 | -------------------------------------------------------------------------------- /src/client/merlin_client.ml: -------------------------------------------------------------------------------- 1 | open Brr 2 | module Worker = Brr_webworkers.Worker 3 | 4 | (* When a query is sent to the Worker we keep the Future result in an indexed 5 | table so that the on_message function will be able to determine the Future when 6 | the answer is posted by the Worker. 7 | The Worker works synchronously so we expect answer to arrive in order. *) 8 | type worker = { 9 | worker: Worker.t; 10 | queue: (Protocol.answer -> unit) Queue.t 11 | } 12 | 13 | let add_fut worker res = Queue.add res worker.queue 14 | let res_fut worker v = (Queue.take worker.queue) v 15 | 16 | let make_worker url = 17 | let worker = Worker.create @@ Jstr.of_string url in 18 | let queue = Queue.create () in 19 | let worker = { worker; queue } in 20 | let on_message m = 21 | let m = Ev.as_type m in 22 | let data_marshaled : bytes = Brr_io.Message.Ev.data m in 23 | let data : Protocol.answer = Marshal.from_bytes data_marshaled 0 in 24 | res_fut worker data 25 | in 26 | let _listener = 27 | Ev.listen Brr_io.Message.Ev.message on_message @@ 28 | Worker.as_target worker.worker 29 | in 30 | worker 31 | 32 | (* todo share that with worker *) 33 | type action = Completion | Type_enclosing | Errors 34 | 35 | type errors = Protocol.error list 36 | 37 | let query ~action worker (*todo: other queries*) = 38 | let fut, set = Fut.create () in 39 | add_fut worker set; 40 | Worker.post worker.worker (Marshal.to_bytes action []); 41 | fut 42 | 43 | let query_errors worker (source : string) = 44 | let open Fut.Syntax in 45 | let action = Protocol.All_errors source in 46 | let+ data : Protocol.answer = query ~action worker in 47 | Console.(log ["Received errors:"; data]); 48 | match data with 49 | | Protocol.Errors errors -> errors 50 | | _ -> assert false 51 | 52 | let query_completions worker (source : string) position = 53 | let open Fut.Syntax in 54 | let action = Protocol.Complete_prefix (source, position) in 55 | let+ data : Protocol.answer = query ~action worker in 56 | Console.(log ["Received completions:"; data]); 57 | match data with 58 | | Protocol.Completions compl -> compl 59 | | _ -> assert false 60 | 61 | let query_type worker (source : string) position = 62 | let open Fut.Syntax in 63 | let action = Protocol.Type_enclosing (source, position) in 64 | let+ data : Protocol.answer = query ~action worker in 65 | Console.(log ["Received typed enclosings:"; data]); 66 | match data with 67 | | Protocol.Typed_enclosings l -> l 68 | | _ -> assert false 69 | 70 | let add_cmis worker cmis = 71 | let open Fut.Syntax in 72 | let action = Protocol.Add_cmis cmis in 73 | let+ data : Protocol.answer = query ~action worker in 74 | Console.(log ["Received response from adding cmis:"; data]); 75 | match data with 76 | | Protocol.Added_cmis -> () 77 | | _ -> assert false -------------------------------------------------------------------------------- /src/extension/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name merlin_codemirror) 3 | (public_name merlin-js.code-mirror) 4 | (libraries 5 | brr 6 | merlin_client 7 | code-mirror 8 | code-mirror.lint 9 | code-mirror.autocomplete 10 | code-mirror.tooltip 11 | code-mirror.stream)) 12 | -------------------------------------------------------------------------------- /src/extension/merlin_codemirror.ml: -------------------------------------------------------------------------------- 1 | open Code_mirror 2 | open Brr 3 | 4 | module Utils = Utils 5 | 6 | let linter worker = fun view -> 7 | let open Fut.Syntax in 8 | let doc = Utils.get_full_doc @@ Editor.View.state view in 9 | let+ result = Merlin_client.query_errors worker doc in 10 | List.map (fun Protocol.{ kind; loc; main; sub = _; source } -> 11 | let from = loc.loc_start.pos_cnum in 12 | let to_ = loc.loc_end.pos_cnum in 13 | let source = Protocol.report_source_to_string source in 14 | let severity = match kind with 15 | | Report_error 16 | | Report_warning_as_error _ 17 | | Report_alert_as_error _ -> Lint.Diagnostic.Error 18 | | Report_warning _ -> Lint.Diagnostic.Warning 19 | | Report_alert _ -> Lint.Diagnostic.Info 20 | in 21 | Lint.Diagnostic.create ~source ~from ~to_ ~severity ~message:main () 22 | ) result 23 | |> Array.of_list 24 | 25 | let keywords = List.map 26 | (fun label -> 27 | Autocomplete.Completion.create ~label ~type_:"keyword" ()) 28 | [ 29 | "as"; "do"; "else"; "end"; "exception"; "fun"; "functor"; "if"; "in"; 30 | "include"; "let"; "of"; "open"; "rec"; "struct"; "then"; "type"; "val"; 31 | "while"; "with"; "and"; "assert"; "begin"; "class"; "constraint"; 32 | "done"; "downto"; "external"; "function"; "initializer"; "lazy"; 33 | "match"; "method"; "module"; "mutable"; "new"; "nonrec"; "object"; 34 | "private"; "sig"; "to"; "try"; "value"; "virtual"; "when"; 35 | ] 36 | 37 | let merlin_completion worker = fun ctx -> 38 | let open Fut.Syntax in 39 | let source = Utils.get_full_doc @@ Autocomplete.Context.state ctx in 40 | let pos = Autocomplete.Context.pos ctx in 41 | let+ { from; to_; entries } = 42 | Merlin_client.query_completions worker source (`Offset pos) 43 | in 44 | let options = 45 | let num_completions = List.length entries in 46 | List.mapi (fun i Query_protocol.Compl.{ name; desc; _ } -> 47 | let boost = num_completions - i in 48 | Autocomplete.Completion.create ~label:name ~detail:desc ~boost ()) entries 49 | in 50 | Some (Autocomplete.Result.create ~filter:true ~from ~to_ ~options ()) 51 | 52 | let autocomplete worker = 53 | let override = [ 54 | Autocomplete.Source.from_list keywords; 55 | Autocomplete.Source.create @@ merlin_completion worker] 56 | in 57 | let config = Autocomplete.config () ~override in 58 | Autocomplete.create ~config () 59 | 60 | let tooltip_on_hover worker = 61 | let open Tooltip in 62 | hover_tooltip @@ 63 | fun ~view ~pos ~side:_ -> 64 | let open Fut.Syntax in 65 | let doc = Utils.get_full_doc @@ Editor.View.state view in 66 | let pos = `Offset pos in 67 | let+ result = Merlin_client.query_type worker doc pos in 68 | match result with 69 | | (loc, `String type_, _)::_ -> 70 | let create _view = 71 | let dom = El.div [El.txt' type_] in 72 | Tooltip_view.create ~dom () 73 | in 74 | let pos = loc.loc_start.pos_cnum in 75 | let end_ = loc.loc_end.pos_cnum in 76 | Some (Tooltip.create ~pos ~end_ ~above:true ~arrow:true ~create ()) 77 | | _ -> None 78 | 79 | let ocaml = Jv.get Jv.global "__CM__mllike" |> Stream.Language.of_jv 80 | let ocaml = Stream.Language.define ocaml 81 | 82 | module type Config = sig 83 | val worker_url : string 84 | val cmis : Protocol.cmis 85 | end 86 | 87 | module Make (Config : Config) = struct 88 | let worker = 89 | let worker = Merlin_client.make_worker Config.worker_url in 90 | let _ = Merlin_client.add_cmis worker Config.cmis in 91 | worker 92 | 93 | let autocomplete = autocomplete worker 94 | let tooltip_on_hover = tooltip_on_hover worker 95 | let linter = Lint.create (linter worker) 96 | 97 | let all_extensions = [| 98 | linter; 99 | autocomplete; 100 | tooltip_on_hover 101 | |] 102 | end 103 | -------------------------------------------------------------------------------- /src/extension/merlin_codemirror.mli: -------------------------------------------------------------------------------- 1 | module Utils : sig 2 | val get_el_by_id : string -> Brr.El.t 3 | val get_full_doc : Code_mirror.Editor.State.t -> string 4 | end 5 | 6 | val ocaml : Code_mirror.Extension.t 7 | (** An extension providing OCaml syntax highlighting *) 8 | 9 | module type Config = sig 10 | val worker_url : string 11 | (** The url of the worker javascript file *) 12 | 13 | val cmis : Protocol.cmis 14 | (** CMIs are required for merlin to work correctly. These can either be 15 | provided statically or provided as a list of URLs from which the 16 | CMIs can be downloaded. If using URLs, these will only be 17 | downloaded on demand. *) 18 | end 19 | 20 | module Make : functor (Config : Config) -> sig 21 | val autocomplete : Code_mirror.Extension.t 22 | (** An extension providing completions when typing *) 23 | 24 | val tooltip_on_hover : Code_mirror.Extension.t 25 | (** An extension providing type-information when hovering code *) 26 | 27 | val linter : Code_mirror.Extension.t 28 | (** An extension that highlights errors and warnings in the code *) 29 | 30 | val all_extensions : Code_mirror.Extension.t array 31 | (** All the Merlin-specific extensions (does not include [ocaml]) *) 32 | end 33 | -------------------------------------------------------------------------------- /src/extension/utils.ml: -------------------------------------------------------------------------------- 1 | open Code_mirror 2 | open Brr 3 | let get_el_by_id i = 4 | Brr.Document.find_el_by_id G.document (Jstr.of_string i) |> Option.get 5 | 6 | 7 | let get_full_doc state = 8 | let lines = Editor.(state |> State.doc |> Text.to_jstr_array) in 9 | lines |> Array.map Jstr.to_string |> Array.to_list |> String.concat "\n" 10 | -------------------------------------------------------------------------------- /src/protocol/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name protocol) 3 | (public_name merlin-js.protocol) 4 | (libraries 5 | merlin-lib.ocaml_parsing 6 | merlin-lib.query_protocol 7 | merlin-lib.kernel)) 8 | -------------------------------------------------------------------------------- /src/protocol/protocol.ml: -------------------------------------------------------------------------------- 1 | open Merlin_kernel 2 | module Location = Ocaml_parsing.Location 3 | 4 | type source = string 5 | 6 | (** CMIs are provided either statically or as URLs to be downloaded on demand *) 7 | 8 | (** Dynamic cmis are loaded from beneath the given url. In addition the 9 | top-level modules are specified, and prefixes for other modules. For 10 | example, for the OCaml standard library, a user might pass: 11 | 12 | {[ 13 | { dcs_url="/static/stdlib"; 14 | dcs_toplevel_modules=["Stdlib"]; 15 | dcs_file_prefixes=["stdlib__"]; } 16 | ]} 17 | 18 | In which case, merlin will expect to be able to download a valid file 19 | from the url ["/static/stdlib/stdlib.cmi"] corresponding to the 20 | specified toplevel module, and it will also attempt to download any 21 | module with the prefix ["Stdlib__"] from the same base url, so for 22 | example if an attempt is made to look up the module ["Stdlib__Foo"] 23 | then merlin-js will attempt to download a file from the url 24 | ["/static/stdlib/stdlib__Foo.cmi"]. 25 | *) 26 | 27 | type dynamic_cmis = { 28 | dcs_url : string; 29 | dcs_toplevel_modules : string list; 30 | dcs_file_prefixes : string list; 31 | } 32 | 33 | type static_cmi = { 34 | sc_name : string; (* capitalised, e.g. 'Stdlib' *) 35 | sc_content : string; 36 | } 37 | 38 | type cmis = { 39 | static_cmis : static_cmi list; 40 | dynamic_cmis : dynamic_cmis option; 41 | } 42 | 43 | type action = 44 | | Complete_prefix of source * Msource.position 45 | | Type_enclosing of source * Msource.position 46 | | All_errors of source 47 | | Add_cmis of cmis 48 | 49 | type error = { 50 | kind : Location.report_kind; 51 | loc: Location.t; 52 | main : string; 53 | sub : string list; 54 | source : Location.error_source; 55 | } 56 | 57 | type completions = { 58 | from: int; 59 | to_: int; 60 | entries : Query_protocol.Compl.entry list 61 | } 62 | 63 | type is_tail_position = 64 | [`No | `Tail_position | `Tail_call] 65 | 66 | (* type errors = { from: int; to_: int; entries: error list } *) 67 | type answer = 68 | | Errors of error list 69 | | Completions of completions 70 | | Typed_enclosings of 71 | (Location.t * [ `Index of int | `String of string ] * is_tail_position) list 72 | | Added_cmis 73 | 74 | let report_source_to_string = function 75 | | Location.Lexer -> "lexer" 76 | | Location.Parser -> "parser" 77 | | Location.Typer -> "typer" 78 | | Location.Warning -> "warning" (* todo incorrect ?*) 79 | | Location.Unknown -> "unknown" 80 | | Location.Env -> "env" 81 | | Location.Config -> "config" 82 | -------------------------------------------------------------------------------- /src/worker/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name worker) 3 | (public_name merlin-js.worker) 4 | (js_of_ocaml 5 | (javascript_files stubs.js)) 6 | (preprocess (pps js_of_ocaml-ppx)) 7 | (libraries 8 | protocol 9 | merlin-lib.kernel 10 | merlin-lib.utils 11 | merlin-lib.query_protocol 12 | merlin-lib.query_commands 13 | merlin-lib.ocaml_parsing 14 | js_of_ocaml)) 15 | -------------------------------------------------------------------------------- /src/worker/static/dune: -------------------------------------------------------------------------------- 1 | (data_only_dirs stdlib) 2 | 3 | (library 4 | (name static_files) 5 | (public_name merlin-js.worker.static) 6 | (modules static_files) 7 | (preprocess (pps ppx_blob)) 8 | (libraries merlin-js.protocol) 9 | (preprocessor_deps 10 | (glob_files stdlib/*.cmi))) 11 | 12 | (rule 13 | (target static_files.ml) 14 | (deps (glob_files stdlib/*.cmi)) 15 | (action (run ocaml %{dep:gen_static.ml}))) 16 | -------------------------------------------------------------------------------- /src/worker/static/gen_static.ml: -------------------------------------------------------------------------------- 1 | #use "topfind" ;; 2 | #require "unix";; 3 | 4 | 5 | let rec iter_cmi ~f dir_handle = 6 | match Unix.readdir dir_handle with 7 | | exception End_of_file -> () 8 | | file -> 9 | if Filename.extension file = ".cmi" then 10 | f file; 11 | iter_cmi ~f dir_handle 12 | 13 | let () = 14 | let cwd = Unix.getcwd () in 15 | let stdlib = Filename.concat cwd "stdlib" in 16 | let out = open_out "static_files.ml" in 17 | 18 | Printf.fprintf out "open Protocol\nlet stdlib_cmis = ["; 19 | let dir = Unix.opendir stdlib in 20 | iter_cmi ~f:(fun file -> 21 | let fullpath = Filename.concat stdlib file in 22 | let module_name = Filename.basename file |> String.capitalize_ascii |> Filename.remove_extension in 23 | Printf.fprintf out "{sc_name=%S; sc_content=[%%blob %S]};" module_name fullpath) dir; 24 | Printf.fprintf out "]\n"; 25 | 26 | close_out out 27 | -------------------------------------------------------------------------------- /src/worker/static/stdlib/arith_status.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/arith_status.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/big_int.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/big_int.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/bigarray.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/bigarray.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/camlinternalAtomic.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/camlinternalAtomic.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/camlinternalFormat.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/camlinternalFormat.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/camlinternalFormatBasics.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/camlinternalFormatBasics.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/camlinternalLazy.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/camlinternalLazy.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/camlinternalMod.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/camlinternalMod.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/camlinternalOO.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/camlinternalOO.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/dynlink.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/dynlink.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/event.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/event.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/profiling.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/profiling.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/ratio.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/ratio.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/runtime_events.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/runtime_events.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/std_exit.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/std_exit.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Arg.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Arg.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Array.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Array.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__ArrayLabels.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__ArrayLabels.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Atomic.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Atomic.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Bigarray.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Bigarray.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Bool.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Bool.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Buffer.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Buffer.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Bytes.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Bytes.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__BytesLabels.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__BytesLabels.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Callback.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Callback.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Char.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Char.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Complex.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Complex.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Condition.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Condition.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Digest.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Digest.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Domain.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Domain.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Dynarray.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Dynarray.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Effect.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Effect.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Either.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Either.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Ephemeron.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Ephemeron.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Filename.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Filename.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Float.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Float.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Format.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Format.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Fun.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Fun.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Gc.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Gc.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Genlex.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Genlex.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Hashtbl.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Hashtbl.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__In_channel.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__In_channel.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Int.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Int.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Int32.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Int32.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Int64.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Int64.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Lazy.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Lazy.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Lexing.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Lexing.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__List.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__List.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__ListLabels.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__ListLabels.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Map.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Map.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Marshal.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Marshal.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__MoreLabels.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__MoreLabels.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Mutex.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Mutex.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Nativeint.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Nativeint.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Obj.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Obj.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Oo.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Oo.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Option.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Option.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Out_channel.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Out_channel.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Parsing.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Parsing.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Pervasives.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Pervasives.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Printexc.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Printexc.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Printf.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Printf.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Queue.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Queue.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Random.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Random.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Result.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Result.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Scanf.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Scanf.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Semaphore.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Semaphore.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Seq.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Seq.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Set.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Set.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Stack.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Stack.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__StdLabels.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__StdLabels.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Stream.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Stream.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__String.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__String.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__StringLabels.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__StringLabels.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Sys.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Sys.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Type.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Type.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Uchar.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Uchar.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Unit.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Unit.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/stdlib__Weak.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/stdlib__Weak.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/str.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/str.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/thread.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/thread.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/topdirs.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/topdirs.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/unix.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/unix.cmi -------------------------------------------------------------------------------- /src/worker/static/stdlib/unixLabels.cmi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voodoos/merlin-js/a4f3a7fd5418ee4b0bdc408bd8741d0d9d6cc6a5/src/worker/static/stdlib/unixLabels.cmi -------------------------------------------------------------------------------- /src/worker/stubs.js: -------------------------------------------------------------------------------- 1 | //Provides: caml_unix_times 2 | function caml_unix_times() { 3 | return 4.2 4 | } 5 | -------------------------------------------------------------------------------- /src/worker/worker.ml: -------------------------------------------------------------------------------- 1 | open Merlin_utils 2 | open Std 3 | open Merlin_kernel 4 | module Location = Ocaml_parsing.Location 5 | 6 | let sync_get url = 7 | let open Js_of_ocaml in 8 | let x = XmlHttpRequest.create () in 9 | x##.responseType := Js.string "arraybuffer"; 10 | x##_open (Js.string "GET") (Js.string url) Js._false; 11 | x##send Js.null; 12 | match x##.status with 13 | | 200 -> 14 | Js.Opt.case 15 | (File.CoerceTo.arrayBuffer x##.response) 16 | (fun () -> 17 | Firebug.console##log (Js.string "Failed to receive file"); 18 | None) 19 | (fun b -> Some (Typed_array.String.of_arrayBuffer b)) 20 | | _ -> None 21 | 22 | let filename_of_module unit_name = 23 | Printf.sprintf "%s.cmi" (String.uncapitalize_ascii unit_name) 24 | 25 | let reset_dirs () = 26 | Ocaml_utils.Directory_content_cache.clear (); 27 | let open Ocaml_utils.Load_path in 28 | let { visible; hidden } = get_paths () in 29 | reset (); 30 | init ~auto_include:no_auto_include ~visible ~hidden 31 | 32 | let add_dynamic_cmis dcs = 33 | let open Ocaml_typing.Persistent_env.Persistent_signature in 34 | let old_loader = !load in 35 | 36 | let fetch = 37 | (fun filename -> 38 | let open Option.Infix in 39 | let url = Filename.concat dcs.Protocol.dcs_url filename in 40 | sync_get url) 41 | in 42 | 43 | List.iter ~f:(fun name -> 44 | let filename = filename_of_module name in 45 | match fetch (filename_of_module name) with 46 | | Some content -> 47 | let name = Filename.(concat "/static/stdlib" filename) in 48 | Js_of_ocaml.Sys_js.create_file ~name ~content 49 | | None -> ()) dcs.dcs_toplevel_modules; 50 | 51 | let new_load ~allow_hidden ~unit_name = 52 | let filename = filename_of_module unit_name in 53 | let fs_name = Filename.(concat "/static/stdlib" filename) in 54 | (* Check if it's already been downloaded. This will be the 55 | case for all toplevel cmis. Also check whether we're supposed 56 | to handle this cmi *) 57 | if 58 | not (Sys.file_exists fs_name) && 59 | List.exists ~f:(fun prefix -> 60 | String.starts_with ~prefix filename) dcs.dcs_file_prefixes 61 | then begin 62 | match fetch filename with 63 | | Some x -> 64 | Js_of_ocaml.Sys_js.create_file ~name:fs_name ~content:x; 65 | (* At this point we need to tell merlin that the dir contents 66 | have changed *) 67 | reset_dirs () 68 | | None -> 69 | Printf.eprintf "Warning: Expected to find cmi at: %s\n%!" 70 | (Filename.concat dcs.Protocol.dcs_url filename) 71 | end; 72 | old_loader ~allow_hidden ~unit_name 73 | in 74 | load := new_load 75 | 76 | let add_cmis { Protocol.static_cmis; dynamic_cmis } = 77 | List.iter static_cmis ~f:(fun { Protocol.sc_name; sc_content } -> 78 | let filename = Printf.sprintf "%s.cmi" (String.uncapitalize_ascii sc_name) in 79 | let name = Filename.(concat "/static/stdlib" filename) in 80 | Js_of_ocaml.Sys_js.create_file ~name ~content:sc_content); 81 | Option.iter ~f:add_dynamic_cmis dynamic_cmis; 82 | Protocol.Added_cmis 83 | 84 | let config = 85 | let initial = Mconfig.initial in 86 | { initial with 87 | merlin = { initial.merlin with 88 | stdlib = Some "/static/stdlib" }} 89 | 90 | let make_pipeline source = 91 | Mpipeline.make config source 92 | 93 | let dispatch source query = 94 | let pipeline = make_pipeline source in 95 | Mpipeline.with_pipeline pipeline @@ fun () -> ( 96 | Query_commands.dispatch pipeline query 97 | ) 98 | 99 | module Completion = struct 100 | (* Prefixing code from ocaml-lsp-server *) 101 | let rfindi = 102 | let rec loop s ~f i = 103 | if i < 0 then 104 | None 105 | else if f (String.unsafe_get s i) then 106 | Some i 107 | else 108 | loop s ~f (i - 1) 109 | in 110 | fun ?from s ~f -> 111 | let from = 112 | let len = String.length s in 113 | match from with 114 | | None -> len - 1 115 | | Some i -> 116 | if i > len - 1 then 117 | raise @@ Invalid_argument "rfindi: invalid from" 118 | else 119 | i 120 | in 121 | loop s ~f from 122 | let lsplit2 s ~on = 123 | match String.index_opt s on with 124 | | None -> None 125 | | Some i -> 126 | let open String in 127 | Some (sub s ~pos:0 ~len:i, sub s ~pos:(i + 1) ~len:(length s - i - 1)) 128 | 129 | (** @see