{"id":15470451,"url":"https://github.com/adroll/rebar3_hank","last_synced_at":"2025-04-06T10:11:50.549Z","repository":{"id":37980933,"uuid":"321259416","full_name":"AdRoll/rebar3_hank","owner":"AdRoll","description":"The Erlang Dead Code Cleaner","archived":false,"fork":false,"pushed_at":"2024-07-08T05:52:40.000Z","size":284,"stargazers_count":68,"open_issues_count":11,"forks_count":9,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-06T10:11:42.619Z","etag":null,"topics":["erlang","hacktoberfest","rebar3-plugin"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AdRoll.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-14T06:52:33.000Z","updated_at":"2024-09-25T16:40:17.000Z","dependencies_parsed_at":"2023-02-19T07:31:04.804Z","dependency_job_id":"bcf52de0-2ce0-42f8-87b1-df9e8e5d2ce4","html_url":"https://github.com/AdRoll/rebar3_hank","commit_stats":{"total_commits":160,"total_committers":12,"mean_commits":"13.333333333333334","dds":0.575,"last_synced_commit":"3e4b2b92b79eeaf91e43236293594ec0d0f0b6b6"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdRoll%2Frebar3_hank","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdRoll%2Frebar3_hank/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdRoll%2Frebar3_hank/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdRoll%2Frebar3_hank/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AdRoll","download_url":"https://codeload.github.com/AdRoll/rebar3_hank/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247464222,"owners_count":20942970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erlang","hacktoberfest","rebar3-plugin"],"created_at":"2024-10-02T02:04:44.728Z","updated_at":"2025-04-06T10:11:50.511Z","avatar_url":"https://github.com/AdRoll.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rebar3_hank [![Build Status](https://github.com/AdRoll/rebar3_hank/actions/workflows/erlang.yml/badge.svg)](https://github.com/AdRoll/rebar3_hank) [![Hex pm](http://img.shields.io/hexpm/v/rebar3_hank.svg?style=flat)](https://hex.pm/packages/rebar3_hank)\n### The Erlang Dead Code Cleaner\n\n\u003cimg src=\"https://repository-images.githubusercontent.com/321259416/91eb8780-3de1-11eb-83e2-be100515c76b\" width=\"300\" alt=\"Kill it with Fire\" /\u003e\n\n\u003e Mr. Scorpio says productivity is up 2%, and it's all because of my motivational techniques, like donuts and the possibility of more donuts to come.\n\u003e\n\u003e _(Homer Simpson)_\n\n## Sample Output\n\nIf Hank detects issues in your code, it will report them as follows…\n\n```\nsrc/lapp.erl:18: maybe_evaluate/3 doesn't need its #2 argument\nsrc/lapp.erl:15: maybe_evaluate/2 doesn't need its #1 argument\nsrc/lapp.erl:5: ?DEFAULT_SAMPLE_RATE is unused\nsrc/lapp.app.src:0: sample_rate is not used anywhere in the code\nsrc/include/header.hrl:2: ?SOME_MACRO/1 is used only at src/lapp.erl\nsrc/my_behaviour.erl:3: Callback process/1 is not used anywhere in the module\nsrc/include/header.hrl:1: ?APP_HEADER is unused\nsrc/main.erl:8: Field color in record state is unused\n```\n\n## Build\n\n```bash\n$ rebar3 compile\n```\n\n## Test\n\n```bash\n$ rebar3 test\n```\n\n## Usage\n\nAdd the plugin to your rebar config:\n\n```erlang\n{project_plugins, [rebar3_hank]}\n```\n\nThen just call the plugin directly in an existing application:\n\n```bash\n$ rebar3 hank # or…\n$ rebar3 kiwf # (Kill It With Fire)\n```\n\nThis will review your project, analyzing every `*.[he]rl` file in it (optionally skipping some folders/files if you want to - see below).\nNote that Hank will **not** consider files from your project dependencies for the analysis. It will only check the source code in your current application (_applications_, if you're working in an umbrella project).\n\nIt will then apply its rules and produce a list of all the dead code (_specially **oxbow** code_) that you can effectively delete and/or refactor.\n\n### Command-Line Options\n\n```\n$ rebar3 help hank\n\nUsage: rebar3 hank [-u \u003cunused_ignores\u003e]\n\n  -u, --unused_ignores  Warn on unused ignores (default: true).\n\n```\nBy 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`.\n\nIt'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.\n\n```markdown\n===\u003e The following ignore specs are no longer needed and can be removed:\n* src/ignore_not_empty.erl: unused_hrls\n* src/ignore_not_empty.erl: unused_configuration_options\n```\n\n## Certainty\n\nIn principle, Hank should have _Dialyzer_ levels of certainty. That is: if Hank points at some code, you can be **100% sure** it's _dead_.\n\nThat means that if you find some false positives (i.e. Hank pointed at some code that was not really dead / should not be deleted), **please** report it as **a bug** and we'll take care of fixing it.\n\n## Configuration\n\nThe plugin supports the following configuration options in the `hank` section of `rebar.config`:\n\n* `rules` (`[hank_rule:t()]`):\n    - This is the list of rules to apply to the analyzed code. Each rule is a module that should apply the `hank_rule` behavior.\n    - If this option is not defined, Hank will apply all [the default rules](src/rules).\n* `parsing_style` (`hank:parsing_style()`):\n    - This parameter determines if Hank should parse files in a parallel (`rpc:pmap/3`) or sequential (`lists:map/2`) fashion.\n    - The default value is `parallel` since it's faster.\n    - It's recommended to use `sequential` when reporting bugs since the error descriptions are usually more detailed.\n* `ignore` (`[file:filename_all() | {file:filename_all(), hank_rule:t() | [hank_rule:t()]} | {file:filename_all(), hank_rule:t() | [hank_rule:t()], list()}]`):\n    - List of wildcard patterns representing the files and rules that Hank will ignore when formatting. Tuple format is used to ignore either a specific rule or a set of rules in those files.\n  ```erlang\n  % single rule\n  {hank,\n   [{ignore, [\n    \"rel/**/*\",\n    \"lib/some_module.erl\",\n    {\"test/**/*.erl\", unnecessary_function_arguments}\n  ]}]}\n  ```\n  or\n  ```erlang\n  % set of rules (after expansion, the same wildcard and options are used for all rules)\n  {hank,\n   [{ignore, [\n    {\"test/**/*.erl\", [unused_macros, unnecessary_function_arguments]}\n  ]}]}\n  ```\n    - For ignoring options for `unused_configuration_options` rule, set a list of keys from the .config files you want to ignore.\n  ```erlang\n  {hank,\n   [{ignore, [\n    {\"sys.config\", unused_configuration_options, [not_used_but_ignored]}\n  ]}]}\n  ```\n    - You can also ignore a specific file adding the attribute `-hank ignore.` to it.\n    - And you can ignore specific rules adding the attribute `-hank [hank_rule:t()].` with the list of rules you want to ignore.\n\n### Ignore specific rule items\nYou can even ignore specific rule items with the `-hank` attribute by giving extra _ignore specifications_ for each rule, example:\n```erlang\n-hank([single_use_hrls, %% Will ignore the whole rule within the module\n       {unused_macros,\n          [\"ALL\", %% Will ignore ?ALL, ?ALL() and ?ALL(X)\n           {\"ZERO\", 0}, %% Will ignore ?ZERO() but not ?ZERO(X) nor ?ZERO\n           {\"ONE\",  1}, %% Will ignore ?ONE(X) but not ?ONE()   nor ?ONE\n           {\"NONE\", none} %% Will ignore ?NONE but not ?NONE(X) nor ?NONE()\n           ]},\n       {unused_record_fields,\n           [a_record, %% Will ignore all fields in #a_record\n            {a_record, a_field} %% Will ignore #a_record.a_field\n           ]},\n       {unused_callbacks,\n           [all, %% Will ignore all versions of the all callback (i.e. any arity)\n            {just, 1} %% Will ignore just(term()) but not just() nor just(_, _) callbacks\n           ]},\n       {unused_configuration_options,\n           [option, %% Will ignore any appearance of option\n            {\"this_file.config\", option} %% Will ignore option if it appears in \"this_file.config\"\n           ]},\n       {single_use_hrl_attrs,\n           [\"ALL\",          %% Will ignore ?ALL, ?ALL() and ?ALL(X)\n            {\"ZERO\", 0},    %% Will ignore ?ZERO() but not ?ZERO(X) nor ?ZERO\n            {\"ONE\",  1},    %% Will ignore ?ONE(X) but not ?ONE()   nor ?ONE\n            {\"NONE\", none}, %% Will ignore ?NONE   but not ?NONE(X) nor ?NONE()\n            record_name     %% Will ignore #record_name\n           ]},\n       {unnecessary_function_arguments,\n           [{ignore_me, 2}, %% Will ignore any unused argument from ignore_me/2\n            {ignore_me_too, 3, 2}, %% Will ignore the 2nd argument from ignore_me_too/3\n            ignore_me_again]}]). %% Will ignore any unused argument from any `ignore_me_again/x` within the module (no matter the arity)\n```\nRefer to each rule documentation for further details.\n\n## Rules\n\nFind detailed information about the rules provided by Hank in [hex docs](https://hexdocs.pm/rebar3_hank/).\n\n## Full Example\n\n[**@elbrujohalcon**](https://github.com/elbrujohalcon) presented Hank in a lightning talk at CodeBEAM V SF 2021. Watch his talk where he shows an example of using Hank in an iterative process:\n\n[![Hank @ CodeBEAM V SF 2021](http://img.youtube.com/vi/JWicgBIoUTM/0.jpg)](http://www.youtube.com/watch?v=JWicgBIoUTM \"Hank @ CodeBEAM V SF 2021\")\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadroll%2Frebar3_hank","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadroll%2Frebar3_hank","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadroll%2Frebar3_hank/lists"}