From d31d5ccc4baeeea7efa999ea344a2fcc031bdbc5 Mon Sep 17 00:00:00 2001 From: sabiwara Date: Wed, 29 Oct 2025 08:14:38 +0900 Subject: [PATCH] Warn on deprecated ~~~ unary op in tokenizer --- lib/elixir/src/elixir_tokenizer.erl | 16 +++++++++++----- lib/elixir/test/erlang/tokenizer_test.erl | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/elixir/src/elixir_tokenizer.erl b/lib/elixir/src/elixir_tokenizer.erl index b418a837786..14ea3ca7922 100644 --- a/lib/elixir/src/elixir_tokenizer.erl +++ b/lib/elixir/src/elixir_tokenizer.erl @@ -883,8 +883,18 @@ handle_unary_op(Rest, Line, Column, Kind, Length, Op, Scope, Tokens) -> Token = {identifier, {Line, Column, nil}, Op}, tokenize(Remaining, NewLine, NewColumn, Scope, [Token | Tokens]); {Remaining, NewLine, NewColumn} -> + NewScope = + %% TODO: Remove these deprecations on Elixir v2.0 + case Op of + '~~~' -> + Msg = "~~~ is deprecated. Use Bitwise.bnot/1 instead for clarity", + prepend_warning(Line, Column, Msg, Scope); + _ -> + Scope + end, + Token = {Kind, {Line, Column, nil}, Op}, - tokenize(Remaining, NewLine, NewColumn, Scope, [Token | Tokens]) + tokenize(Remaining, NewLine, NewColumn, NewScope, [Token | Tokens]) end. handle_op([$: | Rest], Line, Column, _Kind, Length, Op, Scope, Tokens) when ?is_space(hd(Rest)) -> @@ -904,10 +914,6 @@ handle_op(Rest, Line, Column, Kind, Length, Op, Scope, Tokens) -> Msg = "^^^ is deprecated. It is typically used as xor but it has the wrong precedence, use Bitwise.bxor/2 instead", prepend_warning(Line, Column, Msg, Scope); - '~~~' -> - Msg = "~~~ is deprecated. Use Bitwise.bnot/1 instead for clarity", - prepend_warning(Line, Column, Msg, Scope); - '<|>' -> Msg = "<|> is deprecated. Use another pipe-like operator", prepend_warning(Line, Column, Msg, Scope); diff --git a/lib/elixir/test/erlang/tokenizer_test.erl b/lib/elixir/test/erlang/tokenizer_test.erl index b383a74b1c3..5fecbf6aac5 100644 --- a/lib/elixir/test/erlang/tokenizer_test.erl +++ b/lib/elixir/test/erlang/tokenizer_test.erl @@ -16,6 +16,10 @@ tokenize_error(String) -> {error, Error, _, _, _} = elixir_tokenizer:tokenize(String, 1, []), Error. +tokenize_warnings(String) -> + {ok, _Line, _Column, Warnings, Result, []} = elixir_tokenizer:tokenize(String, 1, []), + {lists:reverse(Result), Warnings}. + type_test() -> [{int, {1, 1, 1}, "1"}, {type_op, {1, 3, nil}, '::'}, @@ -279,3 +283,13 @@ sigil_heredoc_test() -> invalid_sigil_delimiter_test() -> {[{line, 1}, {column, 1}], "invalid sigil delimiter: ", Message} = tokenize_error("~s\\"), true = lists:prefix("\"\\\" (column 3, code point U+005C)", lists:flatten(Message)). + +deprecated_operators_test() -> + { + [{xor_op, {1, 1, nil}, '^^^'}, {int, {1, 4, 1}, "1"}], + [{{1, 1}, "^^^ is deprecated. It is typically used as xor but it has the wrong precedence, use Bitwise.bxor/2 instead"}] + } = tokenize_warnings("^^^1"), + { + [{unary_op, {1, 1, nil}, '~~~'}, {int, {1, 4, 1}, "1"}], + [{{1, 1}, "~~~ is deprecated. Use Bitwise.bnot/1 instead for clarity"}] + } = tokenize_warnings("~~~1").