Skip to content

Commit 4c97baa

Browse files
committed
fix test
1 parent 8d8cab5 commit 4c97baa

File tree

2 files changed

+52
-30
lines changed

2 files changed

+52
-30
lines changed

lib/elixir_sense/core/compiler/fn.ex

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,17 +186,16 @@ defmodule ElixirSense.Core.Compiler.Fn do
186186
defp escape({:&, meta, [pos]}, dict) when is_integer(pos) and pos > 0 do
187187
# This might pollute user space but is unlikely because variables
188188
# named :"&1" are not valid syntax.
189-
var = {:"&#{pos}", meta, nil}
190-
{var, :orddict.store(pos, var, dict)}
191-
189+
# NOTE: ElixirSense intentionally uses :"&#{pos}" instead of :capture atom
190+
# (Elixir 1.17+ uses :capture) because :"&#{pos}" provides better variable intelligence
192191
case :orddict.find(pos, dict) do
193192
{:ok, var} ->
194193
{var, dict}
195194

196195
:error ->
197196
# elixir uses here elixir_module:next_counter(?key(E, module))
198197
# but we are not compiling and do not need to keep count in module scope
199-
# elixir 1.17 also renames the var to `capture`
198+
# elixir 1.19 added {:capture, pos} metadata
200199
next = System.unique_integer()
201200
var = {:"&#{pos}", [{:counter, next}, {:capture, pos} | meta], nil}
202201
{var, :orddict.store(pos, var, dict)}

test/elixir_sense/core/compiler_test.exs

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -974,24 +974,38 @@ defmodule ElixirSense.Core.CompilerTest do
974974
{{{:., dot_meta, target}, call_meta, args}, state}
975975

976976
{:fn, meta, args} = _node, state ->
977-
meta =
978-
if Version.match?(System.version(), "< 1.19.0") do
979-
Keyword.delete(meta, :capture)
980-
else
981-
meta
982-
end
983-
977+
# Always remove {:capture, true} metadata for normalization
978+
# Both ElixirSense and Elixir >= 1.19 produce it, so normalize it away
979+
meta = Keyword.delete(meta, :capture)
984980
{{:fn, meta, args}, state}
985981

986982
{atom, meta, nil} = node, state when is_atom(atom) ->
987-
# elixir changes the name to capture and does different counter tracking
983+
# ElixirSense intentionally uses :"&#{pos}" instead of :capture
984+
# Convert to :capture to match Elixir 1.17+ behavior
988985
node =
989-
with "&" <> int <- to_string(atom), {_, ""} <- Integer.parse(int) do
986+
with "&" <> int <- to_string(atom), {pos, ""} <- Integer.parse(int) do
987+
# Normalize metadata
990988
meta =
991-
Keyword.delete(meta, :counter)
992-
|> Keyword.delete(:capture)
993-
994-
{:capture, meta, nil}
989+
if Version.match?(System.version(), "< 1.17.0") do
990+
# Elixir < 1.17 used :"&#{pos}" with no special metadata
991+
Keyword.delete(meta, :counter) |> Keyword.delete(:capture)
992+
else
993+
# Elixir >= 1.17 uses :capture atom
994+
if Version.match?(System.version(), "< 1.19.0") do
995+
# Elixir 1.17-1.18: no {:capture, pos} metadata
996+
Keyword.delete(meta, :counter) |> Keyword.delete(:capture)
997+
else
998+
# Elixir >= 1.19: has {:capture, pos} metadata, remove :counter only
999+
Keyword.delete(meta, :counter)
1000+
end
1001+
end
1002+
1003+
# Convert to :capture for Elixir 1.17+
1004+
if Version.match?(System.version(), "< 1.17.0") do
1005+
{atom, meta, nil}
1006+
else
1007+
{:capture, meta, nil}
1008+
end
9951009
else
9961010
_ -> node
9971011
end
@@ -1019,28 +1033,37 @@ defmodule ElixirSense.Core.CompilerTest do
10191033
{{:->, meta, args}, state}
10201034

10211035
{:fn, meta, args} = _node, state ->
1022-
meta =
1023-
if Version.match?(System.version(), ">= 1.19.0-rc.0") do
1024-
Keyword.delete(meta, :capture)
1025-
else
1026-
meta
1027-
end
1028-
1036+
# Normalize :capture metadata - always remove for comparison
1037+
# (ElixirSense normalizes this too)
1038+
meta = Keyword.delete(meta, :capture)
10291039
{{:fn, meta, args}, state}
10301040

10311041
{:capture, meta, nil} = _node, state ->
1032-
# elixir changes the name to capture and does different counter tracking
1033-
meta = Keyword.delete(meta, :counter)
1034-
1042+
# Normalize capture variable metadata
1043+
# Always remove :counter and optionally :capture depending on version
10351044
meta =
1036-
if Version.match?(System.version(), ">= 1.19.0-rc.0") do
1037-
Keyword.delete(meta, :capture)
1045+
if Version.match?(System.version(), "< 1.19.0") do
1046+
# Elixir < 1.19: remove both counter and capture metadata
1047+
Keyword.delete(meta, :counter) |> Keyword.delete(:capture)
10381048
else
1039-
meta
1049+
# Elixir >= 1.19: keep :capture but remove :counter
1050+
Keyword.delete(meta, :counter)
10401051
end
10411052

10421053
{{:capture, meta, nil}, state}
10431054

1055+
{atom, meta, nil} = node, state when is_atom(atom) ->
1056+
# Handle old :"&#{pos}" format from Elixir < 1.18
1057+
node =
1058+
with "&" <> int <- to_string(atom), {_, ""} <- Integer.parse(int) do
1059+
meta = Keyword.delete(meta, :counter) |> Keyword.delete(:capture)
1060+
{atom, meta, nil}
1061+
else
1062+
_ -> node
1063+
end
1064+
1065+
{node, state}
1066+
10441067
node, state ->
10451068
{node, state}
10461069
end)

0 commit comments

Comments
 (0)