|
1 | | -# xref_runner |
2 | | -Erlang Xref Runner (inspired in rebar xref) |
| 1 | + |
| 2 | + |
| 3 | +# Xref Runner |
| 4 | +Erlang Xref Runner (inspired in rebar's rebar_xref) |
| 5 | + |
| 6 | +## Contact Us |
| 7 | +For **questions** or **general comments** regarding the use of this library, |
| 8 | +please use our public [hipchat room](https://www.hipchat.com/gpBpW3SsT). |
| 9 | + |
| 10 | +If you find any **bugs** or have a **problem** while using this library, please |
| 11 | +[open an issue](https://github.com/inaka/elvis/issues/new) in this repo |
| 12 | +(or a pull request :)). |
| 13 | + |
| 14 | +And you can check all of our open-source projects at [inaka.github.io](http://inaka.github.io). |
| 15 | + |
| 16 | +## Why Xref Runner? |
| 17 | +So, Erlang/OTP comes with an excellent tool to check your code and detect bugs: [Xref](http://www.erlang.org/doc/apps/tools/xref_chapter.html). |
| 18 | +The problem lies in its not-extremely-simple interface. Using `xref` out of the box requires you to start a process, set up parameters, add directories, etc. before you can actually just run the checks you want to run. |
| 19 | +To mitigate that, [rebar](http://github.com/rebar/rebar) comes with a handy command line tool (`rebar xref`) that prints xref generated warnings on your console. |
| 20 | +But, sometimes, you don't want to use rebar or you want to get the warnings as erlang terms and not just printed out in the console. |
| 21 | +That's when xref_runner comes along. |
| 22 | + |
| 23 | +## How to Use it? |
| 24 | +Just make sure it's in your code path and call `xref_runner:check/2` with the proper parameters. |
| 25 | + |
| 26 | +The first parameter is one of the available checks provided by `xref`: |
| 27 | +```erlang |
| 28 | +-type check() :: undefined_function_calls |
| 29 | + | undefined_functions |
| 30 | + | locals_not_used |
| 31 | + | exports_not_used |
| 32 | + | deprecated_function_calls |
| 33 | + | deprecated_functions. |
| 34 | +``` |
| 35 | + |
| 36 | +The second paramter is a configuration map. All of its fields are optional. The allowed fields are: |
| 37 | + |
| 38 | +* **extra_paths**: Directories to be added to the xref code path. _default value:_ `[]` |
| 39 | +* **xref_defaults**: Default values to configure xref (check `xref:set_default`). _default value:_ `[]` |
| 40 | +* **dirs**: Directories to be scanned with `xref`. _default value:_ `["ebin"]` |
| 41 | + |
| 42 | +Using that function will give you a list of _warnings_ as its result. Warnings are also maps with the following fields: |
| 43 | + |
| 44 | +* **filename**: The name of the file for which the warning is reported |
| 45 | +* **line**: The line number where the warning is reported. `0` means it's a module-level warning (like an undefined function). _Note:_ In case of warnings with source and target, line numbers refer to the line in which the source function is _defined_, not the line where the target function is _used_. |
| 46 | +* **source**: Module, function and argument number where the warning is found |
| 47 | +* **target** _(optional)_: For `undefined_function_calls` and `deprecated_function_calls`, function call that generates the warning. |
| 48 | + |
| 49 | +## Examples |
| 50 | +Using the modules in the [examples](test/examples) folder, these are some of the results generated by the tests: |
| 51 | + |
| 52 | +```erlang |
| 53 | +> xref_runner:check(undefined_function_calls, #{dirs => ["test"]}). |
| 54 | +[#{filename => "test/examples/undefined_function_calls.erl", |
| 55 | + line => 5, |
| 56 | + source => {undefined_function_calls,bad,0}, |
| 57 | + target => {undefined_function_calls,undefined_here,0}}, |
| 58 | + #{filename => "test/examples/undefined_function_calls.erl", |
| 59 | + line => 9, |
| 60 | + source => {undefined_function_calls,bad,1}, |
| 61 | + target => {other_module,undefined_somewhere_else,1}}, |
| 62 | + #{filename => "test/examples/undefined_function_calls.erl", |
| 63 | + line => 9, |
| 64 | + source => {undefined_function_calls,bad,1}, |
| 65 | + target => {undefined_functions,undefined_there,0}}, |
| 66 | + … |
| 67 | +] |
| 68 | +``` |
| 69 | + |
| 70 | +```erlang |
| 71 | +> xref_runner:check(undefined_functions, #{dirs => ["test"], |
| 72 | + xref_defaults => []}). |
| 73 | +[#{filename => [],line => 0,source => {other_module,undefined_somewhere_else,0}}, |
| 74 | + #{filename => [],line => 0,source => {other_module,undefined_somewhere_else,1}}, |
| 75 | + #{filename => "test/examples/undefined_function_calls.erl", |
| 76 | + line => 0, |
| 77 | + source => {undefined_function_calls,undefined_here,0}}, |
| 78 | + … |
| 79 | +] |
| 80 | +``` |
| 81 | + |
| 82 | +```erlang |
| 83 | +> xref_runner:check(locals_not_used, #{dirs => ["test"]}). |
| 84 | +[#{filename => "test/examples/locals_not_used.erl", |
| 85 | + line => 9, |
| 86 | + source => {locals_not_used,local_not,1}}] |
| 87 | +``` |
| 88 | + |
| 89 | +```erlang |
| 90 | +> xref_runner:check(exports_not_used, #{dirs => ["test"]}). |
| 91 | +[#{filename => "test/examples/deprecated_function_calls.erl", |
| 92 | + line => 7, |
| 93 | + source => {deprecated_function_calls,bad,0}}, |
| 94 | + #{filename => "test/examples/deprecated_function_calls.erl", |
| 95 | + line => 10, |
| 96 | + source => {deprecated_function_calls,bad,1}}, |
| 97 | + #{filename => "test/examples/deprecated_function_calls.erl", |
| 98 | + line => 14, |
| 99 | + source => {deprecated_function_calls,good,0}}, |
| 100 | +… |
| 101 | +] |
| 102 | +``` |
| 103 | + |
| 104 | +```erlang |
| 105 | +> xref_runner:check(deprecated_function_calls, #{dirs => ["test"]}). |
| 106 | +[#{filename => "test/examples/deprecated_function_calls.erl", |
| 107 | + line => 7, |
| 108 | + source => {deprecated_function_calls,bad,0}, |
| 109 | + target => {deprecated_functions,deprecated,0}}, |
| 110 | + #{filename => "test/examples/deprecated_function_calls.erl", |
| 111 | + line => 10, |
| 112 | + source => {deprecated_function_calls,bad,1}, |
| 113 | + target => {deprecated_function_calls,internal,0}}, |
| 114 | + #{filename => "test/examples/deprecated_function_calls.erl", |
| 115 | + line => 10, |
| 116 | + source => {deprecated_function_calls,bad,1}, |
| 117 | + target => {deprecated_functions,deprecated,1}}, |
| 118 | + … |
| 119 | +] |
| 120 | +``` |
| 121 | + |
| 122 | +```erlang |
| 123 | +> xref_runner:check(deprecated_functions, #{dirs => ["test"]}). |
| 124 | +[#{filename => "test/examples/deprecated_function_calls.erl", |
| 125 | + line => 17, |
| 126 | + source => {deprecated_function_calls,internal,0}}, |
| 127 | + #{filename => "test/examples/deprecated_functions.erl", |
| 128 | + line => 8, |
| 129 | + source => {deprecated_functions,deprecated,0}}, |
| 130 | + #{filename => "test/examples/deprecated_functions.erl", |
| 131 | + line => 10, |
| 132 | + source => {deprecated_functions,deprecated,1}}, |
| 133 | + #{filename => "test/examples/ignore_xref.erl", |
| 134 | + line => 19, |
| 135 | + source => {ignore_xref,internal,0}}] |
| 136 | +``` |
| 137 | + |
| 138 | +```erlang |
| 139 | +2015-02-09 15:57:42.499 |
| 140 | +> xref_runner:check(deprecated_function_calls, #{dirs => ["test"]}). |
| 141 | +[#{filename => "test/examples/deprecated_function_calls.erl", |
| 142 | + line => 7, |
| 143 | + source => {deprecated_function_calls,bad,0}, |
| 144 | + target => {deprecated_functions,deprecated,0}}, |
| 145 | + #{filename => "test/examples/deprecated_function_calls.erl", |
| 146 | + line => 10, |
| 147 | + source => {deprecated_function_calls,bad,1}, |
| 148 | + target => {deprecated_function_calls,internal,0}}, |
| 149 | + #{filename => "test/examples/deprecated_function_calls.erl", |
| 150 | + line => 10, |
| 151 | + source => {deprecated_function_calls,bad,1}, |
| 152 | + target => {deprecated_functions,deprecated,1}}, |
| 153 | + … |
| 154 | +] |
| 155 | +``` |
0 commit comments