Skip to content

Commit fae7195

Browse files
committed
Deprecate single quites in quoted atoms and calls, refs #13958
1 parent 13eadf9 commit fae7195

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

lib/elixir/src/elixir_tokenizer.erl

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,15 @@ tokenize([T | Rest], Line, Column, Scope, Tokens) when ?pipe_op(T) ->
489489
% Non-operator Atoms
490490

491491
tokenize([$:, H | T] = Original, Line, Column, Scope, Tokens) when ?is_quote(H) ->
492-
case elixir_interpolation:extract(Line, Column + 2, Scope, true, T, H) of
492+
OuterScope = case H == $' of
493+
true ->
494+
prepend_warning(Line, Column, "single quotes around atoms are deprecated. Use double quotes instead.", Scope);
495+
496+
false ->
497+
Scope
498+
end,
499+
500+
case elixir_interpolation:extract(Line, Column + 2, OuterScope, true, T, H) of
493501
{NewLine, NewColumn, Parts, Rest, InterScope} ->
494502
NewScope = case is_unnecessary_quote(Parts, InterScope) of
495503
true ->
@@ -508,7 +516,7 @@ tokenize([$:, H | T] = Original, Line, Column, Scope, Tokens) when ?is_quote(H)
508516

509517
case unescape_tokens(Parts, Line, Column, NewScope) of
510518
{ok, [Part]} when is_binary(Part) ->
511-
case unsafe_to_atom(Part, Line, Column, Scope) of
519+
case unsafe_to_atom(Part, Line, Column, OuterScope) of
512520
{ok, Atom} ->
513521
Token = {atom_quoted, {Line, Column, H}, Atom},
514522
tokenize(Rest, NewLine, NewColumn, NewScope, [Token | Tokens]);
@@ -518,7 +526,7 @@ tokenize([$:, H | T] = Original, Line, Column, Scope, Tokens) when ?is_quote(H)
518526
end;
519527

520528
{ok, Unescaped} ->
521-
Key = case Scope#elixir_tokenizer.existing_atoms_only of
529+
Key = case OuterScope#elixir_tokenizer.existing_atoms_only of
522530
true -> atom_safe;
523531
false -> atom_unsafe
524532
end,
@@ -531,7 +539,7 @@ tokenize([$:, H | T] = Original, Line, Column, Scope, Tokens) when ?is_quote(H)
531539

532540
{error, Reason} ->
533541
Message = " (for atom starting at line ~B)",
534-
interpolation_error(Reason, Original, Scope, Tokens, Message, [Line], Line, Column + 1, [H], [H])
542+
interpolation_error(Reason, Original, OuterScope, Tokens, Message, [Line], Line, Column + 1, [H], [H])
535543
end;
536544

537545
tokenize([$: | String] = Original, Line, Column, Scope, Tokens) ->
@@ -897,7 +905,15 @@ handle_dot([$., $( | Rest], Line, Column, DotInfo, Scope, Tokens) ->
897905
tokenize([$( | Rest], Line, Column, Scope, TokensSoFar);
898906

899907
handle_dot([$., H | T] = Original, Line, Column, DotInfo, Scope, Tokens) when ?is_quote(H) ->
900-
case elixir_interpolation:extract(Line, Column + 1, Scope, true, T, H) of
908+
OuterScope = case H == $' of
909+
true ->
910+
prepend_warning(Line, Column, "single quotes around calls are deprecated. Use double quotes instead.", Scope);
911+
912+
false ->
913+
Scope
914+
end,
915+
916+
case elixir_interpolation:extract(Line, Column + 1, OuterScope, true, T, H) of
901917
{NewLine, NewColumn, [Part], Rest, InterScope} when is_list(Part) ->
902918
NewScope = case is_unnecessary_quote([Part], InterScope) of
903919
true ->
@@ -928,7 +944,7 @@ handle_dot([$., H | T] = Original, Line, Column, DotInfo, Scope, Tokens) when ?i
928944
Message = "interpolation is not allowed when calling function/macro. Found interpolation in a call starting with: ",
929945
error({?LOC(Line, Column), Message, [H]}, Rest, NewScope, Tokens);
930946
{error, Reason} ->
931-
interpolation_error(Reason, Original, Scope, Tokens, " (for function name starting at line ~B)", [Line], Line, Column, [H], [H])
947+
interpolation_error(Reason, Original, OuterScope, Tokens, " (for function name starting at line ~B)", [Line], Line, Column, [H], [H])
932948
end;
933949

934950
handle_dot([$. | Rest], Line, Column, DotInfo, Scope, Tokens) ->

lib/elixir/test/elixir/kernel/warning_test.exs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,42 @@ defmodule Kernel.WarningTest do
201201
end
202202
end
203203

204+
describe "deprecated single quotes in atoms" do
205+
test "warns for single quotes in atoms" do
206+
assert_warn_eval(
207+
[
208+
"nofile:1:1",
209+
"single quotes around atoms are deprecated. Use double quotes instead"
210+
],
211+
~s/:'a+b'/
212+
)
213+
end
214+
215+
test "warns twice for single and unnecessary atom quotes" do
216+
assert_warn_eval(
217+
[
218+
"nofile:1:1",
219+
"single quotes around atoms are deprecated. Use double quotes instead",
220+
"nofile:1:1",
221+
"found quoted atom \"ab\" but the quotes are not required"
222+
],
223+
~s/:'ab'/
224+
)
225+
end
226+
227+
test "warns twice for single and unnecessary call quotes" do
228+
assert_warn_eval(
229+
[
230+
"nofile:1:9",
231+
"single quotes around calls are deprecated. Use double quotes instead",
232+
"nofile:1:9",
233+
"found quoted call \"length\" but the quotes are not required"
234+
],
235+
~s/[Kernel.'length'([])]/
236+
)
237+
end
238+
end
239+
204240
test "warns on :: as atom" do
205241
assert_warn_eval(
206242
[

0 commit comments

Comments
 (0)