Skip to content
This repository was archived by the owner on Oct 8, 2025. It is now read-only.

Commit dd673f3

Browse files
committed
Fix get_surrounding_module/2 ast helper
1 parent df9f0bb commit dd673f3

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

lib/next_ls/commands/alias.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ defmodule NextLS.Commands.Alias do
2525
def run(opts) do
2626
with {:ok, %{text: text, uri: uri, position: position}} <- unify(opts(), Map.new(opts)),
2727
{:ok, ast} = parse(text),
28-
{:ok, defm} <- ASTHelpers.get_nearest_module(ast, position),
28+
{:ok, defm} <- ASTHelpers.get_surrounding_module(ast, position),
2929
{:ok, {:__aliases__, _, modules}} <- get_node(ast, position) do
3030
range = make_range(defm)
3131
indent = EditHelpers.get_indent(text, range.start.line)

lib/next_ls/extensions/elixir_extension/code_action/require.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ defmodule NextLS.ElixirExtension.CodeAction.Require do
1616

1717
with {:ok, require_module} <- get_edit(diagnostic.message),
1818
{:ok, ast} <- parse_ast(text),
19-
{:ok, defm} <- ASTHelpers.get_nearest_module(ast, range.start),
19+
{:ok, defm} <- ASTHelpers.get_surrounding_module(ast, range.start),
2020
indentation <- get_indent(text, defm),
2121
nearest <- find_nearest_node_for_require(defm),
2222
range <- get_edit_range(nearest) do

lib/next_ls/helpers/ast_helpers.ex

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,15 @@ defmodule NextLS.ASTHelpers do
154154
end)
155155
end
156156

157-
@spec get_nearest_module(ast :: Macro.t(), position :: Position.t()) :: {:ok, Macro.t()} | {:error, String.t()}
158-
def get_nearest_module(ast, position) do
157+
@spec get_surrounding_module(ast :: Macro.t(), position :: Position.t()) :: {:ok, Macro.t()} | {:error, String.t()}
158+
def get_surrounding_module(ast, position) do
159159
defm =
160160
ast
161161
|> Macro.prewalker()
162162
|> Enum.filter(fn node -> match?({:defmodule, _, _}, node) end)
163+
|> Enum.filter(fn {_, ctx, _} ->
164+
position.line + 1 - ctx[:line] >= 0
165+
end)
163166
|> Enum.min_by(
164167
fn {_, ctx, _} ->
165168
abs(ctx[:line] - 1 - position.line)

test/next_ls/helpers/ast_helpers_test.exs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ defmodule NextLS.ASTHelpersTest do
7676
end
7777
end
7878

79-
describe "find_nearest_module/2" do
79+
describe "get_surrounding_module/2" do
8080
test "finds the nearest defmodule definition in the ast" do
8181
{:ok, ast} =
8282
Spitfire.parse("""
@@ -95,18 +95,18 @@ defmodule NextLS.ASTHelpersTest do
9595

9696
for line <- lines do
9797
position = %Position{line: line, character: 0}
98-
assert {:ok, {:defmodule, _, [{:__aliases__, _, [:Foo]} | _]}} = ASTHelpers.get_nearest_module(ast, position)
98+
assert {:ok, {:defmodule, _, [{:__aliases__, _, [:Foo]} | _]}} = ASTHelpers.get_surrounding_module(ast, position)
9999
end
100100

101101
lines = 5..7
102102

103103
for line <- lines do
104104
position = %Position{line: line, character: 0}
105-
assert {:ok, {:defmodule, _, [{:__aliases__, _, [:Bar]} | _]}} = ASTHelpers.get_nearest_module(ast, position)
105+
assert {:ok, {:defmodule, _, [{:__aliases__, _, [:Bar]} | _]}} = ASTHelpers.get_surrounding_module(ast, position)
106106
end
107107

108108
position = %Position{line: 0, character: 0}
109-
assert {:ok, {:defmodule, _, [{:__aliases__, _, [:Test]} | _]}} = ASTHelpers.get_nearest_module(ast, position)
109+
assert {:ok, {:defmodule, _, [{:__aliases__, _, [:Test]} | _]}} = ASTHelpers.get_surrounding_module(ast, position)
110110
end
111111

112112
test "errors out when it can't find a module" do
@@ -116,7 +116,25 @@ defmodule NextLS.ASTHelpersTest do
116116
""")
117117

118118
position = %Position{line: 0, character: 0}
119-
assert {:error, "no defmodule definition"} = ASTHelpers.get_nearest_module(ast, position)
119+
assert {:error, "no defmodule definition"} = ASTHelpers.get_surrounding_module(ast, position)
120+
end
121+
122+
test "it finds the nearest surrounding module" do
123+
{:ok, ast} =
124+
Spitfire.parse("""
125+
defmodule Test do
126+
alias Foo
127+
alias Bar
128+
alias Baz
129+
130+
defmodule Quix do
131+
defstruct [:key]
132+
end
133+
end
134+
""")
135+
136+
position = %Position{line: 4, character: 0}
137+
assert {:ok, {:defmodule, _, [{:__aliases__, _, [:Test]} | _]}} = ASTHelpers.get_surrounding_module(ast, position)
120138
end
121139
end
122140
end

0 commit comments

Comments
 (0)