Skip to content

Commit 9fea9ba

Browse files
authored
Support describes and tests with unevaluated names (#537)
When a test is formatted as: test "performs some" <> "action" do assert work_done() end The language server crashes with message: ** (Protocol.UndefinedError) protocol String.Chars not implemented for {:<>, ... ["performs some", "action"], ... This comes from `lib/language_server/providers/document_symbols.ex:222` where the "name" of the test is interpolated into a string. In order for this "unevaluated" test name AST to be interpolated into a string, it must first become a string or something that the String.Chars protocol can turn into a string. My approach here is to turn the test name AST into a string using `Macro.to_string`, which simply converts an AST into its Elixir code equivalent.
1 parent c536672 commit 9fea9ba

File tree

2 files changed

+100
-4
lines changed

2 files changed

+100
-4
lines changed

apps/language_server/lib/language_server/providers/document_symbols.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
219219
defp extract_symbol(_current_module, {:test, location, [name | _]}) do
220220
%Info{
221221
type: :function,
222-
name: ~s(test "#{name}"),
222+
name: "test #{Macro.to_string(name)}",
223223
location: location,
224224
children: []
225225
}
@@ -251,7 +251,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
251251

252252
%Info{
253253
type: :function,
254-
name: ~s(describe "#{name}"),
254+
name: "describe #{Macro.to_string(name)}",
255255
location: location,
256256
children: module_symbols
257257
}

apps/language_server/test/providers/document_symbols_test.exs

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,7 +2018,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
20182018
]} = DocumentSymbols.symbols(uri, text, false)
20192019
end
20202020

2021-
test "[nested] handles exunit descibe tests" do
2021+
test "[nested] handles exunit describe tests" do
20222022
uri = "file:///project/test.exs"
20232023
text = ~S[
20242024
defmodule MyModuleTest do
@@ -2075,7 +2075,64 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
20752075
]} = DocumentSymbols.symbols(uri, text, true)
20762076
end
20772077

2078-
test "[flat] handles exunit descibe tests" do
2078+
test "[nested] handles exunit describes and tests with unevaluated names" do
2079+
uri = "file:///project/test.exs"
2080+
text = ~S[
2081+
defmodule MyModuleTest do
2082+
use ExUnit.Case
2083+
describe ~S(some "descripton") do
2084+
test "does" <> "something", do: :ok
2085+
end
2086+
end
2087+
]
2088+
2089+
assert {:ok,
2090+
[
2091+
%Protocol.DocumentSymbol{
2092+
children: [
2093+
%Protocol.DocumentSymbol{
2094+
children: [
2095+
%Protocol.DocumentSymbol{
2096+
children: [],
2097+
kind: 12,
2098+
name: "test \"does\" <> \"something\"",
2099+
range: %{
2100+
end: %{character: 10, line: 4},
2101+
start: %{character: 10, line: 4}
2102+
},
2103+
selectionRange: %{
2104+
end: %{character: 10, line: 4},
2105+
start: %{character: 10, line: 4}
2106+
}
2107+
}
2108+
],
2109+
kind: 12,
2110+
name: "describe ~S(some \"descripton\")",
2111+
range: %{
2112+
end: %{character: 8, line: 3},
2113+
start: %{character: 8, line: 3}
2114+
},
2115+
selectionRange: %{
2116+
end: %{character: 8, line: 3},
2117+
start: %{character: 8, line: 3}
2118+
}
2119+
}
2120+
],
2121+
kind: 2,
2122+
name: "MyModuleTest",
2123+
range: %{
2124+
end: %{character: 6, line: 1},
2125+
start: %{character: 6, line: 1}
2126+
},
2127+
selectionRange: %{
2128+
end: %{character: 6, line: 1},
2129+
start: %{character: 6, line: 1}
2130+
}
2131+
}
2132+
]} = DocumentSymbols.symbols(uri, text, true)
2133+
end
2134+
2135+
test "[flat] handles exunit describe tests" do
20792136
uri = "file:///project/test.exs"
20802137
text = ~S[
20812138
defmodule MyModuleTest do
@@ -2114,6 +2171,45 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
21142171
]} = DocumentSymbols.symbols(uri, text, false)
21152172
end
21162173

2174+
test "[flat] handles exunit describes and tests with unevaluated names" do
2175+
uri = "file:///project/test.exs"
2176+
text = ~S[
2177+
defmodule MyModuleTest do
2178+
use ExUnit.Case
2179+
describe ~S(some "descripton") do
2180+
test "does" <> "something", do: :ok
2181+
end
2182+
end
2183+
]
2184+
2185+
assert {:ok,
2186+
[
2187+
%Protocol.SymbolInformation{
2188+
name: "MyModuleTest",
2189+
kind: 2,
2190+
location: %{
2191+
range: %{end: %{character: 6, line: 1}, start: %{character: 6, line: 1}}
2192+
}
2193+
},
2194+
%Protocol.SymbolInformation{
2195+
name: "describe ~S(some \"descripton\")",
2196+
kind: 12,
2197+
location: %{
2198+
range: %{end: %{character: 8, line: 3}, start: %{character: 8, line: 3}}
2199+
},
2200+
containerName: "MyModuleTest"
2201+
},
2202+
%Protocol.SymbolInformation{
2203+
name: "test \"does\" <> \"something\"",
2204+
kind: 12,
2205+
location: %{
2206+
range: %{end: %{character: 10, line: 4}, start: %{character: 10, line: 4}}
2207+
},
2208+
containerName: "describe ~S(some \"descripton\")"
2209+
}
2210+
]} = DocumentSymbols.symbols(uri, text, false)
2211+
end
2212+
21172213
test "[nested] handles exunit callbacks" do
21182214
uri = "file:///project/test.exs"
21192215

0 commit comments

Comments
 (0)