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

Feature: Store hank output in json file #184

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,19 @@ $ rebar3 help hank

Usage: rebar3 hank [-u <unused_ignores>]

-u, --unused_ignores Warn on unused ignores (default: true).
Usage: rebar3 hank [-u <unused_ignores>] [-o <output_json_file>]

-u, --unused_ignores Warn on unused ignores (default: true).
-o, --output_json_file Emit output (in JSON format) to a file (default: empty string - meaning: donot emit output
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-o, --output_json_file Emit output (in JSON format) to a file (default: empty string - meaning: donot emit output
-o, --output_json_file Emit output (in JSON format) to a file (default: empty string - meaning: do not emit output).


```
By default, Hank will emit warnings such as the following ones if you are ignoring rules that you don't need to ignore (more on that below). But you can turn those warnings off, by using `--unused_ignores=no`.

It's worth noting that, even when those warnings are printed, that doesn't affect the overall result of the command. That is, if Hank can't find any instances of oxbow code, it will return successfully (i.e. `exit code: 0`) even when it may print these warnings.

By default, if hank detect issues in your code, it will print those issue on the console. But you can save this result in JSON format,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
By default, if hank detect issues in your code, it will print those issue on the console. But you can save this result in JSON format,
By default, if Hank detects issues in your code, it will print those issues on the console. But you can save this result in a file (in JSON format),

by using `--output_json_file=output_filename.json`.

```markdown
===> The following ignore specs are no longer needed and can be removed:
* src/ignore_not_empty.erl: unused_hrls
Expand Down
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
{rebar3_format, "~> 1.2.0"},
{rebar3_lint, "~> 1.1.0"},
{rebar3_sheldon, "~> 0.4.2"},
{rebar3_ex_doc, "~> 0.2.11"}]}.
{rebar3_ex_doc, "~> 0.2.11"},
{jsx, "~> 3.1.0"}]}.

{dialyzer, [{warnings, [no_return, unmatched_returns, error_handling, underspecs]}]}.

Expand Down
33 changes: 33 additions & 0 deletions src/hank_rule.erl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
-export([default_rules/0]).
-export([analyze/3]).
-export([is_ignored/3]).
-export([result_to_json/1]).

%% @doc The list of default rules to apply
-spec default_rules() -> [].
Expand Down Expand Up @@ -47,3 +48,35 @@ analyze(Rule, ASTs, Context) ->
-spec is_ignored(t(), ignore_pattern(), all | term()) -> boolean().
is_ignored(Rule, Pattern, IgnoreSpec) ->
IgnoreSpec =:= all orelse Rule:ignored(Pattern, IgnoreSpec).

-spec result_to_json(hank_rule:result()) -> map().
result_to_json(Data) ->
#{file := FileName, line := Line, rule := RuleBroken, text := Description} = Data,
#{
<<"path">> => iolist_to_binary(FileName),
<<"start_line">> => Line,
<<"hank_rule_broken">> => atom_to_binary(RuleBroken),
<<"title">> => compute_title(RuleBroken),
<<"message">> => iolist_to_binary(Description)
}.

-spec compute_title(atom()) -> binary().
compute_title(RuleBroken) ->
case RuleBroken of
unused_macros ->
<<"Unused Macros">>;
single_use_hrl_attrs ->
<<"Macro is only used once">>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<<"Macro is only used once">>;
<<"Macro only used once">>;

unused_record_fields ->
<<"Field in the record is unused">>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<<"Field in the record is unused">>;
<<"Unused field in record">>;

unused_hrls ->
<<"Unused hrl files">>;
unused_configuration_options ->
<<"Unused config">>;
unused_callbacks ->
<<"Unused callback functions">>;
unnecessary_function_arguments ->
<<"Unused function arguments found">>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<<"Unused function arguments found">>;
<<"Unused function arguments">>;

single_use_hrls ->
<<"Hrl is only used once">>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<<"Hrl is only used once">>
<<"Hrl file only used once">>

end.
25 changes: 24 additions & 1 deletion src/rebar3_hank_prv.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ opts() ->
$u,
"unused_ignores",
boolean,
"Warn on unused ignores (default: true)."}].
"Warn on unused ignores (default: true)."},
{output_json_file,
$o,
"output_json_file",
string,
"Emit output (in JSON format) to a file (default: empty string - meaning: donot emit output"}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Emit output (in JSON format) to a file (default: empty string - meaning: donot emit output"}
"Emit output (in JSON format) to a file (default: empty string - meaning: do not emit output)"}

].

%% @private
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, iodata()}.
Expand Down Expand Up @@ -69,6 +75,7 @@ do(State) ->
unused_ignores := UnusedIgnores,
stats := Stats} ->
instrument(Stats, UnusedIgnores, State),
maybe_write_data_to_json_file(Results, State),
{error, format_results(Results)}
catch
Kind:Error:Stack ->
Expand Down Expand Up @@ -120,6 +127,22 @@ format_result(#{file := File,
text := Msg}) ->
hank_utils:format_text("~ts:~tp: ~ts", [File, Line, Msg]).

-spec maybe_write_data_to_json_file([hank_rule:result()], rebar_state:t()) -> ok.
maybe_write_data_to_json_file(Result, State) ->
{Args, _} = rebar_state:command_parsed_args(State),
case lists:keyfind(output_json_file, 1, Args) of
{output_json_file, JsonFilePath} ->
ConvertedResult = convert_data_to_binary(Result),
EncodedResult = jsx:encode(ConvertedResult),
ok = file:write_file(JsonFilePath, EncodedResult);
_ ->
ok
end.

-spec convert_data_to_binary([hank_rules:result()]) -> list().
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't return binaries. Therefore, its name is wrong. A better name would be results_to_json.

convert_data_to_binary(Results) ->
lists:map(fun hank_rule:result_to_json/1, Results).

%% @private
%% @doc Determines files that should be fully hidden to Hank.
is_hidden(Filename) ->
Expand Down