@@ -86,36 +86,6 @@ module Syntax = struct
86
86
| None -> Text_document. documentUri td |> Uri. to_path |> of_fname
87
87
end
88
88
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
-
119
89
let await task =
120
90
let * cancel_token = Server. cancel_token () in
121
91
let f () = Lev_fiber.Thread. await task in
@@ -146,40 +116,112 @@ let await task =
146
116
in
147
117
raise (Jsonrpc.Response.Error. E e))
148
118
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
150
123
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
161
174
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
166
179
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 =
168
212
let + timer = Lev_fiber.Timer.Wheel. task wheel in
169
213
let merlin_config =
170
214
let uri = Text_document. documentUri tdoc in
171
215
Merlin_config.DB. get merlin_db uri
172
216
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 }
176
218
177
- let make wheel config ~ merlin_thread (doc : DidOpenTextDocumentParams.t ) =
219
+ let make wheel config pipeline (doc : DidOpenTextDocumentParams.t ) =
178
220
Fiber. of_thunk (fun () ->
179
221
let tdoc = Text_document. make doc in
180
222
let syntax = Syntax. of_text_document tdoc in
181
223
match syntax with
182
- | Ocaml | Reason -> make_merlin wheel config ~merlin_thread tdoc syntax
224
+ | Ocaml | Reason -> make_merlin wheel config pipeline tdoc syntax
183
225
| Ocamllex | Menhir | Cram | Dune -> Fiber. return (Other { tdoc; syntax }))
184
226
185
227
let update_text ?version t changes =
@@ -200,9 +242,7 @@ let update_text ?version t changes =
200
242
| tdoc -> (
201
243
match t with
202
244
| 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 })
206
246
207
247
module Merlin = struct
208
248
type t = merlin
@@ -216,35 +256,7 @@ module Merlin = struct
216
256
let kind t = Kind. of_fname (Uri. to_path (uri (Merlin t)))
217
257
218
258
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
248
260
249
261
let with_pipeline_exn doc f =
250
262
let + res = with_pipeline doc f in
0 commit comments