Skip to content

Commit a47a1ec

Browse files
committed
handle improper lists in variable inspector
Fixes #1028
1 parent 866e698 commit a47a1ec

File tree

2 files changed

+65
-12
lines changed

2 files changed

+65
-12
lines changed

apps/elixir_ls_debugger/lib/debugger/variables.ex

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ defmodule ElixirLS.Debugger.Variables do
1313
:named
1414
else
1515
:indexed
16+
17+
try do
18+
# this call will raise ArgumentError for improper list, no better way to check it
19+
_ = length(var)
20+
:indexed
21+
rescue
22+
ArgumentError ->
23+
# improper list has head and tail
24+
:named
25+
end
1626
end
1727
end
1828

@@ -36,17 +46,36 @@ defmodule ElixirLS.Debugger.Variables do
3646

3747
def children(var, start, count) when is_list(var) do
3848
start = start || 0
39-
count = count || Enum.count(var)
40-
41-
sliced =
42-
var
43-
|> Enum.slice(start, count)
4449

45-
if Keyword.keyword?(var) do
46-
sliced
47-
else
48-
sliced
49-
|> with_index_as_name(start)
50+
try do
51+
# this call will raise ArgumentError for improper list, no better way to check it
52+
max_count = length(var)
53+
count = count || max_count
54+
55+
sliced =
56+
var
57+
|> Enum.slice(start, count)
58+
59+
if Keyword.keyword?(var) do
60+
sliced
61+
else
62+
sliced
63+
|> with_index_as_name(start)
64+
end
65+
rescue
66+
ArgumentError ->
67+
count = count || 2
68+
69+
if start == 0 and count >= 1 do
70+
[{"hd", hd(var)}]
71+
else
72+
[]
73+
end ++
74+
if start + count >= 2 do
75+
[{"tl", tl(var)}]
76+
else
77+
[]
78+
end
5079
end
5180
end
5281

@@ -107,7 +136,13 @@ defmodule ElixirLS.Debugger.Variables do
107136
end
108137

109138
def num_children(var) when is_list(var) do
110-
Enum.count(var)
139+
try do
140+
length(var)
141+
rescue
142+
ArgumentError ->
143+
# improper list has head and tail
144+
2
145+
end
111146
end
112147

113148
def num_children(var) when is_bitstring(var) do
@@ -167,7 +202,14 @@ defmodule ElixirLS.Debugger.Variables do
167202
if Keyword.keyword?(var) and var != [] do
168203
"keyword"
169204
else
170-
"list"
205+
try do
206+
# this call will raise ArgumentError for improper list, no better way to check it
207+
_ = length(var)
208+
"list"
209+
rescue
210+
ArgumentError ->
211+
"improper list"
212+
end
171213
end
172214
end
173215

apps/elixir_ls_debugger/test/variables_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ defmodule ElixirLS.Debugger.VariablesTest do
3939
assert Variables.type([1]) == "list"
4040
assert Variables.type(~c"asd") == "list"
4141

42+
assert Variables.type([[] | "data"]) == "improper list"
43+
4244
assert Variables.type(abc: 123) == "keyword"
4345

4446
assert Variables.type(%{}) == "map"
@@ -47,6 +49,8 @@ defmodule ElixirLS.Debugger.VariablesTest do
4749

4850
assert Variables.type(%Date{year: 2022, month: 1, day: 1}) == "%Date{}"
4951
assert Variables.type(%ArgumentError{}) == "%ArgumentError{}"
52+
# TODO MapSet
53+
# TODO :array
5054
end
5155

5256
test "num_children" do
@@ -92,6 +96,8 @@ defmodule ElixirLS.Debugger.VariablesTest do
9296
assert Variables.num_children([1]) == 1
9397
assert Variables.num_children(~c"asd") == 3
9498

99+
assert Variables.num_children([[] | "data"]) == 2
100+
95101
assert Variables.num_children(abc: 123) == 1
96102

97103
assert Variables.num_children(%{}) == 0
@@ -111,6 +117,11 @@ defmodule ElixirLS.Debugger.VariablesTest do
111117
assert Variables.children(~c"asd", 0, 10) == [{"0", 97}, {"1", 115}, {"2", 100}]
112118
end
113119

120+
test "improper list" do
121+
assert Variables.children([1, 2, 3 | "data"], 0, 10) == [{"hd", 1}, {"tl", [2, 3 | "data"]}]
122+
assert Variables.children([1, 2, 3 | "data"], 1, 10) == [{"tl", [2, 3 | "data"]}]
123+
end
124+
114125
test "keyword" do
115126
assert Variables.children([abc: 123], 0, 10) == [abc: 123]
116127

0 commit comments

Comments
 (0)