Source file queryManager.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
[%%import "vsrocq_config.mlh"]
open Protocol.LspWrapper
open Protocol.Printing
open Types
let Log log = Log.mk_log "queryManager"
let context_of_vernac_state (st : Vernacstate.t) =
let st = st.Vernacstate.interp in
Vernacstate.Interp.unfreeze_interp_state st;
begin match st.lemmas with
| None ->
let env = Global.env () in
let sigma = Evd.from_env env in
sigma, env
| Some lemmas ->
let open Declare in
let open Vernacstate in
lemmas |> LemmaStack.with_top ~f:Proof.get_current_context
end
[%%if rocq ="8.18" || rocq ="8.19"]
[%%elif rocq ="8.20"]
let parsable_make = Pcoq.Parsable.make
let unfreeze = Pcoq.unfreeze
let entry_parse = Pcoq.Entry.parse
[%%else]
let parsable_make = Procq.Parsable.make
let unfreeze = Procq.unfreeze
let entry_parse = Procq.Entry.parse
[%%endif]
[%%if rocq ="8.18" || rocq ="8.19"]
let parse_entry st entry pattern =
let pa = Pcoq.Parsable.make (Gramlib.Stream.of_string pattern) in
Vernacstate.Parser.parse (Utilities.vernacstate_synterp_parsing st) entry pa
[%%else]
let parse_entry st entry pattern =
let pa = parsable_make (Gramlib.Stream.of_string pattern) in
unfreeze (Utilities.vernacstate_synterp_parsing st);
entry_parse entry pa
[%%endif]
[%%if rocq ="8.18" || rocq ="8.19" || rocq ="8.20"]
let smart_global = Pcoq.Prim.smart_global
[%%else]
let smart_global = Procq.Prim.smart_global
[%%endif]
[%%if rocq ="8.18" || rocq ="8.19" || rocq ="8.20"]
let lconstr = Pcoq.Constr.lconstr
[%%else]
let lconstr = Procq.Constr.lconstr
[%%endif]
[%%if rocq ="8.18" || rocq ="8.19"]
let print_located_qualid _ qid = Prettyp.print_located_qualid qid
[%%else]
let print_located_qualid = Prettyp.print_located_qualid
[%%endif]
[%%if rocq ="8.18" || rocq ="8.19" || rocq = "8.20" || rocq = "9.0" || rocq = "9.1"]
let pr_glob_without_symbols env sigma c =
Constrextern.without_symbols (Printer.pr_glob_constr_env env sigma) c
[%%else]
let pr_glob_without_symbols env sigma c =
let flags = PrintingFlags.Extern.current() in
let flags = { flags with notations = false } in
Printer.pr_glob_constr_env ~flags env sigma c
[%%endif]
[%%if rocq ="8.18" || rocq ="8.19"]
let print_name = Prettyp.print_name
[%%else]
let print_name =
let access = Library.indirect_accessor[@@warning "-3"] in
Prettyp.print_name access
[%%endif]
let about vs ~pattern =
let sigma, env = context_of_vernac_state vs in
try
let ref_or_by_not = parse_entry vs (smart_global) pattern in
let udecl = None in
Ok (pp_of_rocqpp @@ Prettyp.print_about env sigma ref_or_by_not udecl)
with e ->
let e, info = Exninfo.capture e in
let message = Pp.string_of_ppcmds @@ CErrors.iprint (e, info) in
Error ({message; code=None})
(** Try to generate hover text from [pattern] the context of the given [sentence] *)
let hover_of_sentence pattern = function
| None -> None
| Some sentence ->
match Utilities.get_vernac_state sentence.Document.checked with
| None -> None
| Some vs ->
let sigma, env = context_of_vernac_state vs in
try
let ref_or_by_not = parse_entry vs (smart_global) pattern in
Language.Hover.get_hover_contents env sigma ref_or_by_not
with e ->
let e, info = Exninfo.capture e in
log (fun () -> "Exception while handling hover: " ^ (Pp.string_of_ppcmds @@ CErrors.iprint (e, info)));
None
let hover document pos =
let raw = Document.raw_document document in
let loc = RawDocument.loc_of_position raw pos in
let opattern = RawDocument.word_at_loc raw loc in
let osentence = Document.find_sentence document loc in
let otoken = Option.bind osentence (fun s -> Document.token_at_loc s loc) in
match opattern, otoken with
| None, _ | _, None | _, Some (Tok.STRING _) -> log (fun () -> "hover: no hoverable item found at cursor"); None
| Some pattern, _ ->
log (fun () -> "hover: found word at cursor: \"" ^ pattern ^ "\"");
match hover_of_sentence pattern (Document.find_sentence_before_pos document pos) with
| Some _ as x -> x
| None ->
match Document.find_sentence_after_pos document pos with
| None -> None
| Some sentence as opt ->
match hover_of_sentence pattern opt with
| Some _ as x -> x
| None ->
match sentence.ast with
| Error _ -> None
| Parsed ast ->
match ast.classification with
| VtProofStep _ | VtStartProof _ ->
hover_of_sentence pattern (Document.find_next_qed_pos document pos)
| _ -> None
let find_all_ident (tokens: (Loc.t * Tok.t) list) (ident: string) : Loc.t list =
List.filter_map (fun (loc, tok) ->
match tok with
| Tok.IDENT s
| Tok.FIELD s when s = ident -> Some loc
| _ -> None) tokens
let highlight document pos =
let raw = Document.raw_document document in
let loc = RawDocument.loc_of_position raw pos in
let osentence = Document.find_sentence document loc in
let otoken = Option.bind osentence (fun s -> Document.token_at_loc s loc) in
match otoken with
| None -> log (fun () -> "highlight: no item found at cursor"); []
| Some (Tok.IDENT pattern) | Some (Tok.FIELD pattern) ->
log (fun () -> "highlight: found token at cursor: \"" ^ pattern ^ "\"");
let sentences = Document.sentences document in
let tokens = List.concat_map Document.tokens_of_sentence sentences in
let locs = find_all_ident tokens pattern in
List.map (RawDocument.range_of_loc raw) locs
| Some token -> log (fun () -> "highlight: token at cursor is not an identifier: " ^ Tok.extract_string false token); []
[%%if rocq ="8.18" || rocq ="8.19" || rocq ="8.20"]
let jump_to_definition _ _ _ = None
[%%else]
let jump_to_definition document vs pos =
let _side_effect_needed_ = context_of_vernac_state vs in
let raw = Document.raw_document document in
let loc = RawDocument.loc_of_position raw pos in
let opattern = RawDocument.word_at_loc raw loc in
let osentence = Document.find_sentence document loc in
let otoken = Option.bind osentence (fun s -> Document.token_at_loc s loc) in
match opattern, otoken with
| None, _ | _, None | _, Some (Tok.STRING _) -> log (fun () -> "jumpToDef: no jumpable item found at cursor"); None
| Some pattern, _ ->
log (fun () -> "jumpToDef: found word at cursor: \"" ^ pattern ^ "\"");
try
let qid = parse_entry vs (Procq.Prim.qualid) pattern in
let ref = Nametab.locate_extended qid in
match Nametab.cci_src_loc ref with
| None -> None
| Some loc ->
begin match loc.Loc.fname with
| Loc.ToplevelInput | InFile { dirpath = None } -> None
| InFile { dirpath = Some dp } ->
let f = Loadpath.locate_absolute_library @@ Libnames.dirpath_of_string dp in
begin match f with
| Ok f ->
let f = Filename.remove_extension f ^ ".v" in
(if Sys.file_exists f then
let b_pos = Position.create ~character:(loc.bp - loc.bol_pos) ~line:(loc.line_nb - 1) in
let e_pos = Position.create ~character:(loc.ep - loc.bol_pos) ~line:(loc.line_nb - 1) in
let range = Range.create ~end_:b_pos ~start:e_pos in
Some (range, f)
else
None
)
| Error _ -> None
end
end
with e ->
let e, info = Exninfo.capture e in
log (fun () -> Pp.string_of_ppcmds @@ CErrors.iprint (e, info)); None
[%%endif]
let check ~vs ~pattern =
let sigma, env = context_of_vernac_state vs in
let rc = parse_entry vs lconstr pattern in
try
let redexpr = None in
Ok (pp_of_rocqpp @@ Vernacentries.check_may_eval env sigma redexpr rc)
with e ->
let e, info = Exninfo.capture e in
let message = Pp.string_of_ppcmds @@ CErrors.iprint (e, info) in
Error ({message; code=None})
let locate ~vs ~pattern =
let sigma, env = context_of_vernac_state vs in
match parse_entry vs (smart_global) pattern with
| { v = AN qid } -> Ok (pp_of_rocqpp @@ print_located_qualid env qid)
| { v = ByNotation (ntn, sc)} ->
Ok( pp_of_rocqpp @@ Notation.locate_notation
(pr_glob_without_symbols env sigma) ntn sc)
let search ~vs ~id pattern =
let sigma, env = context_of_vernac_state vs in
let query, r = parse_entry vs (G_vernac.search_queries) pattern in
SearchQuery.interp_search ~id env sigma query r
let print ~vs ~pattern =
let sigma, env = context_of_vernac_state vs in
let qid = parse_entry vs (smart_global) pattern in
let udecl = None in
Ok (pp_of_rocqpp @@ print_name env sigma qid udecl)
let get_completions ~vs =
let settings = ExecutionManager.get_options () in
match CompletionSuggester.get_completions settings.completion_options vs with
| None ->
log (fun () -> "No completions available");
[]
| Some lemmas -> lemmas
let to_types_error = function
| Terminated (Ok x) -> Ok x
| Terminated (Error x) -> (Error x)
| Interrupted -> Error ({message = "Interrupted"; code=None})
| Aborted message ->
let message = Pp.string_of_ppcmds message in
Error ({message; code=None})
let to_list = function
| Terminated x -> x
| Aborted _ | Interrupted -> []
let to_option = function
| Terminated x -> Some x
| Aborted _ | Interrupted -> None
let timeout = 0.2
let check ~doc_id ~vs ~pattern =
ProverThread.try_run ~doc_id ~name:"check" ~timeout (fun () -> check ~vs ~pattern) |>
to_types_error
let jump_to_definition document vs pos =
ProverThread.try_run ~doc_id:(Document.id document) ~name:"jump_to_definition" ~timeout
(fun () -> jump_to_definition document vs pos) |>
to_option |> Option.flatten
let locate ~doc_id ~vs ~pattern =
ProverThread.try_run ~doc_id ~name:"locate" ~timeout (fun () -> locate ~vs ~pattern) |>
to_types_error
let search ~doc_id ~vs ~id pattern =
ProverThread.try_run ~doc_id ~name:"search" ~timeout:0.5 (fun () -> search ~vs ~id pattern) |>
to_list
let print ~doc_id ~vs ~pattern =
ProverThread.try_run ~doc_id ~name:"print" ~timeout (fun () -> print ~vs ~pattern) |>
to_types_error
let hover document pos =
ProverThread.try_run ~doc_id:(Document.id document) ~name:"hover" ~timeout
(fun () -> hover document pos) |>
to_option |> Option.flatten
let highlight document pos =
ProverThread.try_run ~doc_id:(Document.id document) ~name:"highlight" ~timeout
(fun () -> highlight document pos) |> to_list
let about ~doc_id ~vs ~pattern =
ProverThread.try_run ~doc_id ~name:"about" ~timeout (fun () -> about vs ~pattern) |>
to_types_error
let get_completions ~doc_id ~vs =
ProverThread.try_run ~doc_id ~name:"get_completions" ~timeout:0.5 (fun () -> get_completions ~vs) |>
to_list