Skip to content

Commit

Permalink
Apply exclude_files to files absolute paths
Browse files Browse the repository at this point in the history
When calling `erlfmt` with absolute paths for the files to format, the
excludes don't apply, even if the resolved paths of the excludes would
match the files to format.

Resolve the paths of the excludes based on the current working directory
and add them to the excludes.

This issue was observed when using the
[VS Code Erlang Formatter extension](https://marketplace.visualstudio.com/items?itemName=szTheory.erlang-formatter).
The extension invokes `rebar3 fmt` with the full path of the file to
format.
  • Loading branch information
danielfinke authored and michalmuskala committed Sep 2, 2024
1 parent 767e5df commit f3be5db
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 11 deletions.
19 changes: 18 additions & 1 deletion src/erlfmt_cli.erl
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,25 @@ with_parsed(Name, Config) ->
erlang:halt(127)
end.

-spec set_difference([file:name_all()], [file:name_all()]) -> [file:name_all()].
set_difference(Files, Excludes) ->
sets:to_list(sets:subtract(sets:from_list(Files), sets:from_list(Excludes))).
{ok, Dir} = file:get_cwd(),
AbsoluteExcludes = [resolve_path(Dir, E) || E <- Excludes],
AllExcludes = sets:from_list(Excludes ++ AbsoluteExcludes),
sets:to_list(sets:subtract(sets:from_list(Files), AllExcludes)).

resolve_path(Dir, Filename) ->
case filename:pathtype(Filename) of
absolute -> Filename;
relative -> resolve_path2(lists:reverse(filename:split(Dir)), filename:split(Filename))
end.

resolve_path2([_H | T1], [".." | T2]) ->
resolve_path2(T1, T2);
resolve_path2([_H | T1], [<<"..">> | T2]) ->
resolve_path2(T1, T2);
resolve_path2(Dir, Filename) ->
filename:join(lists:reverse(Dir) ++ Filename).

%% needed because of getopt
-dialyzer({nowarn_function, [unprotected_with_config/2]}).
Expand Down
41 changes: 31 additions & 10 deletions test/erlfmt_cli_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
noformat_pragma/1,
noformat_pragma_file/1,
exclude_check/1,
exclude_absolute_check/1,
range_check_full/1,
range_check_partial/1
]).
Expand Down Expand Up @@ -98,6 +99,7 @@ groups() ->
noformat_pragma,
noformat_pragma_file,
exclude_check,
exclude_absolute_check,
range_check_full,
range_check_partial
]}
Expand Down Expand Up @@ -250,16 +252,14 @@ noformat_pragma(Config) when is_list(Config) ->
exclude_check(Config) when is_list(Config) ->
Files = filename:join(?config(data_dir, Config), "*.erl"),
Exclude = filename:join(?config(data_dir, Config), "broken.erl"),
WithBroken = os:cmd(
escript() ++ " -c " ++ Files
),
?assertNotMatch(nomatch, string:find(WithBroken, "[warn]")),
?assertNotMatch(nomatch, string:find(WithBroken, "broken.erl")),
WithoutBroken = os:cmd(
escript() ++ " -c " ++ Files ++ " --exclude-files=" ++ Exclude
),
?assertNotMatch(nomatch, string:find(WithoutBroken, "[warn]")),
?assertMatch(nomatch, string:find(WithoutBroken, "broken.erl")).
exclude_test(Files, Exclude).

exclude_absolute_check(Config) when is_list(Config) ->
{ok, ProjectRoot} = file:get_cwd(),
DataDirRelPath = make_relative_path(?config(data_dir, Config), ProjectRoot),
Files = filename:join(?config(data_dir, Config), "*.erl"),
Exclude = filename:join(DataDirRelPath, "broken.erl"),
exclude_test(Files, Exclude).

range_check_full(Config) when is_list(Config) ->
%% Mainly check the options is properly recognized.
Expand All @@ -284,6 +284,27 @@ stdio_test(FileName, Options, Config) ->
{ok, Expected} = file:read_file(Path),
assert_diagnostic:assert_binary_match(Expected, unicode:characters_to_binary(Formatted)).

exclude_test(Files, Exclude) ->
WithBroken = os:cmd(
escript() ++ " -c " ++ Files
),
?assertNotMatch(nomatch, string:find(WithBroken, "[warn]")),
?assertNotMatch(nomatch, string:find(WithBroken, "broken.erl")),
WithoutBroken = os:cmd(
escript() ++ " -c " ++ Files ++ " --exclude-files=" ++ Exclude
),
?assertNotMatch(nomatch, string:find(WithoutBroken, "[warn]")),
?assertMatch(nomatch, string:find(WithoutBroken, "broken.erl")).

escript() ->
%% this relies on the _build structure rebar3 uses
filename:join(code:lib_dir(erlfmt), "../../bin/erlfmt").

make_relative_path(Source, Target) ->
make_relative_path2(filename:split(Source), filename:split(Target)).

make_relative_path2([H | T1], [H | T2]) ->
make_relative_path2(T1, T2);
make_relative_path2(Source, Target) ->
Base = lists:duplicate(length(Target), ".."),
filename:join(Base ++ Source).

0 comments on commit f3be5db

Please sign in to comment.