Skip to content

Commit 8878b85

Browse files
authored
add test coverage and fix some small issues in debugger variables (#668)
1 parent b4dd38a commit 8878b85

File tree

4 files changed

+190
-20
lines changed

4 files changed

+190
-20
lines changed

apps/elixir_ls_debugger/lib/debugger/server.ex

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -608,17 +608,21 @@ defmodule ElixirLS.Debugger.Server do
608608
end
609609

610610
defp variables(state = %__MODULE__{}, pid, var, start, count, filter) do
611+
var_child_type = Variables.child_type(var)
612+
611613
children =
612-
if (filter == "named" and Variables.child_type(var) == :indexed) or
613-
(filter == "indexed" and Variables.child_type(var) == :named) do
614+
if var_child_type == nil or (filter != nil and Atom.to_string(var_child_type) != filter) do
614615
[]
615616
else
616617
Variables.children(var, start, count)
617618
end
618619

619620
Enum.reduce(children, {state, []}, fn {name, value}, {state = %__MODULE__{}, result} ->
621+
num_children = Variables.num_children(value)
622+
child_type = Variables.child_type(value)
623+
620624
{state, var_id} =
621-
if Variables.expandable?(value) do
625+
if child_type do
622626
ensure_var_id(state, pid, value)
623627
else
624628
{state, 0}
@@ -632,9 +636,9 @@ defmodule ElixirLS.Debugger.Server do
632636
}
633637

634638
json =
635-
case Variables.child_type(value) do
636-
:indexed -> Map.put(json, "indexedVariables", Variables.num_children(value))
637-
:named -> Map.put(json, "namedVariables", Variables.num_children(value))
639+
case child_type do
640+
:indexed -> Map.put(json, "indexedVariables", num_children)
641+
:named -> Map.put(json, "namedVariables", num_children)
638642
nil -> json
639643
end
640644

apps/elixir_ls_debugger/lib/debugger/variables.ex

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@ defmodule ElixirLS.Debugger.Variables do
22
@moduledoc """
33
Helper functions for working with variables for paused processes
44
"""
5+
alias ElixirSense.Core.Introspection
56

67
def child_type(var) when is_map(var), do: :named
78
def child_type(var) when is_bitstring(var), do: :indexed
89
def child_type(var) when is_tuple(var), do: :indexed
910
def child_type(var) when is_list(var), do: :indexed
1011
def child_type(_var), do: nil
1112

12-
def expandable?(var) do
13-
num_children(var) > 0
14-
end
15-
1613
def children(var, start, count) when is_list(var) do
1714
start = start || 0
1815
count = count || Enum.count(var)
@@ -42,7 +39,7 @@ defmodule ElixirLS.Debugger.Variables do
4239

4340
for {key, value} <- children do
4441
name =
45-
if is_atom(key) and not String.starts_with?(to_string(key), "Elixir.") do
42+
if is_atom(key) and not Introspection.elixir_module?(key) do
4643
to_string(key)
4744
else
4845
inspect(key)
@@ -60,12 +57,8 @@ defmodule ElixirLS.Debugger.Variables do
6057
Enum.count(var)
6158
end
6259

63-
def num_children(var) when is_binary(var) do
64-
byte_size(var)
65-
end
66-
6760
def num_children(var) when is_bitstring(var) do
68-
if byte_size(var) > 1, do: byte_size(var), else: 0
61+
byte_size(var)
6962
end
7063

7164
def num_children(var) when is_tuple(var) do
@@ -80,16 +73,29 @@ defmodule ElixirLS.Debugger.Variables do
8073
0
8174
end
8275

83-
def type(var) when is_atom(var), do: "atom"
76+
def type(var) when is_boolean(var), do: "boolean"
77+
def type(var) when is_nil(var), do: "nil"
78+
79+
def type(var) when is_atom(var) do
80+
if Introspection.elixir_module?(var) do
81+
"module"
82+
else
83+
"atom"
84+
end
85+
end
86+
8487
def type(var) when is_binary(var), do: "binary"
8588
def type(var) when is_bitstring(var), do: "bitstring"
86-
def type(var) when is_boolean(var), do: "boolean"
89+
8790
def type(var) when is_float(var), do: "float"
8891
def type(var) when is_function(var), do: "function"
8992
def type(var) when is_integer(var), do: "integer"
9093
def type(var) when is_list(var), do: "list"
94+
95+
def type(%name{}), do: "%#{inspect(name)}{}"
96+
9197
def type(var) when is_map(var), do: "map"
92-
def type(var) when is_nil(var), do: "nil"
98+
9399
def type(var) when is_number(var), do: "number"
94100
def type(var) when is_pid(var), do: "pid"
95101
def type(var) when is_port(var), do: "port"

apps/elixir_ls_debugger/test/debugger_test.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ defmodule ElixirLS.Debugger.ServerTest do
184184
"variablesReference" => 0
185185
}
186186
]
187-
})
187+
}),
188+
1000
188189

189190
Server.receive_packet(server, continue_req(10, thread_id))
190191
assert_receive response(_, 10, "continue", %{"allThreadsContinued" => false})
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
defmodule ElixirLS.Debugger.VariablesTest do
2+
use ElixirLS.Utils.MixTest.Case, async: true
3+
alias ElixirLS.Debugger.Variables
4+
5+
test "type" do
6+
assert Variables.type(1234) == "integer"
7+
8+
assert Variables.type(123.4) == "float"
9+
10+
assert Variables.type("") == "binary"
11+
assert Variables.type("asdc") == "binary"
12+
13+
assert Variables.type(<<0::size(1)>>) == "bitstring"
14+
15+
assert Variables.type({}) == "tuple"
16+
assert Variables.type({1}) == "tuple"
17+
assert Variables.type({:ok, 3}) == "tuple"
18+
19+
assert Variables.type(true) == "boolean"
20+
assert Variables.type(false) == "boolean"
21+
22+
assert Variables.type(nil) == "nil"
23+
24+
assert Variables.type(:asd) == "atom"
25+
26+
assert Variables.type(Elixir) == "atom"
27+
assert Variables.type(Some) == "module"
28+
assert Variables.type(Some.Module) == "module"
29+
30+
assert Variables.type(:erlang.make_ref()) == "reference"
31+
32+
assert Variables.type(fn -> :ok end) == "function"
33+
34+
assert Variables.type(spawn(fn -> :ok end)) == "pid"
35+
36+
assert Variables.type(hd(:erlang.ports())) == "port"
37+
38+
assert Variables.type([]) == "list"
39+
assert Variables.type([1]) == "list"
40+
assert Variables.type('asd') == "list"
41+
42+
assert Variables.type(%{}) == "map"
43+
assert Variables.type(%{asd: 123}) == "map"
44+
assert Variables.type(%{"asd" => 123}) == "map"
45+
46+
assert Variables.type(%Date{year: 2022, month: 1, day: 1}) == "%Date{}"
47+
assert Variables.type(%ArgumentError{}) == "%ArgumentError{}"
48+
end
49+
50+
test "num_children" do
51+
assert Variables.num_children(1234) == 0
52+
53+
assert Variables.num_children(123.4) == 0
54+
55+
assert Variables.num_children("") == 0
56+
assert Variables.num_children("asdc") == 4
57+
58+
assert Variables.num_children(<<0::size(1)>>) == 1
59+
assert Variables.num_children(<<0::size(7)>>) == 1
60+
assert Variables.num_children(<<0::size(8)>>) == 1
61+
assert Variables.num_children(<<0::size(9)>>) == 2
62+
63+
assert Variables.num_children({}) == 0
64+
assert Variables.num_children({1}) == 1
65+
assert Variables.num_children({:ok, 3}) == 2
66+
67+
assert Variables.num_children(true) == 0
68+
assert Variables.num_children(false) == 0
69+
70+
assert Variables.num_children(nil) == 0
71+
72+
assert Variables.num_children(:asd) == 0
73+
74+
assert Variables.num_children(Elixir) == 0
75+
assert Variables.num_children(Some) == 0
76+
assert Variables.num_children(Some.Module) == 0
77+
78+
assert Variables.num_children(:erlang.make_ref()) == 0
79+
80+
assert Variables.num_children(fn -> :ok end) == 0
81+
82+
assert Variables.num_children(spawn(fn -> :ok end)) == 0
83+
84+
assert Variables.num_children(hd(:erlang.ports())) == 0
85+
86+
assert Variables.num_children([]) == 0
87+
assert Variables.num_children([1]) == 1
88+
assert Variables.num_children('asd') == 3
89+
90+
assert Variables.num_children(%{}) == 0
91+
assert Variables.num_children(%{asd: 123}) == 1
92+
assert Variables.num_children(%{"asd" => 123}) == 1
93+
94+
assert Variables.num_children(%Date{year: 2022, month: 1, day: 1}) == 5
95+
assert Variables.num_children(%ArgumentError{}) == 3
96+
end
97+
98+
describe "children" do
99+
test "list" do
100+
assert Variables.children([], 0, 10) == []
101+
assert Variables.children([1], 0, 10) == [{"0", 1}]
102+
assert Variables.children([1, 2, 3, 4], 0, 2) == [{"0", 1}, {"1", 2}]
103+
assert Variables.children([1, 2, 3, 4], 1, 2) == [{"1", 2}, {"2", 3}]
104+
assert Variables.children('asd', 0, 10) == [{"0", 97}, {"1", 115}, {"2", 100}]
105+
end
106+
107+
test "tuple" do
108+
assert Variables.children({}, 0, 10) == []
109+
assert Variables.children({1}, 0, 10) == [{"0", 1}]
110+
assert Variables.children({:ok, 3}, 0, 10) == [{"0", :ok}, {"1", 3}]
111+
assert Variables.children({:ok, 3}, 1, 10) == [{"1", 3}]
112+
end
113+
114+
test "map" do
115+
assert Variables.children(%{}, 0, 10) == []
116+
assert Variables.children(%{asd: 123}, 0, 10) == [{"asd", 123}]
117+
assert Variables.children(%{Date: 123}, 0, 10) == [{"Date", 123}]
118+
assert Variables.children(%{"asd" => 123}, 0, 10) == [{"\"asd\"", 123}]
119+
120+
assert Variables.children(%Date{year: 2022, month: 1, day: 1}, 0, 10) == [
121+
{"__struct__", Date},
122+
{"calendar", Calendar.ISO},
123+
{"day", 1},
124+
{"month", 1},
125+
{"year", 2022}
126+
]
127+
128+
assert Variables.children(%ArgumentError{}, 0, 10) == [
129+
{"__exception__", true},
130+
{"__struct__", ArgumentError},
131+
{"message", "argument error"}
132+
]
133+
134+
assert Variables.children(%ArgumentError{}, 1, 10) == [
135+
{"__struct__", ArgumentError},
136+
{"message", "argument error"}
137+
]
138+
139+
assert Variables.children(%ArgumentError{}, 1, 1) == [{"__struct__", ArgumentError}]
140+
end
141+
142+
test "binary" do
143+
assert Variables.children("", 0, 10) == []
144+
assert Variables.children("asdc", 0, 10) == [{"0", 97}, {"1", 115}, {"2", 100}, {"3", 99}]
145+
assert Variables.children("asdc", 1, 10) == [{"1", 115}, {"2", 100}, {"3", 99}]
146+
assert Variables.children("asdc", 1, 2) == [{"1", 115}, {"2", 100}]
147+
end
148+
149+
test "bitstring" do
150+
assert Variables.children(<<0::size(1)>>, 0, 10) == [{"0", <<0::size(1)>>}]
151+
assert Variables.children(<<0::size(3)>>, 0, 10) == [{"0", <<0::size(3)>>}]
152+
assert Variables.children(<<0::size(8)>>, 0, 10) == [{"0", 0}]
153+
assert Variables.children(<<0::size(9)>>, 0, 10) == [{"0", 0}, {"1", <<0::size(1)>>}]
154+
155+
assert Variables.children(<<0::size(17)>>, 1, 10) == [{"1", 0}, {"2", <<0::size(1)>>}]
156+
assert Variables.children(<<0::size(17)>>, 1, 1) == [{"1", 0}]
157+
end
158+
end
159+
end

0 commit comments

Comments
 (0)