Skip to content

Commit

Permalink
rename: support project-wide but unsafe renaming
Browse files Browse the repository at this point in the history
  • Loading branch information
voodoos committed Jan 29, 2024
1 parent 7105c12 commit 1c3ebfd
Showing 1 changed file with 48 additions and 48 deletions.
96 changes: 48 additions & 48 deletions ocaml-lsp-server/src/rename.ml
Original file line number Diff line number Diff line change
@@ -1,67 +1,67 @@
open Import
open Fiber.O
module StringMap = Map.Make (String)

let rename (state : State.t)
{ RenameParams.textDocument = { uri }; position; newName; _ } =
Format.eprintf "DBG URI = %s\n%!" (DocumentUri.to_string uri);
let doc = Document_store.get state.store uri in
match Document.kind doc with
| `Other -> Fiber.return (WorkspaceEdit.create ())
| `Merlin merlin ->
let command =
Query_protocol.Occurrences (`Ident_at (Position.logical position), `Project)
Query_protocol.Occurrences
(`Ident_at (Position.logical position), `Project)
in
let+ locs, _desync = Document.Merlin.dispatch_exn merlin command in
let version = Document.version doc in
let source = Document.source doc in
let edits =
List.map locs ~f:(fun (loc : Warnings.loc) ->
let init = StringMap.empty in
List.fold_left locs ~init ~f:(fun acc (loc : Warnings.loc) ->
let path = loc.loc_start.pos_fname in
let uri = DocumentUri.of_path path in
let range = Range.of_loc loc in
let make_edit () = TextEdit.create ~range ~newText:newName in
match
let occur_start_pos =
Position.of_lexical_position loc.loc_start |> Option.value_exn
in
occur_start_pos
with
| { character = 0; _ } -> make_edit ()
| pos -> (
let mpos = Position.logical pos in
let (`Offset index) = Msource.get_offset source mpos in
assert (index > 0)
(* [index = 0] if we pass [`Logical (1, 0)], but we handle the case
when [character = 0] in a separate matching branch *);
let source_txt = Msource.text source in
match source_txt.[index - 1] with
| '~' (* the occurrence is a named argument *)
| '?' (* is an optional argument *) ->
let empty_range_at_occur_end =
let occur_end_pos = range.Range.end_ in
{ range with start = occur_end_pos }
in
TextEdit.create
~range:empty_range_at_occur_end
~newText:(":" ^ newName)
| _ -> make_edit ()))
let edit =
(* TODO: to perform correct renaming we need a way to load all the
impacted documents *)
match Document_store.get state.store uri with
| exception _ -> make_edit ()
| doc -> (
let source = Document.source doc in
match
let occur_start_pos =
Position.of_lexical_position loc.loc_start |> Option.value_exn
in
occur_start_pos
with
| { character = 0; _ } -> make_edit ()
| pos -> (
let mpos = Position.logical pos in
let (`Offset index) = Msource.get_offset source mpos in
assert (index > 0)
(* [index = 0] if we pass [`Logical (1, 0)], but we handle the
case when [character = 0] in a separate matching branch *);
let source_txt = Msource.text source in
match source_txt.[index - 1] with
| '~' (* the occurrence is a named argument *)
| '?' (* is an optional argument *) ->
let empty_range_at_occur_end =
let occur_end_pos = range.Range.end_ in
{ range with start = occur_end_pos }
in
TextEdit.create
~range:empty_range_at_occur_end
~newText:(":" ^ newName)
| _ -> make_edit ()))
in
StringMap.add_multi acc path edit)
in
let workspace_edits =
let documentChanges =
let open Option.O in
Option.value
~default:false
(let client_capabilities = State.client_capabilities state in
let* workspace = client_capabilities.workspace in
let* edit = workspace.workspaceEdit in
edit.documentChanges)
in
if documentChanges then
let textDocument =
OptionalVersionedTextDocumentIdentifier.create ~uri ~version ()
in
let edits = List.map edits ~f:(fun e -> `TextEdit e) in
WorkspaceEdit.create
~documentChanges:
[ `TextDocumentEdit (TextDocumentEdit.create ~textDocument ~edits) ]
()
else WorkspaceEdit.create ~changes:[ (uri, edits) ] ()
(* TODO: use documentChanges*)
WorkspaceEdit.create
~changes:
(StringMap.to_list_map edits ~f:(fun path edits ->
(DocumentUri.of_path path, edits)))
()
in
workspace_edits

0 comments on commit 1c3ebfd

Please sign in to comment.