Skip to content

Commit e4016bf

Browse files
committed
fix: block on parse error
We create a Block type in the scheduler (and its corresponding PBlock in execution manager) which will send an exec_error if one tries to execute through a parse error. If the user has set block_on_error mode then the behaviour is now identical with parsing errors and execution errors.
1 parent 3723aa5 commit e4016bf

File tree

6 files changed

+45
-23
lines changed

6 files changed

+45
-23
lines changed

language-server/dm/document.ml

+19-16
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type comment = {
5959
type parsing_error = {
6060
start: int;
6161
stop: int;
62-
msg: string Loc.located;
62+
msg: Pp.t Loc.located;
6363
qf: Quickfix.t list option;
6464
}
6565

@@ -248,7 +248,8 @@ let add_sentence parsed parsing_start start stop (ast: sentence_state) synterp_s
248248
let id = Stateid.fresh () in
249249
let scheduler_state_after, schedule =
250250
match ast with
251-
| Error _ -> scheduler_state_before, parsed.schedule (* If the sentence has a parsing error we do not schedule it *)
251+
| Error {msg} ->
252+
scheduler_state_before, Scheduler.schedule_errored_sentence id msg parsed.schedule
252253
| Parsed ast ->
253254
let ast' = (ast.ast, ast.classification, synterp_state) in
254255
Scheduler.schedule_sentence (id, ast') scheduler_state_before parsed.schedule
@@ -397,7 +398,8 @@ let patch_sentence parsed scheduler_state_before id ({ parsing_start; ast; start
397398
log @@ Format.sprintf "Patching sentence %s , %s" (Stateid.to_string id) (string_of_parsed_ast old_sentence.ast);
398399
let scheduler_state_after, schedule =
399400
match ast with
400-
| Error _ -> scheduler_state_before, parsed.schedule
401+
| Error {msg} ->
402+
scheduler_state_before, Scheduler.schedule_errored_sentence id msg parsed.schedule
401403
| Parsed ast ->
402404
let ast = (ast.ast, ast.classification, synterp_state) in
403405
Scheduler.schedule_sentence (id,ast) scheduler_state_before parsed.schedule
@@ -531,11 +533,10 @@ let get_entry ast =
531533
[%%endif]
532534

533535

534-
let handle_parse_error start parsing_start msg qf ({stream; errors; parsed} as parse_state) =
536+
let handle_parse_error start parsing_start msg qf ({stream; errors; parsed;} as parse_state) synterp_state =
535537
log @@ "handling parse error at " ^ string_of_int start;
536538
let stop = Stream.count stream in
537539
let parsing_error = { msg; start; stop; qf} in
538-
let synterp_state = Vernacstate.Synterp.freeze () in
539540
let sentence = { parsing_start; ast = Error parsing_error; start; stop; synterp_state } in
540541
let parsed = sentence :: parsed in
541542
let errors = parsing_error :: errors in
@@ -579,24 +580,26 @@ let handle_parse_more ({loc; synterp_state; stream; raw; parsed; parsed_comments
579580
let e, info = Exninfo.capture exn in
580581
let loc = get_loc_from_info_or_exn e info in
581582
let qf = Result.value ~default:[] @@ Quickfix.from_exception e in
582-
handle_parse_error start begin_char (loc, Pp.string_of_ppcmds @@ CErrors.iprint_no_report (e,info)) (Some qf) parse_state
583+
handle_parse_error start begin_char (loc, CErrors.iprint_no_report (e,info)) (Some qf) parse_state synterp_state
583584
end
584-
| exception (E msg as exn) ->
585-
let loc = Loc.get_loc @@ Exninfo.info exn in
586-
let qf = Result.value ~default:[] @@ Quickfix.from_exception exn in
585+
| exception (E _ as exn) ->
586+
let e, info = Exninfo.capture exn in
587+
let loc = get_loc_from_info_or_exn e info in
588+
let qf = Result.value ~default:[] @@ Quickfix.from_exception e in
587589
junk_sentence_end stream;
588-
handle_parse_error start start (loc,msg) (Some qf) {parse_state with stream}
589-
| exception (CLexer.Error.E e as exn) -> (* May be more problematic to handle for the diff *)
590-
let loc = Loc.get_loc @@ Exninfo.info exn in
590+
handle_parse_error start start (loc, CErrors.iprint_no_report (e, info)) (Some qf) {parse_state with stream} synterp_state
591+
| exception (CLexer.Error.E _ as exn) -> (* May be more problematic to handle for the diff *)
592+
let e, info = Exninfo.capture exn in
593+
let loc = get_loc_from_info_or_exn e info in
591594
let qf = Result.value ~default:[] @@ Quickfix.from_exception exn in
592595
junk_sentence_end stream;
593-
handle_parse_error start start (loc,CLexer.Error.to_string e) (Some qf) {parse_state with stream}
596+
handle_parse_error start start (loc,CErrors.iprint_no_report (e, info)) (Some qf) {parse_state with stream} synterp_state
594597
| exception exn ->
595598
let e, info = Exninfo.capture exn in
596599
let loc = Loc.get_loc @@ info in
597600
let qf = Result.value ~default:[] @@ Quickfix.from_exception exn in
598601
junk_sentence_end stream;
599-
handle_parse_error start start (loc, "Unexpected parse error: " ^ Pp.string_of_ppcmds @@ CErrors.iprint_no_report (e,info)) (Some qf) {parse_state with stream}
602+
handle_parse_error start start (loc, CErrors.iprint_no_report (e,info)) (Some qf) {parse_state with stream} synterp_state
600603
end
601604

602605
let rec unchanged_id id = function
@@ -726,9 +729,9 @@ module Internal = struct
726729
sentence.stop
727730

728731
let string_of_error error =
729-
let (_, str) = error.msg in
732+
let (_, pp) = error.msg in
730733
Format.sprintf "[parsing error] [%s] (%i -> %i)"
731-
str
734+
(Pp.string_of_ppcmds pp)
732735
error.start
733736
error.stop
734737

language-server/dm/document.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ type parsed_ast = {
8484
type parsing_error = {
8585
start: int;
8686
stop: int;
87-
msg: string Loc.located;
87+
msg: Pp.t Loc.located;
8888
qf: Quickfix.t list option;
8989
}
9090

language-server/dm/documentManager.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ let mk_parsing_error_diag st Document.{ msg = (oloc,msg); start; stop; qf } =
226226
in
227227
Some code
228228
in
229-
make_diagnostic st.document range oloc msg severity code
229+
make_diagnostic st.document range oloc (Pp.string_of_ppcmds msg) severity code
230230

231231
let all_diagnostics st =
232232
let parse_errors = Document.parse_errors st.document in

language-server/dm/executionManager.ml

+14-5
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ type delegated_task = {
7878

7979
type prepared_task =
8080
| PSkip of { id: sentence_id; error: Pp.t option }
81+
| PBlock of { id: sentence_id; error: Pp.t Loc.located }
8182
| PExec of executable_sentence
8283
| PQuery of executable_sentence
8384
| PDelegate of delegated_task
@@ -268,7 +269,7 @@ let interp_qed_delayed ~proof_using ~state_id ~st =
268269
let cut_overview task state document =
269270
let range = match task with
270271
| PDelegate { terminator_id } -> Document.range_of_id_with_blank_space document terminator_id
271-
| PSkip { id } | PExec { id } | PQuery { id } ->
272+
| PSkip { id } | PExec { id } | PQuery { id } | PBlock { id } ->
272273
Document.range_of_id_with_blank_space document id
273274
in
274275
let {prepared; processing; processed} = state.overview in
@@ -325,7 +326,7 @@ let update_processing task state document =
325326
let prepared = RangeList.remove_or_truncate_range range prepared in
326327
let overview = {state.overview with prepared; processing} in
327328
{state with overview}
328-
| PSkip { id } | PExec { id } | PQuery { id } ->
329+
| PSkip { id } | PExec { id } | PQuery { id } | PBlock { id } ->
329330
let range = Document.range_of_id_with_blank_space document id in
330331
let processing = RangeList.insert_or_merge_range range processing in
331332
let prepared = RangeList.remove_or_truncate_range range prepared in
@@ -345,7 +346,7 @@ let update_prepared task document state =
345346
let prepared = List.append prepared [ range ] in
346347
let overview = {state.overview with prepared} in
347348
{state with overview}
348-
| PSkip { id } | PExec { id } | PQuery { id } ->
349+
| PSkip { id } | PExec { id } | PQuery { id } | PBlock { id } ->
349350
let range = Document.range_of_id_with_blank_space document id in
350351
let prepared = RangeList.insert_or_merge_range range prepared in
351352
let overview = {state.overview with prepared} in
@@ -361,7 +362,7 @@ let update_overview task state document =
361362
let overview = update_processed_as_Done (Success None) range state.overview in
362363
let overview = {overview with prepared} in
363364
{state with overview}
364-
| PSkip { id } | PExec { id } | PQuery { id } ->
365+
| PSkip { id } | PExec { id } | PQuery { id } | PBlock { id } ->
365366
update_processed id state document
366367
in
367368
match state.todo with
@@ -507,6 +508,7 @@ let last_opt l = try Some (CList.last l).id with Failure _ -> None
507508
let prepare_task task : prepared_task list =
508509
match task with
509510
| Skip { id; error } -> [PSkip { id; error }]
511+
| Block { id; error } -> [PBlock {id; error}]
510512
| Exec e -> [PExec e]
511513
| Query e -> [PQuery e]
512514
| OpaqueProof { terminator; opener_id; tasks; proof_using} ->
@@ -524,6 +526,7 @@ let prepare_task task : prepared_task list =
524526

525527
let id_of_prepared_task = function
526528
| PSkip { id } -> id
529+
| PBlock { id } -> id
527530
| PExec ex -> ex.id
528531
| PQuery ex -> ex.id
529532
| PDelegate { terminator_id } -> terminator_id
@@ -582,6 +585,12 @@ let execute_task st (vs, events, interrupted) task =
582585
end else
583586
try
584587
match task with
588+
| PBlock { id; error = err} ->
589+
let (loc, pp) = err in
590+
let v = error None None pp vs in
591+
let parse_error = Some (id, loc) in
592+
let st = update st id v in
593+
(st, vs, events, false, parse_error)
585594
| PSkip { id; error = err } ->
586595
let v = match err with
587596
| None -> success vs
@@ -804,7 +813,7 @@ let invalidate1 of_sentence id =
804813

805814
let cancel1 todo invalid_id =
806815
let task_of_id = function
807-
| PSkip { id } | PExec { id } | PQuery { id } -> Stateid.equal id invalid_id
816+
| PSkip { id } | PExec { id } | PQuery { id } | PBlock { id } -> Stateid.equal id invalid_id
808817
| PDelegate _ -> false
809818
in
810819
List.filter task_of_id todo

language-server/dm/scheduler.ml

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type executable_sentence = {
3232

3333
type task =
3434
| Skip of { id: sentence_id; error: Pp.t option }
35+
| Block of { id: sentence_id; error: Pp.t Loc.located }
3536
| Exec of executable_sentence
3637
| OpaqueProof of { terminator: executable_sentence;
3738
opener_id: sentence_id;
@@ -214,13 +215,19 @@ let string_of_task (task_id,(base_id,task)) =
214215
| Exec { id } -> Format.sprintf "Exec %s" (Stateid.to_string id)
215216
| OpaqueProof { terminator; tasks } -> Format.sprintf "OpaqueProof [%s | %s]" (Stateid.to_string terminator.id) (String.concat "," (List.map (fun task -> Stateid.to_string task.id) tasks))
216217
| Query { id } -> Format.sprintf "Query %s" (Stateid.to_string id)
218+
| Block { id } -> Format.sprintf "Block %s" (Stateid.to_string id)
217219
in
218220
Format.sprintf "[%s] : [%s] -> %s" (Stateid.to_string task_id) (Option.cata Stateid.to_string "init" base_id) s
219221

220222
let _string_of_state st =
221223
let scopes = (List.map (fun b -> List.map (fun x -> x.id) b.proof_sentences) st.proof_blocks) @ [st.document_scope] in
222224
String.concat "|" (List.map (fun l -> String.concat " " (List.map Stateid.to_string l)) scopes)
223225

226+
let schedule_errored_sentence id error schedule =
227+
let task = Block {id; error} in
228+
let tasks = SM.add id (None, task) schedule.tasks in
229+
{schedule with tasks}
230+
224231
let schedule_sentence (id, (ast, classif, synterp_st)) st schedule =
225232
let base, st, task =
226233
let open Vernacexpr in

language-server/dm/scheduler.mli

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type executable_sentence = {
3737

3838
type task =
3939
| Skip of { id: sentence_id; error: Pp.t option }
40+
| Block of { id: sentence_id; error: Pp.t Loc.located }
4041
| Exec of executable_sentence
4142
| OpaqueProof of { terminator: executable_sentence;
4243
opener_id: sentence_id;
@@ -51,6 +52,8 @@ type schedule
5152

5253
val initial_schedule : schedule
5354

55+
val schedule_errored_sentence : sentence_id -> Pp.t Loc.located -> schedule -> schedule
56+
5457
val schedule_sentence : sentence_id * (Synterp.vernac_control_entry * Vernacextend.vernac_classification * Vernacstate.Synterp.t) -> state -> schedule -> state * schedule
5558
(** Identifies the structure of the document and dependencies between sentences
5659
in order to easily compute the tasks to interpret the a sentence.

0 commit comments

Comments
 (0)