Skip to content

Commit

Permalink
Change uri_with_operation_counts to uri_with_expected_operation
Browse files Browse the repository at this point in the history
and special some message type for emacs
  • Loading branch information
scottming committed Apr 21, 2024
1 parent 5e895b9 commit a36ad78
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 115 deletions.
15 changes: 11 additions & 4 deletions apps/remote_control/lib/lexical/remote_control/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@ defmodule Lexical.RemoteControl.Api do
defdelegate schedule_compile(project, force?), to: Build
defdelegate compile_document(project, document), to: Build

def maybe_schedule_compile(project, triggered_file_uri) do
RemoteControl.call(project, Build, :maybe_schedule_compile, [triggered_file_uri])
def maybe_schedule_compile(project, triggered_file_uri, triggered_message) do
RemoteControl.call(project, Build, :maybe_schedule_compile, [
triggered_file_uri,
triggered_message
])
end

def maybe_compile_document(project, document) do
RemoteControl.call(project, Build, :maybe_compile_document, [project, document])
def maybe_compile_document(project, document, triggered_message) do
RemoteControl.call(project, Build, :maybe_compile_document, [
project,
document,
triggered_message
])
end

def expand_alias(
Expand Down
8 changes: 4 additions & 4 deletions apps/remote_control/lib/lexical/remote_control/build.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ defmodule Lexical.RemoteControl.Build do
:ok
end

def maybe_schedule_compile(triggered_file_uri) do
def maybe_schedule_compile(triggered_file_uri, message) do
if Rename.in_progress?() do
Rename.mark_saved(triggered_file_uri)
Rename.update_progress(triggered_file_uri, message)
else
GenServer.cast(__MODULE__, {:compile, false})
end
end

def maybe_compile_document(%Project{} = project, %Document{} = document) do
def maybe_compile_document(%Project{} = project, %Document{} = document, message) do
if Rename.in_progress?() do
Rename.mark_changed(document.uri)
Rename.update_progress(document.uri, message)
else
compile_document(project, document)
end
Expand Down
25 changes: 13 additions & 12 deletions apps/remote_control/lib/lexical/remote_control/code_mod/rename.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ defmodule Lexical.RemoteControl.CodeMod.Rename do
alias Lexical.Document
alias Lexical.Document.Position
alias Lexical.Document.Range
alias Lexical.Protocol.Notifications.DidChange
alias Lexical.Protocol.Notifications.DidSave
alias Lexical.RemoteControl.Commands

alias __MODULE__

@spec prepare(Analysis.t(), Position.t()) ::
Expand All @@ -25,35 +28,33 @@ defmodule Lexical.RemoteControl.CodeMod.Rename do

defp set_rename_progress(document_changes_list, client_name) do
client_name
|> uri_with_operation_counts(document_changes_list)
|> uri_with_expected_operation(document_changes_list)
|> Commands.Rename.set_rename_progress()
end

defp uri_with_operation_counts("Visual Studio Code", document_changes_list) do
defp uri_with_expected_operation(client_name, document_changes_list)
when client_name in ["Visual Studio Code", "emacs"] do
document_changes_list
|> Enum.flat_map(fn %Document.Changes{document: document, rename_file: rename_file} ->
if rename_file do
# first operation is for `DidChange` in the old file,
# Note: `DidSave` won't be received for the old file
# second operation is for `DidSave` in the new file
[{rename_file.old_uri, 1}, {rename_file.new_uri, 1}]
# when the file is renamed, we won't receive `DidSave` for the old file
[{rename_file.old_uri, DidChange}, {rename_file.new_uri, DidSave}]
else
[{document.uri, 2}]
[{document.uri, DidSave}]
end
end)
|> Map.new()
end

defp uri_with_operation_counts(_, document_changes_list) do
defp uri_with_expected_operation(_, document_changes_list) do
document_changes_list
|> Enum.flat_map(fn %Document.Changes{document: document, rename_file: rename_file} ->
if rename_file do
# first operation is for `DidChange`
# second operation is for `DidSave`
[{document.uri, 2}]
[{document.uri, DidSave}]
else
# Some editors do not directly save the file after renaming, such as *neovim*.
# when the file is not renamed, we'll only received `DidChange` for the old file
[{document.uri, 1}]
[{document.uri, DidChange}]
end
end)
|> Map.new()
Expand Down
71 changes: 22 additions & 49 deletions apps/remote_control/lib/lexical/remote_control/commands/rename.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,28 @@ defmodule Lexical.RemoteControl.Commands.Rename do
Therefore, we need this module to make some markings to determine whether it is currently in the process of renaming.
"""
defmodule State do
defstruct uri_with_operation_counts: %{}
defstruct uri_with_expected_operation: %{}

def new(uri_with_operation_counts) do
%__MODULE__{uri_with_operation_counts: uri_with_operation_counts}
def new(uri_with_expected_operation) do
%__MODULE__{uri_with_expected_operation: uri_with_expected_operation}
end

def mark_changed(%__MODULE__{} = state, uri) do
new_uri_with_operation_counts =
delete_key_or_reduce_counts(state.uri_with_operation_counts, uri)
def update_progress(%__MODULE__{} = state, uri, operation_message) do
new_uri_with_expected_operation =
maybe_pop_expected_operation(state.uri_with_expected_operation, uri, operation_message)

%__MODULE__{state | uri_with_operation_counts: new_uri_with_operation_counts}
end

def mark_saved(%__MODULE__{} = state, uri) do
new_uri_with_operation_counts =
delete_key_or_reduce_counts(state.uri_with_operation_counts, uri)

%__MODULE__{state | uri_with_operation_counts: new_uri_with_operation_counts}
%__MODULE__{state | uri_with_expected_operation: new_uri_with_expected_operation}
end

def in_progress?(%__MODULE__{} = state) do
state.uri_with_operation_counts != %{}
state.uri_with_expected_operation != %{}
end

defp delete_key_or_reduce_counts(uri_with_operation_counts, uri) do
{_, new_map} =
Map.get_and_update(uri_with_operation_counts, uri, fn
nil -> :pop
current_counts when current_counts <= 1 -> :pop
current_counts -> {current_counts, current_counts - 1}
end)

new_map
def maybe_pop_expected_operation(uri_to_operation, uri, %operation{}) do
case uri_to_operation do
%{^uri => ^operation} -> Map.delete(uri_to_operation, uri)
_ -> uri_to_operation
end
end
end

Expand All @@ -53,17 +42,13 @@ defmodule Lexical.RemoteControl.Commands.Rename do
{:ok, state}
end

@spec set_rename_progress(%{Lexical.uri() => integer()}) :: :ok
def set_rename_progress(uri_with_operation_counts) do
GenServer.cast(__MODULE__, {:set_rename_progress, uri_with_operation_counts})
@spec set_rename_progress(%{Lexical.uri() => atom()}) :: :ok
def set_rename_progress(uri_with_expected_operation) do
GenServer.cast(__MODULE__, {:set_rename_progress, uri_with_expected_operation})
end

def mark_changed(uri) do
GenServer.cast(__MODULE__, {:mark_changed, uri})
end

def mark_saved(uri) do
GenServer.cast(__MODULE__, {:mark_saved, uri})
def update_progress(uri, operation_message) do
GenServer.cast(__MODULE__, {:update_progress, uri, operation_message})
end

def in_progress? do
Expand All @@ -76,26 +61,14 @@ defmodule Lexical.RemoteControl.Commands.Rename do
end

@impl true
def handle_cast({:set_rename_progress, uri_with_operation_counts}, _state) do
new_state = State.new(uri_with_operation_counts)
{:noreply, new_state}
end

@impl true
def handle_cast({:mark_changed, uri}, %State{} = state) do
new_state = State.mark_changed(state, uri)
{:noreply, new_state}
end

@impl true
def handle_cast({:mark_saved, uri}, %State{} = state) do
new_state = State.mark_saved(state, uri)
def handle_cast({:set_rename_progress, uri_with_expected_operation}, _state) do
new_state = State.new(uri_with_expected_operation)
{:noreply, new_state}
end

@impl true
def handle_cast({:mark_closed, uri}, %State{} = state) do
new_state = State.mark_closed(state, uri)
def handle_cast({:update_progress, uri, message}, state) do
new_state = State.update_progress(state, uri, message)
{:noreply, new_state}
end
end

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
defmodule Lexical.RemoteControl.Commands.RenameTest do
alias Lexical.RemoteControl.Commands.Rename

defmodule FakeDidChange do
defstruct [:field]
end

defmodule FakeDidSave do
defstruct [:field]
end

use ExUnit.Case
use Patch

Expand All @@ -10,17 +18,25 @@ defmodule Lexical.RemoteControl.Commands.RenameTest do
end

test "it should mark the `in_progress` as `true` when a rename is in progress." do
assert :ok = Rename.set_rename_progress(%{"file://file.ex" => 3})
assert :ok = Rename.set_rename_progress(%{"file://file.ex" => FakeDidChange})
assert Rename.in_progress?()
end

test "it should mark the `in_progress` as false when a rename is done" do
file_uri = "file://file.ex"
Rename.set_rename_progress(%{file_uri => 2})

Rename.mark_changed(file_uri)
Rename.mark_saved(file_uri)
Rename.set_rename_progress(%{file_uri => FakeDidSave})
Rename.update_progress(file_uri, %FakeDidSave{})

refute Rename.in_progress?()
end

test "it should still in progress if there are files yet to be saved." do
uri1 = "file://file1.ex"
uri2 = "file://file2.ex"

Rename.set_rename_progress(%{uri1 => FakeDidChange, uri2 => FakeDidSave})
Rename.update_progress(uri1, %FakeDidChange{})

assert Rename.in_progress?()
end
end
8 changes: 4 additions & 4 deletions apps/server/lib/lexical/server/state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ defmodule Lexical.Server.State do
{:ok, state}
end

def apply(%__MODULE__{} = state, %DidChange{lsp: event}) do
def apply(%__MODULE__{} = state, %DidChange{lsp: event} = message) do
uri = event.text_document.uri
version = event.text_document.version
project = state.configuration.project
Expand All @@ -162,7 +162,7 @@ defmodule Lexical.Server.State do
)

Api.broadcast(project, updated_message)
Api.maybe_compile_document(state.configuration.project, updated_source)
Api.maybe_compile_document(state.configuration.project, updated_source, message)
{:ok, state}

error ->
Expand Down Expand Up @@ -207,12 +207,12 @@ defmodule Lexical.Server.State do
end
end

def apply(%__MODULE__{} = state, %DidSave{lsp: event}) do
def apply(%__MODULE__{} = state, %DidSave{lsp: event} = message) do
uri = event.text_document.uri

case Document.Store.save(uri) do
:ok ->
Api.maybe_schedule_compile(state.configuration.project, uri)
Api.maybe_schedule_compile(state.configuration.project, uri, message)
{:ok, state}

error ->
Expand Down

0 comments on commit a36ad78

Please sign in to comment.