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

Language Server Protocol for TLAPM #93

Merged
merged 145 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 116 commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
e09e72d
Initial experiments with LSP.
kape1395 Sep 19, 2023
fc0cd13
Empty LSP server works.
kape1395 Sep 19, 2023
6d06443
Some code reorg.
kape1395 Sep 19, 2023
c5e54d4
Use the code formatter.
kape1395 Sep 19, 2023
e71f936
Improving it.
kape1395 Sep 19, 2023
705f1cc
CLI added, some refactorings, 2 transports.
kape1395 Sep 20, 2023
7b6735f
IO Tracing added.
kape1395 Sep 20, 2023
67b1629
Some LSP communication works already.
kape1395 Sep 22, 2023
6b90562
Option to redirect stderr to a file.
kape1395 Sep 23, 2023
637f37d
Use logging to a file rom the ts code.
kape1395 Sep 23, 2023
687f5a4
Docs store.
kape1395 Sep 23, 2023
a6ddb4f
Some experiments on test cases.
kape1395 Sep 23, 2023
ff2d50b
Handle some LSP packets.
kape1395 Sep 24, 2023
cc08f1d
Attempt to reuse the original traceln function.
kape1395 Sep 24, 2023
fd022ee
Track connection state.
kape1395 Sep 24, 2023
79eadba
Support prover-info cmd.
kape1395 Sep 24, 2023
d6c7131
Cleanup.
kape1395 Sep 24, 2023
bbbc308
Cleanup.
kape1395 Sep 24, 2023
31d69e1
Playing with more LSP command types.
kape1395 Sep 24, 2023
ac444b2
Notes.
kape1395 Sep 24, 2023
a54d399
Prove-step now contains the cursor in the doc.
kape1395 Sep 24, 2023
9bd124e
Some tests.
kape1395 Sep 29, 2023
413bd17
Some progress on the tlapm invokation.
kape1395 Oct 2, 2023
bf54288
Toolbox parser, support multiline fields.
kape1395 Oct 2, 2023
10f8edf
Small code simplifications.
kape1395 Oct 2, 2023
9316553
Some notes.
kape1395 Oct 3, 2023
866892d
Some test cases.
kape1395 Oct 7, 2023
eeab4f0
Support for reading a TLA file from STDIN.
kape1395 Oct 7, 2023
0f9da46
Use stream add function instead of stream directly.
kape1395 Oct 7, 2023
dede4da
Code reorganized to run on threads.
kape1395 Oct 7, 2023
7d62986
Working on the LSP prove-step command.
kape1395 Oct 7, 2023
4db77ad
Prover is now invoked.
kape1395 Oct 8, 2023
8719f7d
TLAPM is now invoked.
kape1395 Oct 8, 2023
d0120d7
Range translation fixed.
kape1395 Oct 8, 2023
462cad8
Obligations are now shown (on proof event only).
kape1395 Oct 8, 2023
679e556
Structs to maintain obligation state added.
kape1395 Oct 8, 2023
2253767
Notes.
kape1395 Oct 8, 2023
2b416ed
It starts looking like working.
kape1395 Oct 9, 2023
b7cd138
Line diff.
kape1395 Oct 9, 2023
cd5d78f
Docs module reorganized.
kape1395 Oct 9, 2023
32bbf85
Diagnostics pull implemented.
kape1395 Oct 10, 2023
b3bce51
Code formatting.
kape1395 Oct 10, 2023
7ec97db
Unify use of diagnostic source.
kape1395 Oct 10, 2023
9ab7d63
Misc fixes.
kape1395 Oct 10, 2023
2aa1f6f
Show failed obligation.
kape1395 Oct 10, 2023
989642c
Rename the prove-step command.
kape1395 Oct 13, 2023
46a66f0
Makefile env setup targets fixed.
kape1395 Oct 13, 2023
7b3e2b9
Parser is now invoked.
kape1395 Oct 14, 2023
7870b0a
Use modules instead of embedded recs.
kape1395 Oct 14, 2023
cb51893
Consider theorem ranges when checking a step.
kape1395 Oct 14, 2023
8d9d19c
A bit of error handling.
kape1395 Oct 14, 2023
c58d5e4
Make build work with older ocaml versions.
kape1395 Oct 14, 2023
37e8a07
Experiment: use custom notification to present proof states.
kape1395 Oct 15, 2023
58618d5
Notes.
kape1395 Oct 15, 2023
579804a
Proof state is shown somehow.
kape1395 Oct 15, 2023
1a72a56
Cleanup.
kape1395 Oct 16, 2023
0cc97f9
QED step locus tracking fixed in the parser.
kape1395 Oct 16, 2023
4b6baa8
Code action for "check-proof".
kape1395 Oct 16, 2023
2c4b5eb
Use Ocaml 5.1 in the CI build.
kape1395 Oct 16, 2023
871a148
Make CI work with OCaml 5.1.
kape1395 Oct 16, 2023
ca30c58
Better traceln impl.
kape1395 Oct 17, 2023
5177315
Use Re2 instead of Str.
kape1395 Oct 19, 2023
4425941
Try improve range calculations.
kape1395 Oct 19, 2023
83acdf3
Route the obl_num/terminated to the corresponding doc.
kape1395 Oct 20, 2023
38403e8
A bit of cleanup.
kape1395 Oct 20, 2023
ab6cb52
Working on the progress presentation and the cancellation.
kape1395 Oct 21, 2023
2116c53
Progress is now shown.
kape1395 Oct 21, 2023
7da3374
Cleanup.
kape1395 Oct 21, 2023
c72e177
Cancellation support.
kape1395 Oct 21, 2023
7e552c0
Improve error handling.
kape1395 Nov 11, 2023
a12ddea
Fixes #100.
kape1395 Nov 11, 2023
d0ed4b6
Use SigINT to interrupt the TLAPM instead of SigKILL.
kape1395 Dec 17, 2023
07819c6
Buffer proof info updates for some time before sending them to the IDE.
kape1395 Dec 17, 2023
ccaa8f7
Merge remote-tracking branch 'upstream/main' into lsp
kape1395 Dec 21, 2023
528e0a8
Invoke graceful termination on SigINT.
kape1395 Jan 5, 2024
668db17
Initial version of providing the proof state of a step.
kape1395 Jan 7, 2024
4074c28
Missing lib added, some auto-formatting.
kape1395 Jan 7, 2024
07e89f9
Make mutex usage compatible with older ocaml versions.
kape1395 Jan 7, 2024
0cb0251
Broken test fixed.
kape1395 Jan 7, 2024
f18baaa
Remove test LSP client. It is not relevant anymore.
kape1395 Jan 7, 2024
dd07c14
Adjust the proof state structs for the UI.
kape1395 Jan 8, 2024
0928d79
Split tlapm_lsp_docs into multiple files.
kape1395 Jan 12, 2024
332a174
Use HTTPS to download Isabelle.
kape1395 Jan 12, 2024
814e059
Take obligation text from the parser.
kape1395 Jan 13, 2024
ec55193
Use search path when parsing a document.
kape1395 Jan 13, 2024
9be9d3a
Only show steps from the current file.
kape1395 Jan 14, 2024
529e001
Proof steps are determined correctly again. Closes #114.
kape1395 Jan 16, 2024
bb88a5e
Retain proof state based on fingerprints; attach obligations to steps…
kape1395 Jan 21, 2024
b0497da
Include the BY clauses into the proof step range.
kape1395 Jan 22, 2024
d26164b
Show proof steps for HAVE, TAKE, WITNESS.
kape1395 Jan 22, 2024
87788f0
Better error message for unsupported recursive operators.
kape1395 Jan 23, 2024
7db485a
Code reorganized into sub-modules.
kape1395 Jan 23, 2024
8354385
Formatter.
kape1395 Jan 23, 2024
0311059
Move range to the main lsp lib.
kape1395 Jan 23, 2024
241cfb3
Prover client code reorganized.
kape1395 Jan 24, 2024
7db97e8
Reorganize code into sub-modules.
kape1395 Jan 24, 2024
4ef5e1f
Progress reorganized.
kape1395 Jan 24, 2024
54e5930
Add status to TlapsProofStepDetails.
kape1395 Jan 24, 2024
7d9cb83
LSP: omitted and progress fixed.
kape1395 Jan 26, 2024
b500bbd
Misc TODOs addressed.
kape1395 Jan 27, 2024
8bec891
Send updates to the current proof step details.
kape1395 Jan 27, 2024
c00773d
Retain decorators after tabs are switched.
kape1395 Jan 27, 2024
512586b
Set the current proof step via explicit LSP command.
kape1395 Jan 27, 2024
b5aa2a7
Send the obligation role with the details.
kape1395 Jan 27, 2024
f006a8f
Pass obligation status to UI.
kape1395 Jan 28, 2024
9289216
Have to process all the referenced modules.
kape1395 Jan 30, 2024
14e45b5
Exchange module search paths with the LSP client.
kape1395 Feb 3, 2024
52d2219
LSP now takes paths from the client.
kape1395 Feb 3, 2024
31ed7d8
Add `--prefer-stdlib` option and use it in the LSP server. This is to…
kape1395 Feb 9, 2024
1b4437c
Global ref to the parser paths eliminated.
kape1395 Feb 10, 2024
777c732
Propagate parser updates to the loaded docs.
kape1395 Feb 10, 2024
6231f51
Report an understandable error if an operator is applied with a wrong…
kape1395 Feb 13, 2024
5dc0169
Register parsing errors so that they can be reported nicely.
kape1395 Feb 13, 2024
d3eb73f
More of error handling in the parser.
kape1395 Feb 17, 2024
0a5b5f6
Merge remote-tracking branch 'origin/main' into lsp
kape1395 Feb 26, 2024
5fa594b
Merge remote-tracking branch 'upstream/main' into lsp
kape1395 Feb 26, 2024
edfd377
Mistype fixed.
kape1395 May 31, 2024
cee770f
Update lsp/lib/docs/doc_vsn.ml
kape1395 May 31, 2024
8dfcaa5
Remove unused module export.
kape1395 Jun 1, 2024
70d43c3
Mistype fixed.
kape1395 Jun 1, 2024
9bb6a52
Mistype fixed.
kape1395 Jun 1, 2024
9d9a559
Mistype fixed.
kape1395 Jun 1, 2024
6591218
Comment refined.
kape1395 Jun 1, 2024
09c9414
failwith -> assert false
kape1395 Jun 1, 2024
f653fd7
Use atomic instead of mutex in the signal handler.
kape1395 Jun 8, 2024
53cfe83
Merge remote-tracking branch 'origin/main' into lsp
kape1395 Jun 8, 2024
8b8ce33
Multiple mistypes in comments fixed.
kape1395 Jun 8, 2024
933a762
Use assert false for impossible cases.
kape1395 Jun 8, 2024
f682548
Use `type nonrec t = t` instead of a renamed type.
kape1395 Jun 8, 2024
1865962
A function simplified.
kape1395 Jun 8, 2024
6f7c3ac
Don't use needless namespaces.
kape1395 Jun 8, 2024
20583b6
Error message improved.
kape1395 Jun 8, 2024
7491db9
Make code more readable.
kape1395 Jun 8, 2024
7865485
Error message improved.
kape1395 Jun 8, 2024
6b6d9a8
Use OCaml 4.14 instead of 4.13. Build a release on 5.1.0.
kape1395 Jun 8, 2024
f5fccb3
Refine the `step_loc` description.
kape1395 Jun 8, 2024
c573aba
Improve comments.
kape1395 Jun 10, 2024
0ac8eac
Exactly 1 module has to be specified if TLAPM is invoked with the `--…
kape1395 Jun 10, 2024
9e1fbe7
Update to the new dependency versions.
kape1395 Aug 24, 2024
ab37243
Merge remote-tracking branch 'origin/main' into lsp
kape1395 Aug 24, 2024
47afb6b
Use proper library paths in all cases.
kape1395 Aug 26, 2024
0c996a6
Improve comments.
kape1395 Aug 26, 2024
4837328
Handle file read errors gracefully.
kape1395 Aug 26, 2024
8138f4b
Toolbox protocol v2 added, fixed the check if an obligation is in the…
kape1395 Aug 27, 2024
4d53b9e
Cleanup around the pending provers for an obligation.
kape1395 Aug 28, 2024
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
7 changes: 6 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,15 @@ jobs:
# with:
# path: _build_cache
# key: ${{ runner.os }}_build_cache
- name: Install optional dependencies
if: matrix.ocaml-compiler == '2'
kape1395 marked this conversation as resolved.
Show resolved Hide resolved
run: |
eval $(opam env)
make opam-deps-opt
- name: Build installer of TLAPS
run: |
eval $(opam env)
opam install ./ --deps-only --yes
make opam-deps
make
make release
- name: Run a subset of `tlapm` tests
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ocaml_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@


OCAML_VERSIONS = [
'4.08.1',
'4.13.0',
'4.14.0',
'4.13.1',
'4.14.1',
kape1395 marked this conversation as resolved.
Show resolved Hide resolved
'5.1.0'
]


Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,15 @@ jobs:
# with:
# path: _build_cache
# key: ${{ runner.os }}_build_cache
- name: Install optional dependencies
if: matrix.ocaml-compiler == '2'
kape1395 marked this conversation as resolved.
Show resolved Hide resolved
run: |
eval $(opam env)
make opam-deps-opt
- name: Build installer of TLAPS
run: |
eval $(opam env)
opam install ./ --deps-only --yes
make opam-deps
make
make release
- name: Run a subset of `tlapm` tests
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,15 @@ jobs:
# with:
# path: _build_cache
# key: ${{ runner.os }}_build_cache
- name: Install optional dependencies
if: matrix.ocaml-compiler == '2'
kape1395 marked this conversation as resolved.
Show resolved Hide resolved
run: |
eval $(opam env)
make opam-deps-opt
- name: Build installer of TLAPS
run: |
eval $(opam env)
opam install ./ --deps-only --yes
make opam-deps
make
make release
echo "TLAPM_RELEASE_FILE=$(make release-print-file)" >> "$GITHUB_ENV"
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

/_build/
/_build_cache/
/.vscode/
/.vscode/settings.json
/tlaps-*.tar.gz

__pycache__/
Expand Down
2 changes: 2 additions & 0 deletions .ocamlformat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
version=0.26.1
profile=default
14 changes: 14 additions & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"words": [
"tlaplus",
"tlaps",
"tlapm",
"zenon",
"opam",
"ocaml",
"caml",
"sandboxing",
"sprintf",
"printexc"
]
}
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ all: build
opam-deps:
opam install ./ --deps-only --yes --working-dir

opam-deps-opt:
opam install --yes eio_main lsp

opam-deps-dev:
opam install ocamlformat ocaml-lsp-server
opam install --yes ocamlformat ocaml-lsp-server

build:
dune build
Expand All @@ -40,6 +43,10 @@ test-fast:
test-fast-basic:
make -C test fast/basic

fmt:
# Onlt the LSP part is not formatted automatically.
kape1395 marked this conversation as resolved.
Show resolved Hide resolved
cd lsp && dune fmt

install:
dune install --prefix=$(PREFIX)
make -C $(PREFIX)/lib/tlapm/ -f Makefile.post-install
Expand Down
10 changes: 9 additions & 1 deletion dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

(source (github tlaplus/tlapm))

(cram enable)

(package
(name tlapm)
(synopsis "TLA+ Proof Manager")
Expand Down Expand Up @@ -40,5 +42,11 @@
dune-site
dune-build-info
sexplib
cmdliner
camlzip
re2
ppx_inline_test
ppx_assert))
ppx_assert)
(depopts
lsp ; https://github.com/ocaml/ocaml-lsp
eio_main)) ; https://github.com/ocaml-multicore/eio, only available on OCaml version >= 5.
7 changes: 5 additions & 2 deletions library/dune
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
(install
(section (site (tlapm stdlib)))
(files (glob_files "*.tla")))
(section
(site
(tlapm stdlib)))
(files
(glob_files "*.tla")))
23 changes: 23 additions & 0 deletions lsp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# LSP interface to the TLAPS

The `tlapm_lsp` works as an adapter between the `tlapm` and code editors, e.g., VSCode.
It is responsible for:
- Parsing the document structure to locate features related to proofs, e.g.:
- proof obligation by cursor position, possibly collecting all the subtree of obligations.
- Running the `tlapm` on specific obligations and reporting the results.
- Show progress of the tlapm, allow cancel it.
- TODO: Proof re-numbering.
- TODO: Proof decomposition.
- TODO: Easier experimentation on missing facts.

The test folder contains a VSCode extension / LSP client. It is meant only for testing,
the real integration should be done in the TLA+ VSCode extension.

See:
- Dafny plugin. It shows all the obligations as testcases.
<https://github.com/dafny-lang/ide-vscode>
<https://github.com/dafny-lang/dafny/tree/master/Source/DafnyLanguageServer>
- VSCode Decorators: https://github.com/microsoft/vscode-extension-samples/blob/main/decorator-sample/README.md
https://vscode.rocks/decorations/
Gutter -- the left side of the editor.

7 changes: 7 additions & 0 deletions lsp/bin/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(executable
(name tlapm_lsp)
(public_name tlapm_lsp)
(optional) ; Only build, if eio is available, which is only the case for ocaml > 5.
(enabled_if
(>= %{ocaml_version}, "5.0.0"))
(libraries tlapm_lsp_lib eio_main cmdliner))
111 changes: 111 additions & 0 deletions lsp/bin/tlapm_lsp.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
(* cSpell:words cmdliner signum Open_wronly Open_creat fprintf kdprintf *)

open Cmdliner

let traceln_mutex = Mutex.create ()

let transport_of_args tr_stdio tr_socket =
let open Tlapm_lsp_lib.Server in
match (tr_stdio, tr_socket) with
| true, None -> Ok Stdio
| false, Some port -> Ok (Socket port)
| _ -> Error "Exactly one of transports has to be specified."

let run transport log_to log_io =
Printexc.record_backtrace true;
let main_fun (env : Eio_unix.Stdenv.base) =
let main_switch _sw =
let stop_promise, stop_resolver = Eio.Std.Promise.create () in
let handle_signal (_signum : int) =
Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT"
in
Sys.set_signal Sys.sigint (Signal_handle handle_signal);
Tlapm_lsp_lib.Server.run transport log_io env stop_promise
in
let with_log_stderr () = Eio.Switch.run main_switch in
let with_log_file log_file =
let with_log_chan log_chan =
(* This is mostly a copy of default_traceln from eio/core/debug.ml,
just modified to take a specific out channel instead of stderr. *)
let traceln_impl ?__POS__:pos fmt =
let k go =
let b = Buffer.create 512 in
let f = Format.formatter_of_buffer b in
go f;
Option.iter
(fun (file, line, _, _) -> Format.fprintf f " [%s:%d]" file line)
pos;
Format.pp_close_box f ();
Format.pp_print_flush f ();
let msg = Buffer.contents b in
let lines = String.split_on_char '\n' msg in
Mutex.lock traceln_mutex;
Fun.protect ~finally:(fun () -> Mutex.unlock traceln_mutex)
@@ fun () ->
List.iter (Printf.fprintf log_chan "+%s\n") lines;
flush log_chan
in
Format.kdprintf k ("@[" ^^ fmt)
in
let traceln_bnd = { Eio.Debug.traceln = traceln_impl } in
let debug = Eio.Stdenv.debug env in
Eio.Fiber.with_binding debug#traceln traceln_bnd (fun _ ->
Format.pp_set_formatter_out_channel Format.err_formatter log_chan;
Eio.Switch.run main_switch)
in
Out_channel.with_open_gen
[ Open_append; Open_wronly; Open_creat ]
0o644 log_file with_log_chan
in
match log_to with
| None -> with_log_stderr ()
| Some log_file -> with_log_file log_file
in
Eio_main.run main_fun

module Cli = struct
let arg_stdio =
let doc = "Run LSP over StdIO." in
let info = Arg.info [ "stdio" ] ~docv:"BOOL" ~doc in
Arg.value (Arg.flag info)

let arg_socket =
let doc = "Run LSP over TCP, use the specified port." in
let info = Arg.info [ "socket"; "port" ] ~docv:"NUM" ~doc in
Arg.value (Arg.opt (Arg.some Arg.int) None info)

let arg_log_to =
let doc = "Log all to the specified file instead of StdErr." in
let info = Arg.info [ "log-to" ] ~docv:"FILE" ~doc in
Arg.value (Arg.opt (Arg.some Arg.string) None info)

let arg_log_io =
let doc = "Log protocol's IO." in
let info = Arg.info [ "log-io" ] ~docv:"BOOL" ~doc in
Arg.value (Arg.flag info)

let term () =
let combine tr_stdio tr_socket log_to log_io =
match transport_of_args tr_stdio tr_socket with
| Ok transport -> `Ok (run transport log_to log_io)
| Error err -> `Error (false, err)
in
Term.(const combine $ arg_stdio $ arg_socket $ arg_log_to $ arg_log_io)

let name = "tlapm_lsp"
let doc = "LSP interface for TLAPS."

let man =
[
`S Manpage.s_description;
`P "tlapm_lsp allows LSP based IDEs to access the prover functions.";
`S Manpage.s_see_also;
`P "The TLAPM code repository: https://github.com/tlaplus/tlapm";
]

let main () =
let info = Cmd.info ~doc ~man name in
Cmd.v info (Term.ret (term ())) |> Cmd.eval |> Stdlib.exit
end

let () = Cli.main ()
Empty file added lsp/bin/tlapm_lsp.mli
Empty file.
35 changes: 35 additions & 0 deletions lsp/components.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@startuml TLAPM-LSP

component LspServer
LspServer --> Session

note as N_General
General layout of the tlapm_lsp_lib.
end note

component Session as Session {
component Handler
}
Session --> Prover
Session --> Docs

component Docs {
component Doc
component Version
component Actual
Doc *-- Version
Doc *-- Actual
Actual --> Parser
}
component Parser {
component TLAPM
component SANY
}
component Prover {
component Runner
component Toolbox
component Progress
Runner --> Toolbox
Runner --> Progress
}
@enduml
1 change: 1 addition & 0 deletions lsp/lib/const.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let diagnostic_source = "TLAPM"
1 change: 1 addition & 0 deletions lsp/lib/const.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
val diagnostic_source : string
53 changes: 53 additions & 0 deletions lsp/lib/docs/doc.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
open Util

(* Max number of unprocessed/pending versions to keep. *)
let keep_vsn_count = 50

type t = {
uri : LspT.DocumentUri.t;
pending : Doc_vsn.t list;
(** All the received but not yet processed versions. *)
actual : Doc_actual.t; (** Already processed version. *)
}

let make uri tv parser =
{ uri; pending = []; actual = Doc_actual.make uri tv None parser }

let with_parser doc parser =
{ doc with actual = Doc_actual.with_parser doc.actual parser }

let add doc tv =
let drop_till = Doc_vsn.version tv - keep_vsn_count in
let drop_unused = List.filter (fun pv -> Doc_vsn.version pv < drop_till) in
{ doc with pending = tv :: drop_unused doc.pending }

let latest_vsn doc =
match doc.pending with
| [] -> Doc_actual.vsn doc.actual
| latest :: _ -> Doc_vsn.version latest

let set_actual_vsn doc vsn =
if Doc_actual.vsn doc.actual = vsn then Some doc
else
let rec drop_after_vsn = function
| [] -> (None, [])
| (pv : Doc_vsn.t) :: pvs ->
if Doc_vsn.version pv = vsn then (Some pv, [])
else
let res, pvs = drop_after_vsn pvs in
(res, pv :: pvs)
in
let selected, pending = drop_after_vsn doc.pending in
match selected with
| None -> None
| Some selected ->
let actual =
Doc_actual.make doc.uri selected (Some doc.actual)
(Doc_actual.parser doc.actual)
in
Some { doc with actual; pending }

let with_actual doc f =
let doc, act, res = f doc doc.actual in
let doc = { doc with actual = act } in
(doc, res)
12 changes: 12 additions & 0 deletions lsp/lib/docs/doc.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(** Represents a document identified by its uri. It can contain multiple versions and all the related info. *)

open Util

type t

val make : LspT.DocumentUri.t -> Doc_vsn.t -> Util.parser_fun -> t
val with_parser : t -> Util.parser_fun -> t
val add : t -> Doc_vsn.t -> t
val latest_vsn : t -> int
val set_actual_vsn : t -> int -> t option
val with_actual : t -> (t -> Doc_actual.t -> t * Doc_actual.t * 'a) -> t * 'a
Loading
Loading