package forester
A tool for tending mathematical forests
Install
Dune Dependency
Authors
Maintainers
Sources
5.0.tar.gz
md5=24f4aed96a8b8af33aba13fba66f1b37
sha512=d36b896aca11858bb4a00fc704c16cc27a1f197bdb3e479d6132fd70f70d67d7158096285cb0b6fb00db14417f0f822cc27fe65d82f0971e42378fd8271ce573
doc/src/forester.language_server/Semantic_tokens.ml.html
Source file Semantic_tokens.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
(* * SPDX-FileCopyrightText: 2024 The Forester Project Contributors AND The RedPRL Development Team * * SPDX-License-Identifier: GPL-3.0-or-later OR Apache-2.0 WITH LLVM-exception * *) open Forester_prelude open Forester_core open Forester_compiler open struct module L = Lsp.Types end let print_array = Format.( pp_print_array ~pp_sep: (fun out () -> fprintf out "; ") pp_print_int ) module Token_type = struct type t = L.SemanticTokenTypes.t let legend : L.SemanticTokenTypes.t list = [ Namespace; Type; Class; Enum; Interface; Struct; TypeParameter; Parameter; Variable; Property; EnumMember; Event; Function; Method; Macro; Keyword; Modifier; Comment; String; Number; Regexp; Operator; Decorator ] let of_builtin t = t let token_types = List.map (fun s -> match L.SemanticTokenTypes.yojson_of_t s with | `String s -> s | _ -> assert false ) legend let to_int = let module Table = MoreLabels.Hashtbl in let table = lazy( let t = Table.create (List.length legend) in List.iteri (fun data key -> Table.add t ~key ~data) legend; t ) in fun t -> Table.find (Lazy.force table) t let to_legend t = match L.SemanticTokenTypes.yojson_of_t t with | `String s -> s | _ -> assert false end module Token_modifiers_set = struct let list = [ "declaration"; "definition"; "readonly"; "static"; "deprecated"; "abstract"; "async"; "modification"; "documentation"; "defaultLibrary" ] ;; end let legend = L.SemanticTokensLegend.create ~tokenTypes: Token_type.token_types ~tokenModifiers: Token_modifiers_set.list type token = { (* node: string; *) line: int; start_char: int; length: int; token_type: int; token_modifiers: int; } [@@deriving show] type delta_token = { delta_line: int; delta_start_char: int; length: int; token_type: int; token_modifiers: int; } [@@deriving show] let encode : token -> int list = function | {line; start_char; length; token_type; token_modifiers; _} -> [line; start_char; length; token_type; token_modifiers] let encode_deltas : delta_token -> int list = function | {delta_line; delta_start_char; length; token_type; token_modifiers} -> [delta_line; delta_start_char; length; token_type; token_modifiers] let group f l = let rec grouping acc = function | [] -> acc | hd :: tl -> let l1, l2 = List.partition (f hd) tl in grouping ((hd :: l1) :: acc) l2 in grouping [] l (* TODO? *) let node_to_tokens (_ : Code.node Range.located) _ _list = [] let tokenize_path ~(start : L.Position.t) (path : string list) : token list = let offset = ref (start.character) in Eio.traceln "path has %i segments" (List.length path); let@ segment = List.concat_map @~ path in let length = String.length segment in let start_char = !offset in offset := !offset + length + 1; let token_type = 1 in let line = start.line in [ { line; start_char; length; token_type; token_modifiers = 0; (* node = segment *) } ] let shift offset = List.map @@ fun token -> {token with start_char = token.start_char + offset} let builtin ~(start : L.Position.t) str tks = let offset = String.length str in { (* node = str; *) line = start.line; start_char = start.character; length = offset; token_type = 5; token_modifiers = 0 } :: shift offset tks let tokens (nodes : Code.t) : token list = let@ Range.{loc; value} = List.concat_map @~ nodes in let L.Range.{start; end_} = Lsp_shims.Loc.lsp_range_of_range loc in (* Multiline tokens not supported*) if start.line <> end_.line then [] else match value with | Code.Ident path -> tokenize_path ~start path | Code.Text _ -> [] | Code.Put (_path, _t) -> [] (* -> *) (* builtin *) (* ~start *) (* "put" @@ *) (* tokenize_path ~start path @ tokens t *) | Code.Math (_, _) | Code.Verbatim _ | Code.Import (_, _) | Code.Let (_, _, _) | Code.Def (_, _, _) | Code.Group (_, _) | Code.Hash_ident _ | Code.Xml_ident (_, _) | Code.Subtree (_, _) | Code.Open _ | Code.Scope _ | Code.Default (_, _) | Code.Get _ | Code.Fun (_, _) | Code.Object _ | Code.Patch _ | Code.Call (_, _) | Code.Decl_xmlns (_, _) | Code.Alloc _ | Code.Dx_sequent (_, _) | Code.Dx_query (_, _, _) | Code.Dx_prop (_, _) | Code.Dx_var _ | Code.Dx_const_content _ | Code.Dx_const_uri _ | Code.Error _ | Code.Comment _ | Code.Namespace (_, _) -> [] let process_line_delta (index_of_last_line : int option) (tokens : token list) : int * delta_token list = let line = (List.hd tokens).line in let deltas = List.fold_left (fun (last_token, acc) ({start_char; length; token_type; token_modifiers; line; _; } as current_token) -> match last_token with | None -> let delta_line = match index_of_last_line with Some i -> i - line | None -> line in let delta_start_char = start_char in let t = {delta_line; delta_start_char; length; token_type; token_modifiers} in (Some current_token, t :: acc) | Some last_token -> (*If there is a previous token, we know we are still on the same line*) let delta_line = current_token.line - last_token.line in let delta_start_char = if delta_line > 0 then current_token.start_char else current_token.start_char - last_token.start_char in let delta = {delta_line; delta_start_char; length = current_token.length; token_type = current_token.token_type; token_modifiers;} in (Some current_token, delta :: acc) ) (None, []) tokens in line, snd deltas |> List.rev let delta_tokens (tokens : token list list) : int array = tokens |> List.fold_left (fun (last_line, acc) tokens_on_line -> let line, delta_tokens = process_line_delta last_line tokens_on_line in Some line, delta_tokens :: acc ) (None, []) |> snd |> List.rev |> List.concat |> List.concat_map encode_deltas |> List.rev |> Array.of_list let semantic_tokens_delta (_code : Code.node Range.located list) : L.SemanticTokensDelta.t = { L.SemanticTokensDelta.resultId = None; edits = []; } let tokenize_document (identifier : L.TextDocumentIdentifier.t) : L.SemanticTokens.t option = let Lsp_state.{forest; _} = Lsp_state.get () in let uri = URI_scheme.lsp_uri_to_uri ~base: forest.config.url identifier.uri in let@ {nodes; _} = Option.map @~ Imports.resolve_uri_to_code forest uri in let tokens = tokens nodes in Format.( Eio.traceln "%a" ( pp_print_list ~pp_sep: (fun out () -> fprintf out "; ") pp_token ) tokens ); let encoded = List.concat_map encode tokens in let data = Array.of_list @@ encoded in L.SemanticTokens.{data; resultId = None} let tokenize_document_delta (textDocument : L.TextDocumentIdentifier.t) : L.SemanticTokensDelta.t option = let Lsp_state.{forest; _} = Lsp_state.get () in let uri = URI_scheme.lsp_uri_to_uri ~base: forest.config.url textDocument.uri in let@ tree = Option.map @~ Imports.resolve_uri_to_code forest uri in semantic_tokens_delta tree.nodes let on_full_request (params : L.SemanticTokensParams.t) : L.SemanticTokens.t option = tokenize_document params.textDocument let on_delta_request (params : L.SemanticTokensDeltaParams.t) : [`SemanticTokens of L.SemanticTokens.t | `SemanticTokensDelta of L.SemanticTokensDelta.t] option = let@ tokens = Option.map @~ tokenize_document_delta params.textDocument in `SemanticTokensDelta tokens
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>