Skip to content

Commit

Permalink
Move the prepare logic to a individual module
Browse files Browse the repository at this point in the history
  • Loading branch information
scottming committed Mar 29, 2024
1 parent d2e252d commit fc8eb94
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
defmodule Lexical.RemoteControl.CodeMod.Rename do
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
alias Lexical.Ast.Analysis
alias Lexical.Document
alias Lexical.Document.Edit
alias Lexical.Document.Line
alias Lexical.Document.Position
alias Lexical.Document.Range
alias Lexical.RemoteControl.CodeIntelligence.Entity
alias Lexical.RemoteControl.CodeMod.Rename.Prepare
alias Lexical.RemoteControl.Search.Store
require Logger

import Line

@spec rename(Analysis.t(), Position.t(), String.t()) ::
{:ok, %{Lexical.uri() => [Edit.t()]}} | {:error, term()}
def rename(%Analysis{} = analysis, %Position{} = position, new_name) do
with {:ok, entity, range} <- resolve_module(analysis, position) do
with {:ok, entity, range} <- Prepare.resolve_module(analysis, position) do
edits =
analysis.document
|> search_related_candidates(position, entity, range)
Expand All @@ -25,32 +21,8 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
end
end

@spec prepare(Analysis.t(), Position.t()) :: {:ok, String.t(), Range.t()} | {:error, term()}
def prepare(%Analysis{} = analysis, %Position{} = position) do
case resolve_module(analysis, position) do
{:ok, _, range} ->
{:ok, local_module_name(range), range}

{:error, _} ->
{:error, :unsupported_entity}
end
end

defp resolve_module(analysis, position) do
case Entity.resolve(analysis, position) do
{:ok, {module_or_struct, module}, range} when module_or_struct in [:struct, :module] ->
{:ok, module, range}

{:ok, other, _} ->
{:error, {:unsupported_entity, other}}

{:error, reason} ->
{:error, reason}
end
end

defp search_related_candidates(document, position, entity, range) do
local_module_name = local_module_name(range)
local_module_name = Prepare.local_module_name(range)
entities = exacts(entity, local_module_name)

# Users won't always want to rename descendants of a module.
Expand All @@ -69,7 +41,7 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
end

defp at_the_middle_of_module?(document, position, range) do
range_text = range_text(range)
range_text = Prepare.range_text(range)

case Ast.surround_context(document, position) do
{:ok, %{context: {:alias, alias}}} ->
Expand Down Expand Up @@ -99,11 +71,11 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
end

defp entry_matching?(entry, local_module_name) do
entry.range |> range_text() |> String.contains?(local_module_name)
entry.range |> Prepare.range_text() |> String.contains?(local_module_name)
end

defp has_dots_in_range?(entry) do
entry.range |> range_text() |> String.contains?(".")
entry.range |> Prepare.range_text() |> String.contains?(".")
end

defp adjust_range(entries, entity) do
Expand All @@ -119,7 +91,7 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
defp resolve_local_module_range(uri, position, entity) do
with {:ok, _} <- Document.Store.open_temporary(uri),
{:ok, document, analysis} <- Document.Store.fetch(uri, :analysis),
{:ok, result, range} <- resolve_module(analysis, position) do
{:ok, result, range} <- Prepare.resolve_module(analysis, position) do
if result == entity do
{:ok, range}
else
Expand All @@ -142,7 +114,7 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
results,
&Document.Path.ensure_uri(&1.path),
fn result ->
local_module_name_length = result.range |> local_module_name() |> String.length()
local_module_name_length = result.range |> Prepare.local_module_name() |> String.length()
# e.g: `Parent.|ToBeRenameModule`, we need the start position of `ToBeRenameModule`
start_character = result.range.end.character - local_module_name_length
start_position = %{result.range.start | character: start_character}
Expand All @@ -152,13 +124,4 @@ defmodule Lexical.RemoteControl.CodeMod.Rename.Module do
end
)
end

defp range_text(range) do
line(text: text) = range.end.context_line
String.slice(text, range.start.character - 1, range.end.character - range.start.character)
end

defp local_module_name(%Range{} = range) do
range |> range_text() |> Ast.Module.local_name()
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule Lexical.RemoteControl.CodeMod.Rename.Prepare do
alias Lexical.Ast
alias Lexical.Ast.Analysis
alias Lexical.Document.Position
alias Lexical.Document.Line
alias Lexical.Document.Range
alias Lexical.RemoteControl.CodeIntelligence.Entity

import Line

@spec prepare(Analysis.t(), Position.t()) :: {:ok, String.t(), Range.t()} | {:error, term()}
def prepare(%Analysis{} = analysis, %Position{} = position) do
case resolve_module(analysis, position) do
{:ok, _, range} ->
{:ok, local_module_name(range), range}

{:error, _} ->
{:error, :unsupported_entity}
end
end

def resolve_module(analysis, position) do
case Entity.resolve(analysis, position) do
{:ok, {module_or_struct, module}, range} when module_or_struct in [:struct, :module] ->
{:ok, module, range}

{:ok, other, _} ->
{:error, {:unsupported_entity, other}}

{:error, reason} ->
{:error, reason}
end
end

def range_text(range) do
line(text: text) = range.end.context_line
String.slice(text, range.start.character - 1, range.end.character - range.start.character)
end

def local_module_name(%Range{} = range) do
range |> range_text() |> Ast.Module.local_name()
end
end

0 comments on commit fc8eb94

Please sign in to comment.