Skip to content

Commit

Permalink
Use Document.Changes instead of CodeMod.Rename.DocumentChanges
Browse files Browse the repository at this point in the history
  • Loading branch information
scottming committed Mar 24, 2024
1 parent 5e491da commit 4d41168
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
defmodule Lexical.RemoteControl.CodeMod.Rename do
alias Lexical.Ast.Analysis
alias Lexical.Document
alias Lexical.Document.Position
alias Lexical.Document.Range
alias Lexical.RemoteControl.CodeMod.Rename.DocumentChanges
alias __MODULE__

@spec prepare(Analysis.t(), Position.t()) ::
Expand All @@ -14,7 +14,7 @@ defmodule Lexical.RemoteControl.CodeMod.Rename do
@rename_mapping %{module: Rename.Module}

@spec rename(Analysis.t(), Position.t(), String.t()) ::
{:ok, [DocumentChanges.t()]} | {:error, term()}
{:ok, [Document.Changes.t()]} | {:error, term()}
def rename(%Analysis{} = analysis, %Position{} = position, new_name) do
case Rename.Prepare.resolve(analysis, position) do
{:ok, {renamable, entity}, range} ->
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,22 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
alias Lexical.Document.Range
alias Lexical.RemoteControl.CodeIntelligence.Entity
alias Lexical.RemoteControl.CodeMod.Rename
alias Lexical.RemoteControl.CodeMod.Rename.DocumentChanges
alias Lexical.RemoteControl.Search.Store
require Logger

import Line

@spec rename(Range.t(), String.t(), atom()) :: [DocumentChanges.t()]
@spec rename(Range.t(), String.t(), atom()) :: [Document.Changes.t()]
def rename(%Range{} = old_range, new_name, entity) do
{old_suffix, new_suffix} = old_range |> range_text() |> diff(new_name)
results = exacts(entity, old_suffix) ++ descendants(entity, old_suffix)

results
|> Enum.group_by(&Document.Path.ensure_uri(&1.path))
|> Enum.map(fn {uri, entries} ->
rename_file = maybe_rename_file(entries, new_suffix)
edits = Enum.map(entries, &Edit.new(new_suffix, &1.range))
DocumentChanges.new(uri, edits, rename_file)
end)
for {uri, entries} <- Enum.group_by(results, &Document.Path.ensure_uri(&1.path)),
result = to_document_changes(uri, entries, new_suffix),
match?({:ok, _}, result) do
{:ok, document_changes} = result
document_changes
end
end

@spec resolve(Analysis.t(), Position.t()) ::
Expand Down Expand Up @@ -162,4 +160,13 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
|> put_in([:start, :character], start_character)
|> put_in([:end, :character], end_character)
end

defp to_document_changes(uri, entries, new_suffix) do
edits = Enum.map(entries, &Edit.new(new_suffix, &1.range))
rename_file = maybe_rename_file(entries, new_suffix)

with {:ok, document} <- Document.Store.open_temporary(uri) do
{:ok, Document.Changes.new(document, edits, rename_file)}
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -469,13 +469,13 @@ defmodule Lexical.RemoteControl.CodeMod.RenameTest do
{:ok, entries} <- Search.Indexer.Source.index(document.path, text),
:ok <- Search.Store.replace(entries),
analysis = Lexical.Ast.analyze(document),
{:ok, uri_with_changes} <- Rename.rename(analysis, position, new_name) do
changes = uri_with_changes |> Enum.map(& &1.edits) |> List.flatten()
{:ok, document_changes} <- Rename.rename(analysis, position, new_name) do
changes = document_changes |> Enum.map(& &1.edits) |> List.flatten()
applied = apply_edits(document, changes)

result =
if path do
rename_file = uri_with_changes |> Enum.map(& &1.rename_file) |> List.first()
rename_file = document_changes |> Enum.map(& &1.rename_file) |> List.first()
{applied, rename_file}
else
applied
Expand Down
5 changes: 2 additions & 3 deletions apps/server/lib/lexical/server/provider/handlers/rename.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ defmodule Lexical.Server.Provider.Handlers.Rename do
alias Lexical.Protocol.Types.TextDocument
alias Lexical.Protocol.Types.Workspace
alias Lexical.RemoteControl.Api
alias Lexical.RemoteControl.CodeMod.Rename.DocumentChanges
alias Lexical.Server.Provider.Env
require Logger

Expand All @@ -29,8 +28,8 @@ defmodule Lexical.Server.Provider.Handlers.Rename do

{:ok, results} ->
text_document_edits =
Enum.map(results, fn %DocumentChanges{edits: edits, uri: uri} ->
new_text_document_edit(uri, edits)
Enum.map(results, fn %Document.Changes{edits: edits, document: document} ->
new_text_document_edit(document.uri, edits)
end)

rename_files =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ defmodule Lexical.Server.Provider.Handlers.RenameTest do
alias Lexical.Proto.Convert
alias Lexical.Protocol.Requests.Rename
alias Lexical.RemoteControl
alias Lexical.RemoteControl.CodeMod.Rename.DocumentChanges

alias Lexical.Server
alias Lexical.Server.Provider.Env
Expand Down Expand Up @@ -74,22 +73,24 @@ defmodule Lexical.Server.Provider.Handlers.RenameTest do
end

test "returns edit when there are changes", %{project: project, uri: uri} do
document = %Document{uri: uri, version: 0}

patch(Document.Store, :fetch, fn ^uri, :analysis ->
{:ok, nil, %Ast.Analysis{valid?: true}}
end)

patch(RemoteControl.Api, :rename, fn ^project, _analysis, _position, _new_name ->
{:ok,
[
DocumentChanges.new(
"file:///path/to/file.ex",
Document.Changes.new(
document,
[
%{
new_text: "new_text",
range: %{start: %{line: 1, character: 5}, end: %{line: 1, character: 10}}
}
],
{"file:///path/to/file.ex", "file:///path/to/new_text.ex"}
{document.uri, "file:///path/to/new_text.ex"}
)
]}
end)
Expand All @@ -106,9 +107,9 @@ defmodule Lexical.Server.Provider.Handlers.RenameTest do
}
]

assert edit.text_document.uri == "file:///path/to/file.ex"
assert edit.text_document.uri == document.uri
assert edit.text_document.version == 0
assert rename_file.old_uri == "file:///path/to/file.ex"
assert rename_file.old_uri == document.uri
assert rename_file.new_uri == "file:///path/to/new_text.ex"
end
end
Expand Down
11 changes: 9 additions & 2 deletions projects/lexical_shared/lib/lexical/document/changes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ defmodule Lexical.Document.Changes do
Using this struct allows efficient conversions at the language server border, as the document
doesn't have to be looked up (and possibly read off the filesystem) by the language server.
"""
defstruct [:document, :edits]
defstruct [:document, :edits, :rename_file]
alias Lexical.Document

use Lexical.StructAccess

@type edits :: Document.Edit.t() | [Document.Edit.t()]
@type rename_file :: nil | {Lexical.uri(), Lexical.uri()}

This comment has been minimized.

Copy link
@scohen

scohen Mar 25, 2024

Collaborator

maybe make this a record or a struct? I think a struct would be a little clearer.

defmodule Rename do
  defstruct [:from, :to]

  def new(from, to), do: %__MODULE__{from: from, to: to}
@type t :: %__MODULE__{
document: Document.t(),
edits: edits
edits: edits,
rename_file: rename_file()
}

@doc """
Expand All @@ -28,4 +30,9 @@ defmodule Lexical.Document.Changes do
def new(document, edits) do
%__MODULE__{document: document, edits: edits}
end

@spec new(Document.t(), edits(), rename_file()) :: t()
def new(document, edits, rename_file) do
%__MODULE__{document: document, edits: edits, rename_file: rename_file}
end
end

0 comments on commit 4d41168

Please sign in to comment.