• Stars
    star
    255
  • Rank 159,729 (Top 4 %)
  • Language
    Elm
  • License
    Other
  • Created about 5 years ago
  • Updated 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Analyzes Elm projects, to help find mistakes before your users find them.

elm-review

elm-review analyzes Elm projects, to help find mistakes before your users find them.

elm-review reporter output

What does elm-review do?

elm-review analyzes your source code, trying to recognize code that is known to cause problems. All the rules describing problematic code are written in Elm, and elm-review does not come with built-in rules; instead users are encouraged to write rules themselves and publish them as Elm packages, for everyone to benefit. Search the package registry to find what's out there!

Encouraging users to write rules also makes it easy to add custom rules that only apply to your project. Such as rules that:

  • enforce that e.g. image paths only live in an Images module, which other modules can reference.
  • make everyone use a common Button component, instead of creating their own.
  • help users of a library you made, to avoid making mistakes that your API could not prevent them from doing.

Beware how and why you introduce rules in your project though. Often a good API, that guides users to correct solutions, is the best way to go, so instead of writing a rule, maybe there is an API that can be improved? But if a rule seems like the best solution, remember to discuss it with your team. It's easy to mix up patterns that are objectively bad, with patterns that you personally find problematic, and forbidding patterns that other people find useful can be very disruptive.

Try it out

The easiest way to run elm-review, if you have Node.js and npm installed, is to use the elm-review CLI tool.

# Save it to your package.json, if you use npm in your project.
# This is the recommended way.
npm install elm-review --save-dev

# Install globally. This is not recommended.
npm install -g elm-review

You can also try it out without installing it or configuring it if you have Node.js installed. All you need is to find a configuration on GitHub, and note that elm-review packages are encouraged to provide an example one. Once you found the configuration, run elm-review by specifying the name of the GitHub repository and the path to the configuration:

npx elm-review --template jfmengels/elm-review-unused/example

Do you want to find and remove all the dead code in your project? Then run the following command (this might take a while if your project has a lot of dead code though!), and think about whether you want this goodness in your project!

npx elm-review --template jfmengels/elm-review-unused/example --fix-all

More information on that in the CLI documentation.

Configuration

elm-review is configured through a review/ folder in your project. It is a self-contained Elm project where you can specify your dependencies, and write, import, and configure review rules.

Rules are configured in the review/src/ReviewConfig.elm file:

module ReviewConfig exposing (config)

import Review.Rule exposing (Rule)
import Third.Party.Rule
import My.Own.Custom.rule
import Another.Rule


config : List Rule
config =
    [ Third.Party.Rule.rule
    , My.Own.Custom.rule
    , Another.Rule.rule { ruleOptions = [] }
    ]

Get started

You can get started with a fresh configuration by running the elm-review init command with the command line tool installed, which will add a review folder to your project.

You can also use an existing configuration using elm-review init --template <some configuration>. I created some configurations that I believe can be good starting points.

# Start with an empty configuration
elm-review init

# Starter configuration for an Elm application
elm-review init --template jfmengels/elm-review-config/application

# Starter configuration for an Elm package
elm-review init --template jfmengels/elm-review-config/package

Once you have set up an initial configuration, you can add new rules. As elm-review does not come with built-in rules, you can look for packages with rules on the Elm package registry by searching for packages named elm-review-.

Once you've found a package that you like, you can install it with the elm install command, just like any other Elm project dependency.

cd review/ # Go inside your review configuration directory
elm install authorName/packageName
# then update your `review/src/ReviewConfig.elm` to add the rule
# as explained in the package's documentation

Before you start adding rules or an unfamiliar existing configuration, I suggest reading the rest of this document, especially the section on when to enable a rule.

Write your own rule

You can write your own rule using this package's API and elm-syntax. Check out the Review.Rule documentation for how to get started.

NOTE: If you want to create a package containing elm-review rules, I highly recommend using the CLI's elm-review new-package subcommand. This will create a new package that will help you use the best practices and give you helpful tools like easy auto-publishing. More information is available in the maintenance file generated along with it.

If you want to add/create a rule for the package or for your local configuration, then I recommend using elm-review new-rule, which will create a source and test file which you can use as a starting point. For packages, it will add the rule everywhere it should be present (exposed-modules, README, ...).

Here's an example of a rule that prevents a typo in a string that was made too often at your company.

module NoStringWithMisspelledCompanyName exposing (rule)

import Elm.Syntax.Expression as Expression exposing (Expression)
import Elm.Syntax.Node as Node exposing (Node)
import Review.Rule as Rule exposing (Error, Rule)

-- Create a new rule
rule : Rule
rule =
    -- Define the rule with the same name as the module it is defined in
    Rule.newModuleRuleSchema "NoStringWithMisspelledCompanyName" ()
        -- Make it look at expressions
        |> Rule.withSimpleExpressionVisitor expressionVisitor
        |> Rule.fromModuleRuleSchema

-- This function will visit all the expressions (like `1`, `"string"`, `foo bar`, `a + b`, ...)
-- and report problems that it finds
expressionVisitor : Node Expression -> List (Error {})
expressionVisitor node =
    case Node.value node of
        -- It will look at string literals (like "a", """a""")
        Expression.Literal str ->
            if String.contains "frits.com" str then
                -- Return a single error, describing the problem
                [ Rule.error
                    { message = "Replace `frits.com` by `fruits.com`"
                    , details = [ "This typo has been made and noticed by users too many times. Our company is `fruits.com`, not `frits.com`." ]
                    }
                    -- This is the location of the problem in the source code
                    (Node.range node)
                ]

            else
                []

        _ ->
            []

Then add the rule in your configuration:

module ReviewConfig exposing (config)

import NoStringWithMisspelledCompanyName
import Review.Rule exposing (Rule)


config : List Rule
config =
    [ NoStringWithMisspelledCompanyName.rule
    -- other rules...
    ]

If you want to write a rule but might not have an idea of where to start, have a look on the elm-review-rule-ideas repository. You may also want to look for rules in the Elm packages registry and in the GitHub elm-review topic.

When to write or enable a rule

The bar to write or enable a rule should be pretty high. A new rule can often turn out to be a nuisance to someone, sometimes in ways you didn't predict, so making sure the rule solves a real problem, and that your team is on board with it, is important. If a developer disagrees with a rule, they may try to circumvent it, resulting in code that is even more error prone than the pattern that was originally forbidden. So the value provided by the rule should be much greater than the trouble it causes, and if you find that a rule doesn't live up to this, consider disabling it.

Review rules are most useful when some pattern must never appear in the code. It gets less useful when a pattern is allowed to appear in certain cases, as there is no good solution for handling exceptions to rules. If you really need to make exceptions, they must be written in the rule itself, or the rule should be configurable.

For rules that enforce a certain coding style, or suggest simplifications to your code, I would ask you to raise the bar for inclusion even higher. A few examples:

  • I much prefer using |> over <|, and I think using the latter to pipe functions over several lines is harder to read. Even if using |> was indeed better for most situations and even if my teammates agree, this would prevent me from writing tests the suggested way for instance.
  • If a record contains only one field, then I could suggest not using a record and use the field directly, which would make things simpler. But using a record can have the advantage of being more explicit: findFiles [] folder is harder to understand than findFiles { exceptions = [] } folder.

Some rules might suggest using advanced techniques to avoid pitfalls, which can make it harder for newcomers to get something done. When enabling this kind of rule, make sure that the message it gives is helpful enough to unblock users.

When wondering whether to enable a rule, I suggest using this checklist:

  • I have had problems with the pattern I want to forbid.
  • I could not find a way to solve the problem by changing the API of the problematic code or introducing a new API.
  • If the rule exists, I have read its documentation and the section about when not to enable the rule, and it doesn't apply to my situation.
  • I have thought very hard about what the corner cases could be and what kind of patterns this would forbid that are actually okay, and they are acceptable.
  • I think the rule explains well enough how to solve the issue, to make sure beginners are not blocked by it.
  • I have communicated with my teammates and they all agree to enforce the rule.
  • I am ready to disable the rule if it turns out to be more disturbing than helpful.

Is there a way to ignore errors?

elm-review does not provide a way to disable errors on a case-by-case basis โ€” by line or sections of code โ€” like a lot of static analysis tools do. I've written about this in How disable comments make static analysis tools worse.

Because you can't ignore errors easily, elm-review puts more burden on the rules, requiring them to be of higher quality โ€” less false positives โ€” and better designed โ€” avoiding rules that will inherently have lots of exceptions or false positives.

It does provide 2 systems that I think are better alternatives for the health of your project.

Configuring exceptions

You can configure exceptions, which consists of marking specific directories or files as not relevant to a rule or set of rules, preventing errors to be reported for those.

It is a good fit if you wish for elm-review to not report errors in vendored or generated code, or in files and directories that by the nature of the rule should be exempted.

Temporarily suppressing errors

elm-review has a system to temporarily suppressed errors which aims to help you gradually adopt rules that report many errors in your project without having you fix all the issues beforehand.

Running elm-review suppress will generate one JSON file in review/suppressed/ (in your review configuration) for every rule that currently reports errors, and records the number of suppressed errors per file in your project. These files should be included in your versioning system.

As long as suppression files exist for your project, running elm-review will behave as usual but with these additional behaviors:

  • Suppressed errors won't be reported.
  • If there are outstanding errors for the ignored rules and files, the related suppressed errors will be reported until you reduce the number of errors back to the number in the JSON file. This is a good opportunity to fix more!
  • If no errors are being reported and there are less suppressed errors than before, suppression files will be updated automatically, in order to make sure no new errors get re-introduced unknowingly.

While you can run the suppress command to ignore newly reported errors, please do so with moderation. The aim is to allow enabling rules while there are errors remaining and to have these fixed incrementally, not to make it easier to ignore errors.

Use elm-review suppress --help to start using this, and read more about the design choices that went into the feature.

Note that to avoid uncommitted suppression files in your project's main branch, it is recommended to use elm-review suppress --check-after-tests at the end of your test suite.

Extract information

elm-review has quite a nice way of traversing the files of a project and collecting data, especially when things aren't as simple as grepping or applying a regex on the code.

While the tool is mainly designed around reporting issues, you can also use it to extract information from the codebase. You can use this to gain insight into your codebase, or provide information to other tools to enable powerful integrations.

To make use of this feature, run elm-review --extract --report=json with a configuration containing a rule that uses Rule.withDataExtractor.

The result for a rule will be stored under <json>.extracts.<YourRuleName>. To access it, you can then pipe the result into either a Node.js script, a tool that expects JSON, or jq as in the example below.

elm-review --extract --report=json |
    jq -r '.extracts["YourRuleName"]'

# or to be slightly faster
elm-review --extract --report=json --rules YourRuleName |
    jq -r '.extracts["YourRuleName"]'

Combine the above out with --watch for fast feedback when editing your code!

elm-review --report=json --extract

and by reading the value at <output>.extracts["YourRuleName"] in the output.

More Repositories

1

eslint-plugin-fp

ESLint rules for functional programming
JavaScript
961
star
2

eslint-plugin-lodash-fp

ESLint rules for lodash/fp
JavaScript
147
star
3

lodash-fp-docs

JavaScript
87
star
4

node-elm-review

CLI for elm-review
JavaScript
48
star
5

eslint-plugin-import-order

ESLint plugin to enforce the order of import/require statements.
JavaScript
42
star
6

lib-upgrader

CLI builder to help users upgrade library versions
JavaScript
39
star
7

lodash-codemods

Codemods to simplify upgrading Lodash versions
JavaScript
33
star
8

eslint-rule-documentation

Find the url for the documentation of an ESLint rule
JavaScript
30
star
9

elm-lint

elm-lint lints Elm source code, to add additional guarantees to your project.
Elm
27
star
10

eslint-ast-utils

Utility library to manipulate ASTs for ESLint projects
JavaScript
23
star
11

awesome-elm-sponsorship

Elm profiles to sponsor
23
star
12

elm-review-unused

Provides elm-review rules to detect unused elements in your Elm project
Elm
23
star
13

fuzzy-matching

Fuzzy string matcher
JavaScript
22
star
14

elm-review-simplify

Provides elm-review rules to simplify your Elm code
Elm
20
star
15

elm-review-common

Provides common linting rules for elm-review
Elm
14
star
16

eslint-ava-rule-tester

ESLint's RuleTester for AVA
JavaScript
13
star
17

jscodeshift-ava-tester

jscodeshift wrapper to write smaller and better tests for your codemods using AVA
JavaScript
12
star
18

rainbowtable-python

Python
11
star
19

elm-review-rule-ideas

Rule ideas for elm-review
9
star
20

mocha-vs-ava-performance

Setup to help identify performance problems for Ava
JavaScript
9
star
21

elm-review-example

Example project using elm-review
Elm
9
star
22

elm-review-config

Starter configurations for elm-review
Elm
9
star
23

elm-benchmarks

All sorts of benchmarks I made for comparing Elm code
Elm
9
star
24

review-unused

Provides elm-review rules to detect unused functions and types in your Elm files
Elm
8
star
25

create-eslint-index

JavaScript
8
star
26

elm-review-performance

Elm
8
star
27

some-elm-links

A personal mini awesome-elm
6
star
28

update-travis

Utility to update `.travis.yml` to newer Node.js versions
JavaScript
6
star
29

elm-review-documentation

Provides elm-review rules to help with the quality and correctness of your Elm project's documentation
Elm
6
star
30

elm-review-cognitive-complexity

Elm
5
star
31

elm-review-code-style

Elm
5
star
32

elm-review-debug

Provides elm-review rules to detect debug code
Elm
5
star
33

elm-review-design-discussions

Discussions around elm-review's design and evolution
5
star
34

elm-review-test-values

Provides elm-review rules to find misuses of test-only values
Elm
5
star
35

elm-review-the-elm-architecture

Provides elm-review rules to detect unused functions and types in your Elm files
Elm
4
star
36

starkana-manga-crawler

Manga downloader using starkana.com
JavaScript
4
star
37

blog

JavaScript
4
star
38

elm-review-scope

Helper for elm-review that collects data about where variables come from
Elm
3
star
39

enhance-visitors

Enhance your ESLint visitors with shared logic
JavaScript
3
star
40

elm-review-license

Provides an elm-review rule to prevent using packages with unapproved licenses
Elm
3
star
41

node-elm-lint

CLI for elm-lint, which lints Elm source code to add additional guarantees to your project.
JavaScript
3
star
42

react-boilerplate

React boilerplate, using Babel, Redux, ImmutableJS, Webpack, CSS Modules, server-side-rendering (soon) and hotloading
JavaScript
2
star
43

rainbowtable

Implementation of a rainbow table, used to crack hashed passwords, in C++.
C++
2
star
44

set-union

JavaScript
2
star
45

elm-review-noop

Unpublished rules to forbid NoOp messages and useless Cmds
Elm
2
star
46

eslint-find-plugin-rules

Discovers rules in eslint plugins.
JavaScript
2
star
47

elm-review-random-insights

Random elm-review rules to gain insight into your Elm codebase
Elm
2
star
48

elm-lint-reporter

Formats the result of elm-lint in a nice human-readable way
Elm
1
star
49

lint-debug

Provides elm-lint rules to detect debug code
Elm
1
star
50

JavaScript30

HTML
1
star
51

reddit-crawler

Reddit crawler. Based on the talk by Glen Maddern http://glenmaddern.com/articles/javascript-in-2015
JavaScript
1
star
52

review-tea

Provides elm-review rules to detect unused functions and types in your Elm files
Elm
1
star
53

review-common

Provides common linting rules for elm-review
Elm
1
star
54

review-documentation

Provides elm-review rules to help with the quality and correctness of your Elm project's documentation
Elm
1
star
55

elm-review-testing-something

JavaScript
1
star
56

impro

Rรฉgistre de jeux d'improvisation
JavaScript
1
star
57

elm-review-bad-code

elm-review rules to make Elm code worse
Elm
1
star
58

elm-review-no-ignoring-errors

Elm
1
star
59

wuxiaworld-manganese

JavaScript
1
star
60

manganese-cli

Command-line tool to download and organize manga on your computers using popular websites crawling.
JavaScript
1
star
61

inject-in-tag

Inject content into Markdown files
JavaScript
1
star
62

review-debug

Provides elm-review rules to detect debug code
Elm
1
star