Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding option for interpreting to exact cursor position or next command during interpret to point #875

Merged
merged 4 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ After installation and activation of the extension:

#### Proof checking
* `"vscoq.proof.mode": Continuous | Manual` -- Decide whether documents should checked continuously or using the classic navigation commmands (defaults to `Manual`)
* `"vscoq.proof.pointInterpretationMode": Cursor | NextCommand` -- Determines the point to which the proof should be check to when using the 'Interpret to point' command.
* `"vscoq.proof.cursor.sticky": bool` -- a toggle to specify whether the cursor should move as Coq interactively navigates a document (step forward, backward, etc...)
* `"vscoq.proof.delegation": None | Skip | Delegate` -- Decides which delegation strategy should be used by the server.
`Skip` allows to skip proofs which are out of focus and should be used in manual mode. `Delegate` allocates a settable amount of workers
Expand Down
14 changes: 14 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@
"default": 0,
"description": "Configures the proof checking mode for Coq."
},
"vscoq.proof.pointInterpretationMode": {
"scope": "window",
"type": "number",
"enum": [
0,
1
],
"enumItemLabels": [
"Cursor",
"NextCommand"
],
"default": 0,
"description": "Determines the point to which the proof should be checked when using the `Interpret to point` command."
},
"vscoq.proof.cursor.sticky": {
"scope": "window",
"type": "boolean",
Expand Down
7 changes: 4 additions & 3 deletions client/src/manualChecking.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
TextEditor,
commands
commands,

Check warning on line 3 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / dev-setup-opam (ubuntu-latest, 4.14.x, fatalwarnings)

'commands' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 3 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, 8.18.0)

'commands' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 3 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / dev-setup-opam (ubuntu-latest, 4.14.x, dev)

'commands' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 3 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, 8.19.0)

'commands' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 3 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, 8.20+rc1)

'commands' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 3 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, dev)

'commands' is defined but never used. Allowed unused vars must match /^_/u
workspace

Check warning on line 4 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / dev-setup-opam (ubuntu-latest, 4.14.x, fatalwarnings)

'workspace' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 4 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, 8.18.0)

'workspace' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 4 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / dev-setup-opam (ubuntu-latest, 4.14.x, dev)

'workspace' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 4 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, 8.19.0)

'workspace' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 4 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, 8.20+rc1)

'workspace' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 4 in client/src/manualChecking.ts

View workflow job for this annotation

GitHub Actions / install-opam (ubuntu-latest, 4.14.x, dev)

'workspace' is defined but never used. Allowed unused vars must match /^_/u
} from 'vscode';

import {
Expand All @@ -13,10 +14,10 @@
import Client from './client';
import { makeVersionedDocumentId } from './utilities/utils';

export const sendInterpretToPoint = (editor: TextEditor, client: Client) => {
export const sendInterpretToPoint = (editor: TextEditor, client: Client) => {
const textDocument = makeVersionedDocumentId(editor);
const position = editor.selection.active;
client.sendNotification("vscoq/interpretToPoint", {textDocument: textDocument, position: position});
client.sendNotification("vscoq/interpretToPoint", {textDocument: textDocument, position: position });
};

export const sendInterpretToEnd = (editor: TextEditor, client: Client) => {
Expand Down
22 changes: 22 additions & 0 deletions language-server/dm/documentManager.ml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,20 @@ let id_of_pos st pos =
| None -> None
| Some { id } -> Some id

let id_of_sentence_after_pos st pos =
let loc = RawDocument.loc_of_position (Document.raw_document st.document) pos in
(* if the current loc falls squarely within a sentence *)
match Document.find_sentence st.document loc with
| Some { id } -> Some id
| None ->
(** otherwise the sentence start is after the loc,
so we must be in the whitespace before the sentence
and need to interpret to the sentence before instead
*)
match Document.find_sentence_before st.document loc with
| None -> None
| Some { id } -> Some id

let id_of_pos_opt st = function
| None -> begin match st.observe_id with None | Some Top -> None | Some Id id -> Some id end
| Some pos -> id_of_pos st pos
Expand Down Expand Up @@ -318,6 +332,14 @@ let interpret_to_position st pos ~should_block_on_error =
| None -> (st, [], None) (* document is empty *)
| Some id -> interpret_to st id ~should_block_on_error

let interpret_to_next_position st pos ~should_block_on_error =
match id_of_sentence_after_pos st pos with
| None -> (st, [], None, pos) (* document is empty *)
| Some id ->
let new_pos = (Document.range_of_id st.document id).end_ in
let (st, events, blocking_errs) = interpret_to st id ~should_block_on_error in
(st, events, blocking_errs, new_pos)

let get_next_range st pos =
match id_of_pos st pos with
| None -> None
Expand Down
9 changes: 6 additions & 3 deletions language-server/dm/documentManager.mli
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ val get_previous_range : state -> Position.t -> Range.t option
(** [get_previous_pos st pos] get the range of the previous sentence relative to pos *)

val interpret_to_position : state -> Position.t -> should_block_on_error:bool -> (state * events * blocking_error option)
(** [interpret_to_position stateful doc pos] navigates to the last sentence ending
before or at [pos] and returns the resulting state. The [stateful] flag
determines if we record the resulting position in the state. *)
(** [interpret_to_position state pos should_block] navigates to the
last sentence ending before or at [pos] and returns the resulting state, events that need to take place, and a possible blocking error. *)

val interpret_to_next_position : state -> Position.t -> should_block_on_error:bool -> (state * events * blocking_error option * Position.t)
(** [interpret_to_next_position state pos should_block] navigates
to the first sentence after or at [pos] (excluding whitespace) and returns the resulting state, events that need to take place, a possible blocking error, and the position of the sentence that was interpreted until. *)

val interpret_to_previous : state -> (state * events * blocking_error option)
(** [interpret_to_previous doc] navigates to the previous sentence in [doc]
Expand Down
17 changes: 17 additions & 0 deletions language-server/protocol/settings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ module Mode = struct

end

module PointInterpretationMode = struct
type t =
| Cursor
| NextCommand
[@@deriving yojson]

let yojson_of_t = function
| Cursor -> `Int 0
| NextCommand -> `Int 1

let t_of_yojson = function
| `Int 0 -> Cursor
| `Int 1 -> NextCommand
| _ -> Yojson.json_error @@ "invalid value "
end

module Memory = struct

type t = {
Expand All @@ -67,6 +83,7 @@ module Proof = struct
workers: int option;
mode: Mode.t;
block: bool;
pointInterpretationMode: PointInterpretationMode.t
} [@@deriving yojson] [@@yojson.allow_extra_fields]

end
Expand Down
44 changes: 27 additions & 17 deletions language-server/vscoqtop/lspManager.ml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ let max_memory_usage = ref 4000000000
let full_diagnostics = ref false
let full_messages = ref false

let point_interp_mode = ref Settings.PointInterpretationMode.Cursor

let block_on_first_error = ref true

let Dm.Types.Log log = Dm.Log.mk_log "lspManager"
Expand Down Expand Up @@ -130,7 +132,8 @@ let do_configuration settings =
full_diagnostics := settings.diagnostics.full;
full_messages := settings.goals.messages.full;
max_memory_usage := settings.memory.limit * 1000000000;
block_on_first_error := settings.proof.block
block_on_first_error := settings.proof.block;
point_interp_mode := settings.proof.pointInterpretationMode

let send_configuration_request () =
let id = `Int conf_request_id in
Expand Down Expand Up @@ -357,7 +360,7 @@ let textDocumentHover id params =

let progress_hook uri () =
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "ignoring non existant document"
| None -> log @@ "ignoring non existent document"
| Some { st } -> update_view uri st

let mk_proof_view_event uri position =
Expand All @@ -382,9 +385,16 @@ let coqtopInterpretToPoint params =
let Notification.Client.InterpretToPointParams.{ textDocument; position } = params in
let uri = textDocument.uri in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[interpretToPoint] ignoring event on non existant document"; []
| None -> log @@ "[interpretToPoint] ignoring event on non existent document"; []
| Some { st; visible } ->
let (st, events, error_range) = Dm.DocumentManager.interpret_to_position st position ~should_block_on_error:!block_on_first_error in
let (st, events, error_range, position) =
match !point_interp_mode with
| Settings.PointInterpretationMode.Cursor ->
let st, evs, blocking_err = Dm.DocumentManager.interpret_to_position st position ~should_block_on_error:!block_on_first_error in
(st, evs, blocking_err, position)
| Settings.PointInterpretationMode.NextCommand ->
Dm.DocumentManager.interpret_to_next_position st position ~should_block_on_error:!block_on_first_error
in
Durbatuluk1701 marked this conversation as resolved.
Show resolved Hide resolved
replace_state (DocumentUri.to_path uri) st visible;
update_view uri st;
let sel_events = inject_dm_events (uri, events) in
Expand All @@ -400,7 +410,7 @@ let coqtopInterpretToPoint params =
let coqtopStepBackward params =
let Notification.Client.StepBackwardParams.{ textDocument = { uri }; position } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log "[stepBackward] ignoring event on non existant document"; []
| None -> log "[stepBackward] ignoring event on non existent document"; []
| Some { st; visible } ->
if !check_mode = Settings.Mode.Continuous then
match position with
Expand All @@ -423,7 +433,7 @@ let coqtopStepBackward params =
let coqtopStepForward params =
let Notification.Client.StepForwardParams.{ textDocument = { uri }; position } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log "[stepForward] ignoring event on non existant document"; []
| None -> log "[stepForward] ignoring event on non existent document"; []
| Some { st; visible } ->
if !check_mode = Settings.Mode.Continuous then
match position with
Expand Down Expand Up @@ -463,7 +473,7 @@ let textDocumentCompletion id params =
else
let Lsp.Types.CompletionParams.{ textDocument = { uri }; position } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[textDocumentCompletion]ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[textDocumentCompletion]ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st } ->
match Dm.DocumentManager.get_completions st position with
| Ok completionItems ->
Expand All @@ -476,15 +486,15 @@ let textDocumentCompletion id params =
let documentSymbol id params =
let Lsp.Types.DocumentSymbolParams.{ textDocument = {uri}} = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[documentSymbol] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[documentSymbol] ignoring event on non existent document"; Error("Document does not exist"), []
| Some tab -> log @@ "[documentSymbol] getting symbols";
let symbols = Dm.DocumentManager.get_document_symbols tab.st in
Ok(Some (`DocumentSymbol symbols)), []

let coqtopResetCoq id params =
let Request.Client.ResetParams.{ textDocument = { uri } } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[resetCoq] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[resetCoq] ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st; visible } ->
let st, events = Dm.DocumentManager.reset st in
let (st, events') =
Expand All @@ -501,7 +511,7 @@ let coqtopResetCoq id params =
let coqtopInterpretToEnd params =
let Notification.Client.InterpretToEndParams.{ textDocument = { uri } } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[interpretToEnd] ignoring event on non existant document"; []
| None -> log @@ "[interpretToEnd] ignoring event on non existent document"; []
| Some { st; visible } ->
let (st, events, error_range) = Dm.DocumentManager.interpret_to_end st ~should_block_on_error:!block_on_first_error in
replace_state (DocumentUri.to_path uri) st visible;
Expand All @@ -515,32 +525,32 @@ let coqtopInterpretToEnd params =
let coqtopLocate id params =
let Request.Client.LocateParams.{ textDocument = { uri }; position; pattern } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[locate] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[locate] ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st } ->
Dm.DocumentManager.locate st position ~pattern, []

let coqtopPrint id params =
let Request.Client.PrintParams.{ textDocument = { uri }; position; pattern } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[print] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[print] ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st } -> Dm.DocumentManager.print st position ~pattern, []

let coqtopAbout id params =
let Request.Client.AboutParams.{ textDocument = { uri }; position; pattern } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[about] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[about] ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st } -> Dm.DocumentManager.about st position ~pattern, []

let coqtopCheck id params =
let Request.Client.CheckParams.{ textDocument = { uri }; position; pattern } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[check] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[check] ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st } -> Dm.DocumentManager.check st position ~pattern, []

let coqtopSearch id params =
let Request.Client.SearchParams.{ textDocument = { uri }; id; position; pattern } = params in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[search] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[search] ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st } ->
try
let notifications = Dm.DocumentManager.search st ~id position pattern in
Expand All @@ -554,7 +564,7 @@ let sendDocumentState id params =
let Request.Client.DocumentStateParams.{ textDocument } = params in
let uri = textDocument.uri in
match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "[documentState] ignoring event on non existant document"; Error("Document does not exist"), []
| None -> log @@ "[documentState] ignoring event on non existent document"; Error("Document does not exist"), []
| Some { st } -> let document = Dm.DocumentManager.Internal.string_of_state st in
Ok Request.Client.DocumentStateResult.{ document }, []

Expand Down Expand Up @@ -702,7 +712,7 @@ let handle_event = function
send_coq_debug e; [inject_debug_event Dm.Log.debug]
| SendProofView (uri, position) ->
begin match Hashtbl.find_opt states (DocumentUri.to_path uri) with
| None -> log @@ "ignoring event on non existant document"; []
| None -> log @@ "ignoring event on non existent document"; []
| Some { st } ->
let proof = Dm.DocumentManager.get_proof st !diff_mode position in
let messages = Dm.DocumentManager.get_messages st position in
Expand Down
Loading