Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/inaka/elvis_core
The core of an Erlang linter
https://github.com/inaka/elvis_core
elvis elvis-core erlang hacktoberfest linter style-checker
Last synced: 5 days ago
JSON representation
The core of an Erlang linter
- Host: GitHub
- URL: https://github.com/inaka/elvis_core
- Owner: inaka
- License: other
- Created: 2015-11-23T14:25:40.000Z (about 9 years ago)
- Default Branch: main
- Last Pushed: 2024-11-29T12:34:38.000Z (26 days ago)
- Last Synced: 2024-12-13T20:06:44.954Z (12 days ago)
- Topics: elvis, elvis-core, erlang, hacktoberfest, linter, style-checker
- Language: Erlang
- Homepage:
- Size: 1.09 MB
- Stars: 61
- Watchers: 39
- Forks: 56
- Open Issues: 37
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# elvis_core
[![GitHub Actions CI](https://github.com/inaka/elvis_core/workflows/build/badge.svg)](https://github.com/inaka/elvis_core)
[![Erlang Support](https://img.shields.io/badge/Erlang/OTP-24+-blue)](https://www.erlang.org)`elvis_core` is the core library for the [`elvis`](https://github.com/inaka/elvis) Erlang style
reviewer. It is also used by [`rebar3_lint`](https://github.com/project-fifo/rebar3_lint) for easier
integration into your Erlang libraries or applications.It includes the mechanisms to apply rules to your Erlang code, as well as their implementation.
It implements [pre-defined rules](#pre-defined-rules), but also supports
[user-defined ones](#user-defined-rules).## Usage
### As a library
The [`elvis`](https://github.com/inaka/elvis) command-line tool uses `elvis_core` extensively, so
do check that project for a concrete example on how you could use it for your own purposes.### As a `rebar3` plugin
The [`rebar3_lint`](https://github.com/project-fifo/rebar3_lint) plugin eases integration of the
style reviewer into your application or library. Be sure to check that out for further information.### From the Erlang shell
After adding `elvis_core` as a dependency to your project and starting a shell, you will need to
make sure the application is started:```shell
1> {ok, _} = application:ensure_all_started(elvis_core).
{ok,[zipper,katana_code,elvis_core]}
2>
```Once this is done you can apply the style rules in the following ways.
#### Loading configuration from a file
```shell
1> ElvisConfig = elvis_config:from_file("elvis.config").2> elvis_core:rock(ElvisConfig).
# src/elvis_core.erl [OK]
# src/elvis_result.erl [OK]
# src/elvis_style.erl [OK]
# src/elvis_utils.erl [OK]
ok
3>
```This will load the [configuration](#configuration), specified in file `elvis.config`, from the
current directory. If no configuration is found `{invalid_config, _}` is thrown.#### Providing configuration as a value
Another option for using `elvis_core` from the shell is to explicitly provide the configuration as
an argument to `elvis_core:rock/1`:```shell
1> ElvisConfig = [#{dirs => ["src"], filter => "*.erl", rules => []}].
[#{dirs => ["src"],filter => "*.erl",rules => []}]
2> elvis_core:rock(ElvisConfig).
Loading src/elvis_core.erl
# src/elvis_core.erl [OK]
Loading src/elvis_result.erl
# src/elvis_result.erl [OK]
Loading src/elvis_style.erl
# src/elvis_style.erl [OK]
Loading src/elvis_utils.erl
# src/elvis_utils.erl [OK]
ok
3>
```#### Output for failing rules
We have only presented results where all files were well-behaved (i.e. they respect all the rules),
so here's an example of how the output looks when files break some of the rules:```shell
# ../../test/examples/fail_line_length.erl [FAIL]
- line_length
- Line 14 is too long: " io:format(\"This line is 81 characters long and should be detected, yeah!!!\").".
- Line 20 is too long: " io:format(\"This line is 90 characters long and should be detected!!!!!!!!!!!!!!!!!!\").".
# ../../test/examples/fail_no_tabs.erl [FAIL]
- no_tabs
- Line 6 has a tab at column 0.
- Line 15 has a tab at column 0.
# ../../test/examples/small.erl [OK]
```## Configuration
An `elvis.config` file looks something like this:
```erlang
[{elvis, [
{config, [
#{ dirs => ["src"]
, filter => "*.erl"
, ruleset => erl_files }
, #{ dirs => ["include"]
, filter => "*.hrl"
, ruleset => hrl_files }
, #{ dirs => ["."]
, filter => "rebar.config"
, ruleset => rebar_config }
, #{ dirs => ["."]
, filter => "elvis.config"
, ruleset => elvis_config }
]}
% output_format (optional): how to format the output.
% Possible values are 'plain', 'colors' or 'parsable' (default='colors').
, {output_format, colors}
% verbose (optional): when 'true' more information will
% be printed (default=false).
, {verbose, true}
% no_output (optional): when 'true' nothing will be printed
% (default=false).
, {no_output, false}
% parallel: determine how many files will be
% analyzed in parallel (default=1).
, {parallel, 1}
]}].
```### Files, rules and rulesets
The `dirs` key is a list that tells `elvis_core` where it should look for the files that match
`filter`, which will be run through each of the pre-defined rules in the specified `ruleset`.
`filter` can contain `**` for further matching (it uses
[`filelib:wildcard/1`](https://erlang.org/doc/man/filelib.html#wildcard-1) under the hood).If you want to override the [pre-defined rules](#pre-defined-rules), for a given ruleset, you need
to specify them in a `rules` key which is a list of items with the following structure
`{Module, Function, RuleConfig}`, or `{Module, Function}` - if the rule takes no configuration
values. You can also `disable` certain rules if you want to, by specifying them in the `rules` key
and passing `disable` as a third parameter.#### Disabling Rules
**IMPORTANT**: `disable` will only work if you also provided a `ruleset` as shown above.
Let's say you like your files to have a maximum of 90 characters per line and you also like to use
tabs instead of spaces. In that case, you need to override `erl_files`'s `ruleset` pre-defined
`rules` as follows:```erlang
#{ dirs => ["src"]
, filter => "*.erl"
, rules => [
{elvis_text_style, line_length, #{ limit => 90 }} % change line_length from 100 to 90
, {elvis_text_style, no_tabs, disable} % disable no_tabs
]
, ruleset => erl_files
}.
```#### Ignoring modules
You can also `ignore` modules at a _check level_ or at a _ruleset (group of checks) level_:
- at a _check level_, you set the `ignore` option in the rule you want to ignore, e.g.:
```erlang
{elvis_style, no_debug_call, #{ ignore => [elvis, elvis_utils] }}
```(we are telling `elvis` to **ignore** the `elvis` and `elvis_utils` modules when executing
the `no_debug_call` check.- at a _ruleset (group of checks) level_, you set the `ignore` option for the group you want to
ignore, e.g.:```erlang
#{ dirs => ["src"]
, filter => "*.erl"
, ruleset => erl_files
, ignore => [module1, module4]
}.
```With this configuration, none of the checks for `erl_files` is applied to `module1` or `module4`.
### Formatting
Option `output_format` allows you to configure the output format. Possible values are `colors`,
`plain` and `parsable`. The latter could be used for automated parsing and has a format very close
to the one presented by `dialyzer`, like `:::`:```shell
src/example.erl:1:god_modules:This module has too many functions (56). Consider breaking it into a number of modules.
src/example_a.erl:341:no_debug_call:Remove the debug call to io:format/2 on line 341.
src/example_a.erl:511:used_ignored_variable:Ignored variable is being used on line 511 and column 54.
src/example_a.erl:1252:used_ignored_variable:Ignored variable is being used on line 1252 and column 21.
```The default value for the `output_format` option is `colors`.
### Verbosity
It is possible to tell `elvis_core` to produce a more verbose output, using the `verbose` option.
The value provided is a boolean, either `true` or `false`.The default value for the `verbose` option is `false`.
On the other hand, if no output is desired then the value for the `no_output` option should be
`true`.The default value for the `no_output` option is `false`.
### Parallel execution
In order to speed up the analysis process, you can use the `parallel` option.
Its value indicates how many processes to use at the same time to apply the style rules to all the
files gathered. The provided number should be less than or equal to the available cores, since any
value higher than that won't report any speedup benefits.The default value for `parallel` is `1`.
## Configuration examples
You can find examples for configuration files in this project's
[`config`](https://github.com/inaka/elvis_core/tree/HEAD/config) directory.## Application environment
Options `output_format`, `verbose`, `no_output`, and `parallel` can also be set as application-level
environment variables, i.e. as they would be found by `application:get_env/2,3`.## Rules
### Pre-defined rules
A reference to all pre-defined rules (and some other information) implemented in `elvis_core` can be
found in this repository's [RULES.md](https://github.com/inaka/elvis_core/blob/main/RULES.md).### User-defined rules
The implementation of a new rule is a function that takes 3 arguments in the following order:
1. `t:elvis_config:config()`: the value of option `config` as found in the
[configuration](#configuration),
1. `t:elvis_file:file()`: the file to be analyzed,
1. `t:erlang:map()`: a configuration map specific to your user-defined rule.This means you can define rules of your own (user-defined rules) as long as the functions that
implement them respect this interface.## Contributing and reporting bugs
If you find any **bugs** or have other **problems** using this library,
[open an issue](https://github.com/inaka/elvis/issues/new) in this repository (or even a pull
request 😃).## References
Inspired by [HoundCI](https://houndci.com/).