Skip to content

Commit 41ad1f7

Browse files
Add support for mix format plugins (#660) (#690)
* Use formatter_for_file instead of formatter_opts_for_file which is deprecated now * Fallback to original Code.format_string! Co-authored-by: Dalibor Horinek <dal@horinek.net>
1 parent 2db8acc commit 41ad1f7

File tree

4 files changed

+36
-15
lines changed

4 files changed

+36
-15
lines changed

apps/language_server/lib/language_server/providers/execute_command/apply_spec.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ApplySpec do
5656
formatted =
5757
try do
5858
target_line_length =
59-
case SourceFile.formatter_opts(uri) do
60-
{:ok, opts} -> Keyword.get(opts, :line_length, @default_target_line_length)
59+
case SourceFile.formatter_for(uri) do
60+
{:ok, {_, opts}} -> Keyword.get(opts, :line_length, @default_target_line_length)
6161
:error -> @default_target_line_length
6262
end
6363

@@ -94,3 +94,4 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ApplySpec do
9494
end
9595
end
9696
end
97+

apps/language_server/lib/language_server/providers/formatting.ex

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ defmodule ElixirLS.LanguageServer.Providers.Formatting do
55

66
def format(%SourceFile{} = source_file, uri, project_dir) when is_binary(project_dir) do
77
if can_format?(uri, project_dir) do
8-
case SourceFile.formatter_opts(uri) do
8+
case SourceFile.formatter_for(uri) do
9+
{:ok, {formatter, opts}} ->
10+
if should_format?(uri, project_dir, opts[:inputs]) do
11+
do_format(source_file, formatter, opts)
12+
else
13+
{:ok, []}
14+
end
15+
916
{:ok, opts} ->
1017
if should_format?(uri, project_dir, opts[:inputs]) do
1118
do_format(source_file, opts)
@@ -29,8 +36,11 @@ defmodule ElixirLS.LanguageServer.Providers.Formatting do
2936
do_format(source_file)
3037
end
3138

32-
defp do_format(%SourceFile{text: text}, opts \\ []) do
33-
formatted = IO.iodata_to_binary([Code.format_string!(text, opts), ?\n])
39+
40+
defp do_format(%SourceFile{} = source_file, opts \\ []), do: do_format(source_file, nil, opts)
41+
42+
defp do_format(%SourceFile{text: text}, formatter, opts) do
43+
formatted = get_formatted(text, formatter, opts)
3444

3545
response =
3646
text
@@ -43,6 +53,14 @@ defmodule ElixirLS.LanguageServer.Providers.Formatting do
4353
{:error, :internal_error, "Unable to format due to syntax error"}
4454
end
4555

56+
defp get_formatted(text, formatter, _) when is_function(formatter) do
57+
formatter.(text)
58+
end
59+
60+
defp get_formatted(text, _, opts) do
61+
IO.iodata_to_binary([Code.format_string!(text, opts), ?\n])
62+
end
63+
4664
# If in an umbrella project, the cwd might be set to a sub-app if it's being compiled. This is
4765
# fine if the file we're trying to format is in that app. Otherwise, we return an error.
4866
defp can_format?(file_uri = "file:" <> _, project_dir) do

apps/language_server/lib/language_server/server.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,8 @@ defmodule ElixirLS.LanguageServer.Server do
674674
!!get_in(state.client_capabilities, ["textDocument", "signatureHelp"])
675675

676676
locals_without_parens =
677-
case SourceFile.formatter_opts(uri) do
678-
{:ok, opts} -> Keyword.get(opts, :locals_without_parens, [])
677+
case SourceFile.formatter_for(uri) do
678+
{:ok, {_, opts}} -> Keyword.get(opts, :locals_without_parens, [])
679679
:error -> []
680680
end
681681
|> MapSet.new()
@@ -1278,3 +1278,4 @@ defmodule ElixirLS.LanguageServer.Server do
12781278
end)
12791279
end
12801280
end
1281+

apps/language_server/lib/language_server/source_file.ex

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,16 +334,16 @@ defmodule ElixirLS.LanguageServer.SourceFile do
334334
"""
335335
end
336336

337-
@spec formatter_opts(String.t()) :: {:ok, keyword()} | :error
338-
def formatter_opts(uri = "file:" <> _) do
337+
@spec formatter_for(String.t()) :: {:ok, keyword()} | :error
338+
def formatter_for(uri = "file:" <> _) do
339339
path = path_from_uri(uri)
340340

341341
try do
342-
opts =
343-
path
344-
|> Mix.Tasks.Format.formatter_opts_for_file()
345-
346-
{:ok, opts}
342+
if function_exported?(Mix.Tasks.Format, :formatter_for_file, 1) do
343+
{:ok, Mix.Tasks.Format.formatter_for_file(path)}
344+
else
345+
{:ok, {nil, Mix.Tasks.Format.formatter_opts_for_file(path)}}
346+
end
347347
rescue
348348
e ->
349349
IO.warn(
@@ -354,7 +354,7 @@ defmodule ElixirLS.LanguageServer.SourceFile do
354354
end
355355
end
356356

357-
def formatter_opts(_), do: :error
357+
def formatter_for(_), do: :error
358358

359359
defp format_code(code, opts) do
360360
try do
@@ -431,3 +431,4 @@ defmodule ElixirLS.LanguageServer.SourceFile do
431431
{elixir_line - 1, utf16_character}
432432
end
433433
end
434+

0 commit comments

Comments
 (0)