@@ -86,36 +86,6 @@ module Syntax = struct
8686 | None -> Text_document. documentUri td |> Uri. to_path |> of_fname
8787end
8888
89- type merlin =
90- { tdoc : Text_document .t
91- ; pipeline : Mpipeline .t Lazy_fiber .t
92- ; merlin : Lev_fiber.Thread .t
93- ; timer : Lev_fiber.Timer.Wheel .task
94- ; merlin_config : Merlin_config .t
95- ; syntax : Syntax .t
96- }
97-
98- type t =
99- | Other of
100- { tdoc : Text_document .t
101- ; syntax : Syntax .t
102- }
103- | Merlin of merlin
104-
105- let tdoc = function
106- | Other d -> d.tdoc
107- | Merlin m -> m.tdoc
108-
109- let uri t = Text_document. documentUri (tdoc t)
110-
111- let syntax = function
112- | Merlin m -> m.syntax
113- | Other t -> t.syntax
114-
115- let text t = Text_document. text (tdoc t)
116-
117- let source t = Msource. make (text t)
118-
11989let await task =
12090 let * cancel_token = Server. cancel_token () in
12191 let f () = Lev_fiber.Thread. await task in
@@ -146,40 +116,112 @@ let await task =
146116 in
147117 raise (Jsonrpc.Response.Error. E e))
148118
149- let version t = Text_document. version (tdoc t)
119+ module Single_pipeline : sig
120+ type t
121+
122+ val create : Lev_fiber.Thread .t -> t
150123
151- let make_pipeline merlin_config thread tdoc =
152- Lazy_fiber. create (fun () ->
153- let * config = Merlin_config. config merlin_config in
154- let * async_make_pipeline =
155- match
156- Lev_fiber.Thread. task thread ~f: (fun () ->
157- Text_document. text tdoc |> Msource. make |> Mpipeline. make config)
158- with
159- | Error `Stopped -> Fiber. never
160- | Ok task -> Fiber. return task
124+ val use :
125+ t
126+ -> doc :Text_document .t
127+ -> config :Merlin_config .t
128+ -> f :(Mpipeline .t -> 'a )
129+ -> ('a , Exn_with_backtrace .t ) result Fiber .t
130+ end = struct
131+ type t =
132+ { thread : Lev_fiber.Thread .t
133+ ; mutable last : (Text_document .t * Mconfig .t * Mpipeline .t ) option
134+ }
135+
136+ let create thread = { thread; last = None }
137+
138+ let use t ~doc ~config ~f =
139+ let * config = Merlin_config. config config in
140+ let make_pipeline =
141+ match t.last with
142+ | Some (doc' , config' , pipeline ) when doc' == doc && config == config' ->
143+ fun () -> pipeline
144+ | _ ->
145+ let source = Msource. make (Text_document. text doc) in
146+ fun () -> Mpipeline. make config source
147+ in
148+ let task =
149+ match
150+ Lev_fiber.Thread. task t.thread ~f: (fun () ->
151+ let start = Unix. time () in
152+ let pipeline = make_pipeline () in
153+ let res = Mpipeline. with_pipeline pipeline (fun () -> f pipeline) in
154+ let stop = Unix. time () in
155+ (res, pipeline, start, stop))
156+ with
157+ | Error `Stopped -> assert false
158+ | Ok task -> task
159+ in
160+ let * res = await task in
161+ match res with
162+ | Error exn -> Fiber. return (Error exn )
163+ | Ok (res , pipeline , start , stop ) ->
164+ let event =
165+ let module Event = Chrome_trace. Event in
166+ let dur = Event.Timestamp. of_float_seconds (stop -. start) in
167+ let fields =
168+ Event. common_fields
169+ ~ts: (Event.Timestamp. of_float_seconds start)
170+ ~name: " merlin"
171+ ()
172+ in
173+ Event. complete ~dur fields
161174 in
162- let + res = await async_make_pipeline in
163- match res with
164- | Ok s -> s
165- | Error e -> Exn_with_backtrace. reraise e)
175+ t.last < - Some (doc, config, pipeline);
176+ let + () = Metrics. report event in
177+ Ok res
178+ end
166179
167- let make_merlin wheel merlin_db ~merlin_thread tdoc syntax =
180+ type merlin =
181+ { tdoc : Text_document .t
182+ ; pipeline : Single_pipeline .t
183+ ; timer : Lev_fiber.Timer.Wheel .task
184+ ; merlin_config : Merlin_config .t
185+ ; syntax : Syntax .t
186+ }
187+
188+ type t =
189+ | Other of
190+ { tdoc : Text_document .t
191+ ; syntax : Syntax .t
192+ }
193+ | Merlin of merlin
194+
195+ let tdoc = function
196+ | Other d -> d.tdoc
197+ | Merlin m -> m.tdoc
198+
199+ let uri t = Text_document. documentUri (tdoc t)
200+
201+ let syntax = function
202+ | Merlin m -> m.syntax
203+ | Other t -> t.syntax
204+
205+ let text t = Text_document. text (tdoc t)
206+
207+ let source t = Msource. make (text t)
208+
209+ let version t = Text_document. version (tdoc t)
210+
211+ let make_merlin wheel merlin_db pipeline tdoc syntax =
168212 let + timer = Lev_fiber.Timer.Wheel. task wheel in
169213 let merlin_config =
170214 let uri = Text_document. documentUri tdoc in
171215 Merlin_config.DB. get merlin_db uri
172216 in
173- let pipeline = make_pipeline merlin_config merlin_thread tdoc in
174- Merlin
175- { merlin_config; tdoc; pipeline; merlin = merlin_thread; timer; syntax }
217+ Merlin { merlin_config; tdoc; pipeline; timer; syntax }
176218
177- let make wheel config ~ merlin_thread (doc : DidOpenTextDocumentParams.t ) =
219+ let make wheel config pipeline (doc : DidOpenTextDocumentParams.t ) =
178220 Fiber. of_thunk (fun () ->
179221 let tdoc = Text_document. make doc in
180222 let syntax = Syntax. of_text_document tdoc in
181223 match syntax with
182- | Ocaml | Reason -> make_merlin wheel config ~merlin_thread tdoc syntax
224+ | Ocaml | Reason -> make_merlin wheel config pipeline tdoc syntax
183225 | Ocamllex | Menhir | Cram | Dune -> Fiber. return (Other { tdoc; syntax }))
184226
185227let update_text ?version t changes =
@@ -200,9 +242,7 @@ let update_text ?version t changes =
200242 | tdoc -> (
201243 match t with
202244 | Other o -> Other { o with tdoc }
203- | Merlin ({ merlin_config; merlin; _ } as t ) ->
204- let pipeline = make_pipeline merlin_config merlin tdoc in
205- Merlin { t with tdoc; pipeline })
245+ | Merlin t -> Merlin { t with tdoc })
206246
207247module Merlin = struct
208248 type t = merlin
@@ -216,35 +256,7 @@ module Merlin = struct
216256 let kind t = Kind. of_fname (Uri. to_path (uri (Merlin t)))
217257
218258 let with_pipeline (t : t ) f =
219- let * pipeline = Lazy_fiber. force t.pipeline in
220- let * task =
221- match
222- Lev_fiber.Thread. task t.merlin ~f: (fun () ->
223- let start = Unix. time () in
224- let res = Mpipeline. with_pipeline pipeline (fun () -> f pipeline) in
225- let stop = Unix. time () in
226- let event =
227- let module Event = Chrome_trace. Event in
228- let dur = Event.Timestamp. of_float_seconds (stop -. start) in
229- let fields =
230- Event. common_fields
231- ~ts: (Event.Timestamp. of_float_seconds start)
232- ~name: " merlin"
233- ()
234- in
235- Event. complete ~dur fields
236- in
237- (event, res))
238- with
239- | Error `Stopped -> Fiber. never
240- | Ok task -> Fiber. return task
241- in
242- let * res = await task in
243- match res with
244- | Ok (event , result ) ->
245- let + () = Metrics. report event in
246- Ok result
247- | Error e -> Fiber. return (Error e)
259+ Single_pipeline. use t.pipeline ~doc: t.tdoc ~config: t.merlin_config ~f
248260
249261 let with_pipeline_exn doc f =
250262 let + res = with_pipeline doc f in
0 commit comments