Skip to content

Commit 4126cdd

Browse files
authored
Add --migrate flag to mix format (#13846)
1 parent 5902c29 commit 4126cdd

File tree

4 files changed

+44
-13
lines changed

4 files changed

+44
-13
lines changed

lib/elixir/src/elixir_bitstring.erl

+5-2
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,13 @@ format_error({undefined_bittype, Expr}) ->
403403
io_lib:format("unknown bitstring specifier: ~ts", ['Elixir.Macro':to_string(Expr)]);
404404
format_error({unknown_bittype, Name}) ->
405405
io_lib:format("bitstring specifier \"~ts\" does not exist and is being expanded to \"~ts()\","
406-
" please use parentheses to remove the ambiguity", [Name, Name]);
406+
" please use parentheses to remove the ambiguity.\n"
407+
"You may run \"mix format --migrate\" to fix this warning automatically.", [Name, Name]);
407408
format_error({parens_bittype, Name}) ->
408409
io_lib:format("extra parentheses on a bitstring specifier \"~ts()\" have been deprecated. "
409-
"Please remove the parentheses: \"~ts\"",
410+
"Please remove the parentheses: \"~ts\".\n"
411+
"You may run \"mix format --migrate\" to fix this warning automatically."
412+
,
410413
[Name, Name]);
411414
format_error({bittype_mismatch, Val1, Val2, Where}) ->
412415
io_lib:format("conflicting ~ts specification for bit field: \"~p\" and \"~p\"", [Where, Val1, Val2]);

lib/elixir/src/elixir_tokenizer.erl

+4-1
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,10 @@ tokenize([$" | T], Line, Column, Scope, Tokens) ->
267267

268268
%% TODO: Remove me in Elixir v2.0
269269
tokenize([$' | T], Line, Column, Scope, Tokens) ->
270-
NewScope = prepend_warning(Line, Column, "single-quoted strings represent charlists. Use ~c\"\" if you indeed want a charlist or use \"\" instead", Scope),
270+
Message = "single-quoted strings represent charlists. "
271+
"Use ~c\"\" if you indeed want a charlist or use \"\" instead.\n"
272+
"You may run \"mix format --migrate\" to fix this warning automatically.",
273+
NewScope = prepend_warning(Line, Column, Message, Scope),
271274
handle_strings(T, Line, Column + 1, $', NewScope, Tokens);
272275

273276
% Operator atoms

lib/mix/lib/mix/tasks/format.ex

+23-10
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ defmodule Mix.Tasks.Format do
7878
as `.heex`. Without passing this flag, it is assumed that the code being
7979
passed via stdin is valid Elixir code. Defaults to "stdin.exs".
8080
81+
* `--migrate` - enables the `:migrate` option, which should be able to
82+
automatically fix some deprecation warnings but is changing the AST.
83+
This should be safe in typical projects, but there is a non-zero risk
84+
of breaking code for meta-programming heavy projects that relied on a
85+
specific AST, or projects that are re-defining functions from the `Kernel`.
86+
See the "Migration formatting" section in `Code.format_string!/2` for
87+
more information.
88+
8189
## When to format code
8290
8391
We recommend developers to format code directly in their editors, either
@@ -184,7 +192,8 @@ defmodule Mix.Tasks.Format do
184192
dot_formatter: :string,
185193
dry_run: :boolean,
186194
stdin_filename: :string,
187-
force: :boolean
195+
force: :boolean,
196+
migrate: :boolean
188197
]
189198

190199
@manifest_timestamp "format_timestamp"
@@ -362,17 +371,21 @@ defmodule Mix.Tasks.Format do
362371
end
363372

364373
defp eval_dot_formatter(cwd, opts) do
365-
cond do
366-
dot_formatter = opts[:dot_formatter] ->
367-
{dot_formatter, eval_file_with_keyword_list(dot_formatter)}
374+
{dot_formatter, format_opts} =
375+
cond do
376+
dot_formatter = opts[:dot_formatter] ->
377+
{dot_formatter, eval_file_with_keyword_list(dot_formatter)}
368378

369-
File.regular?(Path.join(cwd, ".formatter.exs")) ->
370-
dot_formatter = Path.join(cwd, ".formatter.exs")
371-
{".formatter.exs", eval_file_with_keyword_list(dot_formatter)}
379+
File.regular?(Path.join(cwd, ".formatter.exs")) ->
380+
dot_formatter = Path.join(cwd, ".formatter.exs")
381+
{".formatter.exs", eval_file_with_keyword_list(dot_formatter)}
372382

373-
true ->
374-
{".formatter.exs", []}
375-
end
383+
true ->
384+
{".formatter.exs", []}
385+
end
386+
387+
# the --migrate flag overrides settings from the dot formatter
388+
{dot_formatter, Keyword.take(opts, [:migrate]) ++ format_opts}
376389
end
377390

378391
# This function reads exported configuration from the imported

lib/mix/test/mix/tasks/format_test.exs

+12
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,18 @@ defmodule Mix.Tasks.FormatTest do
534534
end)
535535
end
536536

537+
test "respects the --migrate flag", context do
538+
in_tmp(context.test, fn ->
539+
File.write!("a.ex", "unless foo, do: 'bar'\n")
540+
541+
Mix.Tasks.Format.run(["a.ex"])
542+
assert File.read!("a.ex") == "unless foo, do: 'bar'\n"
543+
544+
Mix.Tasks.Format.run(["a.ex", "--migrate"])
545+
assert File.read!("a.ex") == "if !foo, do: ~c\"bar\"\n"
546+
end)
547+
end
548+
537549
test "uses inputs and configuration from --dot-formatter", context do
538550
in_tmp(context.test, fn ->
539551
File.write!("custom_formatter.exs", """

0 commit comments

Comments
 (0)