Spitfire 0.3.11 raises FunctionClauseError when parsing a charlist literal whose only content is a string interpolation segment.
Repro
Mix.install([{:spitfire, "~> 0.3"}])
Spitfire.parse(~S|defmodule D, do: '#{x}'|)
Stack trace
** (FunctionClauseError) no function clause matching in String.to_charlist/1
# 1
{{1, 19, nil}, {1, 22, nil}, [{:identifier, {1, 21, ~c"x"}, :x}]}
(elixir 1.17.3) lib/string.ex:2847: String.to_charlist/1
(spitfire 0.3.11) lib/spitfire.ex:2480: Spitfire.parse_string/1
Root cause
The :list_string non-interpolation clause of parse_string/1 (lib/spitfire.ex:2480) is missing the when is_binary(string) guard that the parallel :bin_string clause at line 2463 has. When the tokenizer emits a single-element token list for a charlist that is pure interpolation, the unguarded clause matches and String.to_charlist/1 is called on the interpolation-segment tuple.
Charlists with surrounding text ('foo#{x}bar') were unaffected because their token list has multiple elements and falls through to the interpolation-aware clause.
Scope
| Input |
0.3.11 |
| 'foo' |
OK |
| 'foo#{x}bar' |
OK |
| '#{x}' |
crash |
| "#{x}" |
OK |
| heredoc charlist |
OK |
| heredoc bin |
OK |
Also affects downstream xp_spitfire (vendored by Expert LSP) and breaks
Go-to-Definition on files containing this construct. Hit naturally in e.g.
plug_forwarded_peer's lib/plug_forwarded_peer.ex.
Spitfire 0.3.11 raises FunctionClauseError when parsing a charlist literal whose only content is a string interpolation segment.
Repro
Stack trace
Root cause
The :list_string non-interpolation clause of parse_string/1 (lib/spitfire.ex:2480) is missing the
when is_binary(string)guard that the parallel :bin_string clause at line 2463 has. When the tokenizer emits a single-element token list for a charlist that is pure interpolation, the unguarded clause matches andString.to_charlist/1is called on the interpolation-segment tuple.Charlists with surrounding text (
'foo#{x}bar') were unaffected because their token list has multiple elements and falls through to the interpolation-aware clause.Scope
Also affects downstream xp_spitfire (vendored by Expert LSP) and breaks
Go-to-Definition on files containing this construct. Hit naturally in e.g.
plug_forwarded_peer's lib/plug_forwarded_peer.ex.