Skip to content

Commit

Permalink
Fix the issue caused by organizing aliases.
Browse files Browse the repository at this point in the history
When I'm writing functions, I occasionally need to handle unused variables, but I find that organizing aliases still returns results. This causes a lot of interference, especially when there's a bug in nvim, as pressing keys quickly can mess up my code.

We should not return the results of organizing aliases when the cursor is not on a line with an alias or when the current token is not an alias.
  • Loading branch information
scottming committed Jun 1, 2024
1 parent cc5c2f9 commit b56add8
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
defmodule Lexical.RemoteControl.CodeAction.Handlers.OrganizeAliases do
alias Lexical.Ast
alias Lexical.Ast.Analysis
alias Lexical.Ast.Analysis.Scope
alias Lexical.Document
alias Lexical.Document.Changes
alias Lexical.Document.Position
alias Lexical.Document.Range
alias Lexical.RemoteControl
alias Lexical.RemoteControl.CodeAction
alias Lexical.RemoteControl.CodeMod

Expand Down Expand Up @@ -37,9 +40,32 @@ defmodule Lexical.RemoteControl.CodeAction.Handlers.OrganizeAliases do
end

defp check_aliases(%Document{}, %Analysis{} = analysis, %Range{} = range) do
case Analysis.module_scope(analysis, range) do
%Scope{aliases: [_ | _]} -> :ok
_ -> :error
with %Scope{aliases: [_ | _]} <- Analysis.module_scope(analysis, range),
true <-
ancestor_is_alias?(analysis, range.start) or
token_at_cursor_is_alias?(analysis, range.start) do
:ok
else
_ ->
:error
end
end

defp ancestor_is_alias?(%Analysis{} = analysis, %Position{} = position) do
analysis
|> Ast.cursor_path(position)
|> Enum.any?(fn
{:alias, _, _} ->
true

_ ->
false
end)
end

defp token_at_cursor_is_alias?(%Analysis{} = analysis, %Position{} = position) do
project = RemoteControl.get_project()
{:ok, env} = Ast.Env.new(project, analysis, position)
(env.prefix <> env.suffix) |> String.trim_leading() |> String.starts_with?("alias")
end
end
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
defmodule Lexical.RemoteControl.CodeAction.Handlers.OrganizeAliasesTest do
alias Lexical.Document
alias Lexical.Document.Range
alias Lexical.RemoteControl
alias Lexical.RemoteControl.CodeAction.Handlers.OrganizeAliases

import Lexical.Test.CursorSupport
import Lexical.Test.CodeSigil

use Lexical.Test.CodeMod.Case, enable_ast_conversion: false
use Patch

setup do
start_supervised!({Document.Store, derive: [analysis: &Lexical.Ast.analyze/1]})
Expand Down Expand Up @@ -90,6 +92,8 @@ defmodule Lexical.RemoteControl.CodeAction.Handlers.OrganizeAliasesTest do

describe "at the top of a module" do
test "does nothing if there are no aliases" do
patch(RemoteControl, :get_project, %Lexical.Project{})

{:ok, organized} =
~q[
defmodule Nothing do
Expand Down Expand Up @@ -219,6 +223,8 @@ defmodule Lexical.RemoteControl.CodeAction.Handlers.OrganizeAliasesTest do
end

test "aliases in a given scope are pulled to the top" do
patch(RemoteControl, :get_project, %Lexical.Project{})

{:ok, organized} =
~q[
defmodule Scattered do
Expand Down Expand Up @@ -316,4 +322,90 @@ defmodule Lexical.RemoteControl.CodeAction.Handlers.OrganizeAliasesTest do
assert expected == organized
end
end

describe "check the return conditions for the alias" do
test "returns organized aliases if the cursor is at an alias" do
patch(RemoteControl, :get_project, %Lexical.Project{})

{:ok, organized} =
~q[
defmodule Outer do
|alias Foo.Bar
alias A.B.C
alias D.E.F
end] |> organize_aliases()

expected =
~q[
defmodule Outer do
alias A.B.C
alias D.E.F
alias Foo.Bar
end]

assert expected == organized
end

test "returns organized aliases if the cursor's ancesor is an alias" do
{:ok, organized} =
~q[
defmodule Outer do
alias Foo.|Bar
alias A.B.C
alias D.E.F
end] |> organize_aliases()

expected =
~q[
defmodule Outer do
alias A.B.C
alias D.E.F
alias Foo.Bar
end]

assert expected == organized
end

test "does nothing if the cursor is at an `def` keyword" do
patch(RemoteControl, :get_project, %Lexical.Project{})

text =
~q[
defmodule Outer do
alias Foo.Bar
alias A.B.C
alias D.E.F
|def my_fn do
1 + 2
end
end]

{:ok, organized} = organize_aliases(text)

{_, original} = pop_cursor(text)
assert original == organized
end

test "does nothing if the cursor is at the function name" do
patch(RemoteControl, :get_project, %Lexical.Project{})

text =
~q[
defmodule Outer do
alias Foo.Bar
alias A.B.C
alias D.E.F
def |my_fn do
1 + 2
end
end]

{:ok, organized} = organize_aliases(text)

{_, original} = pop_cursor(text)
assert original == organized
end
end
end

0 comments on commit b56add8

Please sign in to comment.