Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read input only once #346

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 19 additions & 72 deletions src/erlfmt.erl
Original file line number Diff line number Diff line change
Expand Up @@ -66,53 +66,19 @@ init(State) ->

%% API entry point
-spec format_file(file:name_all() | stdin, config()) ->
{ok, [unicode:chardata()], [error_info()]} | {skip, string()} | {error, error_info()}.
format_file(FileName, Options) ->
Range = proplists:get_value(range, Options),
case Range of
undefined ->
% Whole file (default).
format_file_full(FileName, Options);
{Start, End} ->
% Remove 'range' property: when applicable we pass explicitly the range instead.
% Also, match specifition of format_string_range.
Options2 = proplists:delete(range, Options),
format_file_range(FileName, {Start, 1}, {End, ?DEFAULT_WIDTH}, Options2)
end.
{ok, string(), string(), [error_info()]} | {skip, string()} | {error, error_info()}.
format_file(FileName, Options0) ->
Options = [{filename, FileName} | Options0],

-spec format_file_full(file:name_all() | stdin, config()) ->
{ok, [unicode:chardata()], [error_info()]} | {skip, string()} | {error, error_info()}.
format_file_full(FileName, Options) ->
PrintWidth = proplists:get_value(print_width, Options, ?DEFAULT_WIDTH),
Pragma = proplists:get_value(pragma, Options, ignore),
try
case file_read_nodes(FileName, Pragma) of
{ok, Nodes0, Warnings} ->
Nodes =
case Pragma of
insert -> insert_pragma_nodes(Nodes0);
delete -> remove_pragma_nodes(Nodes0);
_ -> Nodes0
end,
Formatted = format_nodes(Nodes, PrintWidth),
verify_nodes(FileName, Nodes, Formatted),
VerboseWarnings =
case proplists:get_bool(verbose, Options) of
true -> check_line_lengths(FileName, PrintWidth, Formatted);
false -> []
end,
{ok, Formatted, Warnings ++ VerboseWarnings};
{skip, RawString} ->
{skip, RawString}
end
catch
{error, Error} -> {error, Error}
case read_file_or_stdin(FileName) of
{error, Error} -> {error, Error};
Original -> format_string(Original, Options)
end.

-spec format_string(string(), [
config_option() | {filename, string()} | {range, erlfmt_scan:location()}
]) ->
{ok, string(), [error_info()]} | {skip, string()} | {error, error_info()}.
{ok, string(), string(), [error_info()]} | {skip, string()} | {error, error_info()}.
format_string(String, Options) ->
Range = proplists:get_value(range, Options),
case Range of
Expand All @@ -127,7 +93,7 @@ format_string(String, Options) ->
end.

-spec format_string_full(string(), [config_option() | {filename, string()}]) ->
{ok, string(), [error_info()]} | {skip, string()} | {error, error_info()}.
{ok, string(), string(), [error_info()]} | {skip, string()} | {error, error_info()}.
format_string_full(String, Options) ->
Filename = proplists:get_value(filename, Options, "nofile"),
PrintWidth = proplists:get_value(print_width, Options, ?DEFAULT_WIDTH),
Expand All @@ -148,7 +114,7 @@ format_string_full(String, Options) ->
true -> check_line_lengths(Filename, PrintWidth, Formatted);
false -> []
end,
{ok, unicode:characters_to_list(Formatted), Warnings ++ VerboseWarnings};
{ok, String, unicode:characters_to_list(Formatted), Warnings ++ VerboseWarnings};
{skip, RawString} ->
{skip, RawString}
end
Expand Down Expand Up @@ -278,7 +244,7 @@ replace_pragma_comment_block(Prefix, [Head | Tail]) ->
erlfmt_scan:location(),
[{print_width, pos_integer()}]
) ->
{ok, string(), [error_info()]}
{ok, string(), string(), [error_info()]}
| {skip, string()}
| {error, error_info()}.
format_file_range(FileName, StartLocation, EndLocation, Options) ->
Expand All @@ -291,7 +257,7 @@ format_file_range(FileName, StartLocation, EndLocation, Options) ->
erlfmt_scan:location(),
[{print_width, pos_integer()} | {filename, string()}]
) ->
{ok, string(), [error_info()]}
{ok, string(), string(), [error_info()]}
| {skip, string()}
| {error, error_info()}.
format_string_range(Original, StartLocation, EndLocation, Options) ->
Expand All @@ -312,7 +278,7 @@ format_string_range(FileName, Original, StartLocation, EndLocation, Options) ->
case Result of
{ok, Formatted, Info} ->
Whole = inject_range(Original, StartLine, EndLine, Formatted),
{ok, Whole, Info};
{ok, Original, Whole, Info};
Other ->
% Error or skip.
Other
Expand Down Expand Up @@ -384,38 +350,19 @@ format_range(FileName, StartLocation, EndLocation, Options, Nodes, Warnings) ->
-spec read_nodes(file:name_all()) ->
{ok, [erlfmt_parse:abstract_form()], [error_info()]} | {error, error_info()}.
read_nodes(FileName) ->
try
file_read_nodes(FileName, ignore)
catch
{error, Error} -> {error, Error}
end.

file_read_nodes(FileName, Pragma) ->
read_file(FileName, fun(File) ->
read_nodes(erlfmt_scan:io_node(File), FileName, Pragma)
end).

% Apply 'Action' to file.
read_file(stdin, Action) ->
Action(standard_io);
read_file(FileName, Action) ->
case file:open(FileName, [read, binary, {encoding, unicode}]) of
{ok, File} ->
try
Action(File)
after
file:close(File)
end;
{error, Reason} ->
throw({error, {FileName, 0, file, Reason}})
case read_file_or_stdin(FileName) of
{error, Error} -> {error, Error};
String -> read_nodes_string(FileName, String)
end.

% Return file as one big string (with '\n' as line separator).
read_file_or_stdin(stdin) ->
read_stdin([]);
read_file_or_stdin(FileName) ->
{ok, Bin} = file:read_file(FileName),
unicode:characters_to_list(Bin).
case file:read_file(FileName) of
{ok, Bin} -> unicode:characters_to_list(Bin);
{error, Reason} -> {error, {FileName, 0, file, Reason}}
end.

read_stdin(Acc) ->
case io:get_line("") of
Expand Down
33 changes: 15 additions & 18 deletions src/erlfmt_cli.erl
Original file line number Diff line number Diff line change
Expand Up @@ -193,25 +193,25 @@ format_file(FileName, Config) ->
ok
end,
case Result of
{ok, FormattedText, Warnings} ->
{ok, Original, FormattedText, Warnings} ->
[print_error_info(Warning) || Warning <- Warnings],
write_formatted(FileName, FormattedText, Out);
write_formatted(FileName, Original, FormattedText, Out);
{warn, Warnings} ->
[print_error_info(Warning) || Warning <- Warnings],
io:format(standard_error, "[warn] ~s\n", [FileName]),
warn;
{skip, RawString} ->
write_formatted(FileName, RawString, Out);
write_formatted(FileName, RawString, RawString, Out);
{error, Error} ->
print_error_info(Error),
error
end.

write_formatted(_FileName, _Formatted, check) ->
write_formatted(_FileName, _Original, _Formatted, check) ->
ok;
write_formatted(_FileName, Formatted, standard_out) ->
write_formatted(_FileName, _Original, Formatted, standard_out) ->
io:put_chars(Formatted);
write_formatted(FileName, Formatted, Out) ->
write_formatted(FileName, Original, Formatted, Out) ->
OutFileName = out_file(FileName, Out),
case filelib:ensure_dir(OutFileName) of
ok ->
Expand All @@ -220,14 +220,13 @@ write_formatted(FileName, Formatted, Out) ->
print_error_info({OutFileName, 0, file, Reason1}),
error
end,
{ok, OriginalBin} = file:read_file(FileName),
case unicode:characters_to_binary(Formatted) of
OriginalBin -> ok;
FormattedBin -> write_file(OutFileName, FormattedBin)
case Formatted of
Original -> ok;
_ -> write_file(OutFileName, unicode:characters_to_binary(Formatted))
end.

write_file(OutFileName, FormattedBin) ->
case file:write_file(OutFileName, unicode:characters_to_binary(FormattedBin)) of
case file:write_file(OutFileName, FormattedBin) of
ok ->
ok;
{error, Reason2} ->
Expand All @@ -242,11 +241,9 @@ out_file(FileName, {path, Path}) ->

check_file(FileName, Options) ->
case erlfmt:format_file(FileName, Options) of
{ok, Formatted, FormatWarnings} ->
{ok, OriginalBin} = file:read_file(FileName),
FormattedBin = unicode:characters_to_binary(Formatted),
case FormattedBin of
OriginalBin -> {ok, Formatted, FormatWarnings};
{ok, Original, Formatted, FormatWarnings} ->
case Formatted of
Original -> {ok, Original, Formatted, FormatWarnings};
_ -> {warn, FormatWarnings}
end;
Other ->
Expand All @@ -261,9 +258,9 @@ check_stdin(Options) ->
{ok, OriginalBin} ->
Original = unicode:characters_to_list(OriginalBin),
case erlfmt:format_string(Original, Options) of
{ok, Formatted, FormatWarnings} ->
{ok, _, Formatted, FormatWarnings} ->
case Formatted of
Original -> {ok, Formatted, FormatWarnings};
Original -> {ok, Original, Formatted, FormatWarnings};
_ -> {warn, FormatWarnings}
end;
Other ->
Expand Down
9 changes: 0 additions & 9 deletions src/erlfmt_scan.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
-include("erlfmt_scan.hrl").

-export([
io_node/1,
string_node/1,
continue/1,
last_node_string/1,
Expand Down Expand Up @@ -75,9 +74,6 @@

-opaque state() :: #state{}.

-spec io_node(file:io_device()) -> node_ret().
io_node(IO) -> node(fun io_scan_erl_node/2, IO).

-spec string_node(string()) -> node_ret().
string_node(String) -> node(fun erl_scan_tokens/2, String).

Expand Down Expand Up @@ -108,8 +104,6 @@ continue(Scan, Inner0, Loc0, []) ->
continue(Scan, Inner, Loc, Tokens);
{{error, Reason}, _Inner} ->
{error, {Loc0, file, Reason}};
{eof, _Inner} ->
{eof, Loc0};
{Other, _Inner} ->
Other
end;
Expand Down Expand Up @@ -166,9 +160,6 @@ read_rest(IO, Data) ->
{error, Reason} -> throw({error, Reason})
end.

io_scan_erl_node(IO, Loc) ->
{io:scan_erl_form(IO, "", Loc, ?ERL_SCAN_OPTS), IO}.

erl_scan_tokens(String, Loc) ->
case erl_scan:tokens([], String, Loc, ?ERL_SCAN_OPTS) of
{more, Cont} ->
Expand Down
2 changes: 1 addition & 1 deletion test/assert_diagnostic.erl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ check_elements([H1 | T1], [H2 | T2], I) ->
%% Check the formatted result matches the reference.
assert_snapshot_match(Expected, Output) ->
case Output of
{ok, Formatted, _} ->
{ok, _, Formatted, _} ->
assert_binary_match(Expected, Formatted);
{skip, _} ->
ok;
Expand Down
14 changes: 7 additions & 7 deletions test/erlfmt_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1097,14 +1097,14 @@ format_range(Config, File) ->
DataDir = ?config(data_dir, Config),
Path = DataDir ++ File,
case erlfmt:format_file_range(Path, {3, 45}, {47, 1}, []) of
{ok, _Output, _} -> ok;
{ok, _, _Output, _} -> ok;
{options, Options} -> range_format_exact(Options, Path)
end.

range_format_exact([], _Path) ->
ok;
range_format_exact([{Start, End} | Options], Path) ->
{ok, _Output, _} = erlfmt:format_file_range(Path, Start, End, []),
{ok, _, _Output, _} = erlfmt:format_file_range(Path, Start, End, []),
range_format_exact(Options, Path).

snapshot_range_whole_comments(Config) ->
Expand Down Expand Up @@ -1530,22 +1530,22 @@ contains_pragma_string(String) ->
end.

insert_pragma_string(String) ->
{ok, StringWithPragma, []} = erlfmt:format_string(String, [{pragma, insert}]),
{ok, _, StringWithPragma, []} = erlfmt:format_string(String, [{pragma, insert}]),
%% check that insert_pragma_nodes doesn't insert a pragma, when one has already been inserted.
?assertEqual(
erlfmt:format_string(StringWithPragma, [{pragma, insert}]),
{ok, StringWithPragma, []}
{ok, StringWithPragma, StringWithPragma, []}
),
StringWithPragma.

overlong_warning(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
FileName = filename:join([DataDir, "overlong.erl"]),
Options = [verbose],
{ok, Formatted, FileWarnings} = erlfmt:format_file(FileName, Options),
{ok, _, Formatted, FileWarnings} = erlfmt:format_file(FileName, Options),
FormattedList = unicode:characters_to_list(Formatted),
{ok, _, StringWarnings} = erlfmt:format_string(FormattedList, Options),
{ok, _, RangeWarnings} = erlfmt:format_file_range(
{ok, _, _, StringWarnings} = erlfmt:format_string(FormattedList, Options),
{ok, _, _, RangeWarnings} = erlfmt:format_file_range(
FileName,
{1, 1},
{11, 8},
Expand Down
2 changes: 1 addition & 1 deletion test/erlfmt_format_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ all() ->
end).

format_string(String, Options) ->
{ok, Formatted, []} = erlfmt:format_string(String, Options),
{ok, _, Formatted, []} = erlfmt:format_string(String, Options),
Formatted.

literals(Config) when is_list(Config) ->
Expand Down
2 changes: 1 addition & 1 deletion test/erlfmt_markdown_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,5 @@ strip_good_bad("%% Bad\n" ++ Rest) -> Rest;
strip_good_bad(Rest) -> Rest.

check_fmt(Unformatted, Expected) ->
{ok, Got, []} = erlfmt:format_string(Unformatted, []),
{ok, _, Got, []} = erlfmt:format_string(Unformatted, []),
?assertEqual(string:trim(Expected), string:trim(Got)).