elm-review*
An Elm linter with custom rules
Jeroen Engels (Yeuroune)
Elm Paris
2019
*probable new name.
You'll see "elm-lint" in some slides
Situation
We have a great Elm application.
It's working well and it never crashes.
But we have trouble having a consistent color palette.
viewUserName : String -> Html msg
viewUserName userName =
span
[ Attr.css [ Css.color (Css.hex "#222") ] ]
[ text userName ]
viewAge : Int -> Html msg
viewAge age =
span
[ Attr.css [ Css.color (Css.hex "#333") ] ]
[ text (String.from Int age) ]
import Ui.Color as Color
viewUserName : String -> Html msg
viewUserName userName =
span
[ Attr.css [ Css.color Color.darkGrey ] ]
[ text userName ]
viewAge : Int -> Html msg
viewAge age =
span
[ Attr.css [ Css.color Color.darkGrey ] ]
[ text (String.from Int age) ]
module Ui.Color exposing (darkGrey, andOtherColors)
import Css
darkGrey : Color
darkGrey =
Css.hex "#222"
"We now have a single module for
all of our colors, and we removed superfluous colors.
Because of that, we are sure to have consistent colors everywhere."
New pull request comes in
view : Model -> Html Msg
view model =
div []
[ ...
, Button.button UserAddedItem "Add"
|> Button.withColor (Css.hex "00FF00")
|> Button.toHtml
]
Communication problem
How do we prevent this from happening?
Static code analysis
If you can detect the problem just by reading the code, static code analysis can help.
Rule of thumb
elm-review*
*Name pending your feedback
elm-review : List Rule -> YourProject -> List Error
Configuration
-- LintConfig.elm
module LintConfig exposing (config)
import Lint.Rule exposing (Rule)
import NoDefiningColorsOutsideOfUiColor
config : List Rule
config =
[ NoDefiningColorsOutsideOfUiColor.rule
]
cd <your-project>
# Creates lint/elm.json and lint/LintConfig.elm
elm-lint init
This rule is specific to your team
rule : Rule
rule =
Rule.newSchema "NoDefiningColorsOutsideOfUiColor"
|> Rule.withSimpleExpressionVisitor expressionVisitor
|> Rule.fromSchema
expressionVisitor : Node Expression -> List Error
expressionVisitor node =
case Node.value node of
-- "Application" means function call
Expression.Application (function :: arguments) ->
case Node.value function of
-- "FunctionOrValue" means a variable
Expression.FunctionOrValue [ "Css" ] "hex" ->
[ Rule.error
{ message = "Do not define colors outside of Ui.Color"
, details =
[ "At fruits.com, we try to have all the colors in our application defined in the Ui.Color file. This helps us to have a consistent color palette across the application."
, "You should define this color in the Ui.Color module, and import it to use it at this location. Do check whether the color does not already exist though."
]
}
(Node.range node)
]
_ ->
[]
_ ->
[]
You can now have guarantees that you didn't have before
Handles (part of) the communication with your team
No built-in rules (See why)
-
Custom rules
-
Rules from the Elm package registry
cd <your-project>/lint/
elm install @jfmengels/lint-unused
elm install @jfmengels/lint-debug
Thank you!
Elm package: https://package.elm-lang.org/packages/jfmengels/elm-lint/latest/
NPM: npm install @jfmengels/elm-lint
Live demo: https://elm-lint.now.sh
elm-review (Paris Meetup 2019)
By Jeroen Engels
elm-review (Paris Meetup 2019)
- 578