linol/lsp/test/string_zipper_tests.ml
Simon Cruanes 7fbc187548 Squashed 'thirdparty/lsp/' content from commit aae69863
git-subtree-dir: thirdparty/lsp
git-subtree-split: aae6986391a8519de3da6a7a341f2bd3376e0d2f
2025-04-10 15:44:25 -04:00

191 lines
4.8 KiB
OCaml

open Stdune
module String_zipper = Lsp.Private.String_zipper
module Substring = Lsp.Private.Substring
let to_dyn { String_zipper.Private.left; rel_pos; current; right; line; abs_pos } =
let open Dyn in
let sub x = string (Substring.to_string x) in
let subs = list sub in
record
[ "left", subs left
; "rel_pos", int rel_pos
; "abs_pos", int abs_pos
; "current", sub current
; "right", subs right
; "line", int line
]
;;
type op =
[ `Goto_line of int
| `Insert of string
]
let test ?(which = `All) mode start operations =
let results =
List.fold_left
operations
~init:[ `Hide, start ]
~f:(fun acc (op : [ op | `Hide of op ]) ->
let final =
let _, last = List.hd acc in
let commit_op op =
match op with
| `Insert s -> String_zipper.insert last s
| `Goto_line g -> String_zipper.goto_line last g
in
match op with
| `Hide op -> `Hide, commit_op op
| #op as x -> `Show, commit_op x
in
final :: acc)
|> List.rev
|> List.tl
in
let results =
match which with
| `All -> results
| `Last -> [ List.rev results |> List.hd ]
in
List.filter_map results ~f:(fun (display, res) ->
match display with
| `Hide -> None
| `Show -> Some res)
|> List.iter ~f:(fun res ->
let res =
match mode with
| `Dyn -> String_zipper.Private.reflect res |> to_dyn |> Dyn.to_string
| `String ->
let line = (String_zipper.Private.reflect res).line in
Printf.sprintf "line %d: %S" line (String_zipper.to_string_debug res)
in
Printf.printf "%s\n" res)
;;
let%expect_test "goto line" =
let foo = String_zipper.of_string "foo\nX\nY" in
test `String foo [ `Goto_line 0 ];
[%expect {| line 0: "|foo\nX\nY" |}];
test
`String
foo
[ `Goto_line 0
; `Goto_line 1
; `Goto_line 2
; `Goto_line 3
; `Goto_line 2
; `Goto_line 1
; `Goto_line 0
; `Goto_line 0
];
[%expect
{|
line 0: "|foo\nX\nY"
line 1: "foo\n|X\nY"
line 2: "foo\nX\n|Y"
line 2: "foo\nX\nY|"
line 2: "foo\nX\n|Y"
line 1: "foo\n|X\nY"
line 0: "|foo\nX\nY"
line 0: "|foo\nX\nY" |}];
test `String (String_zipper.of_string "") [ `Goto_line 100; `Goto_line 0 ];
[%expect
{|
line 0: "|"
line 0: "|" |}];
test `String foo [ `Insert "baz"; `Goto_line 1; `Insert "1" ];
[%expect
{|
line 0: "|bazfoo\nX\nY"
line 1: "bazfoo\n|X\nY"
line 1: "bazfoo\n|1X\nY" |}]
;;
let%expect_test "insertions" =
let foo = String_zipper.of_string "foo" in
test `String foo [ `Insert "" ];
[%expect
{|
line 0: "|foo" |}];
test `String foo [ `Insert "a" ];
[%expect
{|
line 0: "|afoo" |}];
test `String foo [ `Insert "a"; `Insert "b" ];
[%expect
{|
line 0: "|afoo"
line 0: "|bafoo" |}]
;;
let%expect_test "mixed insert goto" =
let foo = String_zipper.of_string "foo" in
test `String foo [ `Insert "XXX"; `Insert "YYY"; `Insert "zzz" ];
[%expect
{|
line 0: "|XXXfoo"
line 0: "|YYYXXXfoo"
line 0: "|zzzYYYXXXfoo" |}]
;;
let%expect_test "drop_until" =
let t = String_zipper.of_string "foo\nbar\nxxx" in
let t = String_zipper.goto_line t 1 in
let t' = String_zipper.goto_line t 2 in
let t = String_zipper.drop_until t t' in
printfn "%S" (String_zipper.to_string_debug t);
[%expect
{|
"foo\n|xxx" |}];
let t = String_zipper.of_string "foo\nbar\n" in
let t = String_zipper.goto_line t 2 in
let t = String_zipper.drop_until t t in
printfn "%S" (String_zipper.to_string_debug t);
[%expect
{|
"foo\nbar\n|" |}];
let t = String_zipper.of_string "123\n" in
let t = String_zipper.goto_line t 1 in
let t = String_zipper.drop_until t t in
printfn "%S" (String_zipper.to_string_debug t);
[%expect {| "123\n|" |}]
;;
let%expect_test "squashing" =
let str = "foo\nbar" in
let t = String_zipper.of_string str in
let t = String_zipper.goto_line t 1 in
let t, str' = String_zipper.squash t in
assert (String.equal str str');
printfn "squashing: %S" (String_zipper.to_string_debug t);
[%expect
{|
squashing: "foo\n|bar" |}]
;;
let%expect_test "add buffer between" =
let str = "foo\nbar" in
let t = String_zipper.of_string str in
let t' = String_zipper.goto_line t 1 in
let b = Buffer.create 0 in
String_zipper.add_buffer_between b t t';
printfn "result: %S" (Buffer.contents b);
[%expect
{|
result: "foo\n" |}]
;;
let%expect_test "drop_until bug" =
let t = String_zipper.of_string "foo\nbar\nxxx" in
let t' = String_zipper.goto_line t 10 in
let t = String_zipper.goto_line t 2 in
let t = String_zipper.drop_until t t' in
printfn "%S" (String_zipper.to_string_debug t);
[%expect
{|
"foo\nbar\n|" |}];
printfn "abs_pos: %d" (String_zipper.Private.reflect t).abs_pos;
[%expect
{|
abs_pos: 8 |}]
;;