Skip to content

Commit

Permalink
add find_var
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszsamson committed Sep 18, 2024
1 parent c868a18 commit b802c3d
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 50 deletions.
32 changes: 18 additions & 14 deletions lib/elixir_sense/core/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1600,13 +1600,15 @@ defmodule ElixirSense.Core.Compiler do
)
when module != nil and
def_kind in [:def, :defp, :defmacro, :defmacrop, :defguard, :defguardp] do
state =
case call do
{:__cursor__, _, list} when is_list(list) ->
{_, state, _} = expand(call, state, %{env | function: {:__unknown__, 0}})
state

state = case call do
{:__cursor__, _, list} when is_list(list) ->
{_, state, _} = expand(call, state, %{env | function: {:__unknown__, 0}})
state
_ -> state
end
_ ->
state
end

state_orig = state

Expand Down Expand Up @@ -1825,14 +1827,16 @@ defmodule ElixirSense.Core.Compiler do
{{{:., meta, [module, fun]}, meta, args}, state, env}
else
ast ->
state = if __MODULE__.Utils.has_cursor?(args) and not __MODULE__.Utils.has_cursor?(ast) do
# in case there was cursor in the original args but it's not present in macro result
# expand a fake node
{_ast, state, _env} = expand({:__cursor__, [], []}, state, env)
state
else
state
end
state =
if __MODULE__.Utils.has_cursor?(args) and not __MODULE__.Utils.has_cursor?(ast) do
# in case there was cursor in the original args but it's not present in macro result
# expand a fake node
{_ast, state, _env} = expand({:__cursor__, [], []}, state, env)
state
else
state
end

{ast, state, env} = expand(ast, state, env)
{ast, state, env}
end
Expand Down
44 changes: 15 additions & 29 deletions lib/elixir_sense/core/metadata.ex
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,8 @@ defmodule ElixirSense.Core.Metadata do
{end_line, end_column}
])

# IO.puts(metadata.source)
# dbg(needle)
source_with_cursor = prefix <> "__cursor__(#{needle})" <> suffix
# IO.puts(source_with_cursor)
# dbg(metadata)

{prefix, source_with_cursor}

nil ->
Expand All @@ -98,8 +95,6 @@ defmodule ElixirSense.Core.Metadata do
{prefix, source_with_cursor}
end

# IO.puts(source_with_cursor)

{meta, cursor_env} =
case Code.string_to_quoted(source_with_cursor, columns: true, token_metadata: true) do
{:ok, ast} ->
Expand All @@ -113,6 +108,7 @@ defmodule ElixirSense.Core.Metadata do
if cursor_env != nil do
{meta, cursor_env}
else
# IO.puts(prefix <> "|")
case NormalizedCode.Fragment.container_cursor_to_quoted(prefix,
columns: true,
token_metadata: true
Expand All @@ -129,8 +125,7 @@ defmodule ElixirSense.Core.Metadata do
cursor_env
else
case metadata.closest_env do
{pos, dist, env} ->
dbg({pos, dist})
{_pos, _dist, env} ->
env

nil ->
Expand Down Expand Up @@ -263,30 +258,21 @@ defmodule ElixirSense.Core.Metadata do
|> Enum.min(fn -> nil end)
end

def add_scope_vars(
%State.Env{} = env,
def find_var(
%__MODULE__{vars_info_per_scope_id: vars_info_per_scope_id},
{line, column},
predicate \\ fn _ -> true end
variable,
version,
position
) do
scope_vars = vars_info_per_scope_id[env.scope_id] || %{}
env_vars_keys = env.vars |> Enum.map(&{&1.name, &1.version})

scope_vars_missing_in_env =
scope_vars
|> Enum.filter(fn {key, var} ->
key not in env_vars_keys and Enum.min(var.positions) <= {line, column} and
predicate.(var)
vars_info_per_scope_id
|> Enum.find_value(fn {_scope_id, vars} ->
vars
|> Enum.find_value(fn {{n, v}, info} ->
if n == variable and (v == version or version == :any) and position in info.positions do
info
end
end)
|> Enum.map(fn {_, value} -> value end)

env_vars =
for var <- env.vars do
key = {var.name, var.version}
Map.fetch!(scope_vars, key)
end

%{env | vars: env_vars ++ scope_vars_missing_in_env}
end)
end

@spec at_module_body?(State.Env.t()) :: boolean()
Expand Down
5 changes: 0 additions & 5 deletions lib/elixir_sense/providers/completion/suggestion.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,6 @@ defmodule ElixirSense.Providers.Completion.Suggestion do

env =
Metadata.get_env(metadata, {line, column})
|> Metadata.add_scope_vars(
metadata,
{line, column},
&(to_string(&1.name) != hint)
)

# if variable is rebound then in env there are many variables with the same name
# find the one defined closest to cursor
Expand Down
1 change: 0 additions & 1 deletion lib/elixir_sense/providers/definition/locator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ defmodule ElixirSense.Providers.Definition.Locator do

env =
Metadata.get_env(metadata, {line, column})
|> Metadata.add_scope_vars(metadata, {line, column})

find(
context,
Expand Down
1 change: 0 additions & 1 deletion lib/elixir_sense/providers/references/locator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ defmodule ElixirSense.Providers.References.Locator do
module: module
} =
Metadata.get_env(metadata, {line, column})
|> Metadata.add_scope_vars(metadata, {line, column})

# find last env of current module
attributes = get_attributes(metadata, module)
Expand Down

0 comments on commit b802c3d

Please sign in to comment.