Jeroen Engels
@jfmengels
Elm Radio
module MyModule exposing (Model, Msg, update, view)
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
type alias Model =
    { count : Int }
type Msg
    = Increment
    | Decrement
update : Msg -> Model -> Model
update msg model =
    case msg of
        Increment ->
            { model | count = model.count + 1 }
        Decrement ->
            { model | count = model.count - 1 }
view : Model -> Html Msg
view model =
    div []
        [ button [ onClick Increment ] [ text "+1" ]
        , div [] [ text <| String.fromInt model.count ]
        , button [ onClick Decrement ] [ text "-1" ]
        ]-- Page/Checkout.elm
viewConfirmButton : Html msg
viewConfirmButton =
    Html.button
        [ Attr.style "height" "35px"
        , Events.onClick UserClickedOnConfirmButton
        ]
        [ Html.text "Confirm" ]-- Page/Payment.elm
viewPayButton : Html msg
viewPayButton =
    Html.button
        [ Attr.style "height" "33px"
        , Events.onClick UserClickedOnPayButton
        ]
        [ Html.text "Pay" ]
module Ui.Button exposing (confirm, cancel, andSomeOtherButtons)
  
confirm : msg -> String -> Html msg
cancel : msg -> String -> Html msg-- Page/Checkout.elm
import Ui.Button as Button
viewConfirmButton : Html msg
viewConfirmButton =
    Button.confirm UserClickedOnConfirmButton "Confirm"-- Page/Payment.elm
import Ui.Button as Button
viewPayButton : Html msg
viewPayButton =
    Button.confirm UserClickedOnPayButton "Pay"view : Model -> Html Msg
view model =
    Html.button
        [ Attr.style "height" "34px"
        , Events.onClick UserClickedOnRemoveButton
        ]
        [ Html.text "Remove" ]view : Model -> Html Msg
view model =
    Html.button
        [ Attr.style "height" "34px"
        , Events.onClick UserClickedOnRemoveButton
        ]
        [ Html.text "Remove" ](a + b) / 2Integer 2OperatorApplication
   operator +FunctionOrValue aOperatorApplication
   operator /FunctionOrValue bParenthesizedExpressionrule : Rule
rule =
    Rule.newSchema "NoUsingHtmlButton" ()
        |> Rule.withExpressionVisitor expressionVisitor
        |> Rule.fromSchema
expressionVisitor : Node Expression -> Context -> ( List Error, Context )
expressionVisitor node context =
    case Node.value node of
        Expression.FunctionOrValue [ "Html" ] "button" ->
            ( [ -- Report an error
              ]
            , context
            )
        _ ->
            ( [], context )expressionVisitor : Node Expression -> Context -> ( List Error, Context )
expressionVisitor node context =
    case Node.value node of
        Expression.FunctionOrValue [ "Html" ] "button" ->
            ( [ Rule.error
                    "Do not use Html.button"
                    (Node.range node)
              ]
            , context
            )
        _ ->
            ( [], context )Rule name
Source
code extract
Message
File path
expressionVisitor : Node Expression -> Context -> ( List Error, Context )
expressionVisitor node context =
    case Node.value node of
        Expression.FunctionOrValue [ "Html" ] "button" ->
            ( [ Rule.error
                    "Use Ui.Button instead of the native Html.button"
                    (Node.range node)
              ]
            , context
            )
        _ ->
            ( [], context )expressionVisitor : Node Expression -> Context -> ( List Error, Context )
expressionVisitor node context =
    case Node.value node of
        Expression.FunctionOrValue [ "Html" ] "button" ->
            ( [ Rule.error
            	  { message = "Use Ui.Button instead of the native Html.button"
                  , details =
                    [ "At fruits.com, we try to have a consistent UI across the application, and one of the ways we do that is by having a single nice module to create buttons, named Ui.Button."
                    , "Here, you defined a button using `Html.button` or `Html.Styled.Button`, which is likely not to have the consistent UI we aim for or some of the guarantees we created around our buttons."
                    , "Instead, you should use the Ui.Button module. I suggest reading the documentation in that module, but here is what it would kind of look like: ..."
                    ]
                  }
                  (Node.range node)
              ]
            , context
            )
        _ ->
            ( [], context )Context
Problem
Suggestion
Example
Rule name
Source
code extract
Message
File path
view : Model -> Html Msg
view model =
    -- elm-review-disable-next-line
    Html.button
        [ Attr.style "height" "34px"
        , Events.onClick UserClickedOnRemoveButton
        ]
        [ Html.text "Remove" ]type alias Context =
  { isUiButtonModule : Bool }
rule : Rule
rule =
    Rule.newSchema "NoUnusedDeclarations" { isUiButtonModule = False }
    	-- visitors...
        |> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
        |> Rule.fromSchema
moduleDefinitionVisitor : Node Module -> Context -> ( List Error, Context )
moduleDefinitionVisitor (Node _ { moduleName }) context =
    ( [], { isUiButtonModule = (moduleName == "Ui.Button") } )module Ui.Button exposing (confirm, cancel, andSomeOtherButtons)expressionVisitor : Node Expression -> Context -> ( List Error, Context )
expressionVisitor node context =
    case Node.value node of
        Expression.FunctionOrValue [ "Html" ] "button" ->
            if not context.isUiButtonModule then
                ( [ Rule.error {- ... -} ]
                , context
                )
            else
                ( [], context )
        _ ->
            ( [], context )module A exposing (used, neverUsed)
used =
    "some thing"
neverUsed =
    "other thing"module B exposing (thing)
import A
thing =
    A.used ++ " is exposed"No dynamic function calls
Functions always return the same type
No side-effects
No mutations
No macros
...
No memory management
No race conditions
...
config : List Rule
config =
    [ NoUnused.Variables.rule
    , NoDebug.Log.rule
    ]
        |> Rule.ignoreErrorsForDirectories [ "src-generated/", "src-vendor/" ]{-| Does something.
@deprecated Use someBetterFunction which does it better.
-}
someFunction input =
    -- do something with inputconfig : List Rule
config =
    [ NoDeprecated.rule
        |> Rule.ignoreErrorsForFiles
            [ "src/Api.elm"
            , -- ...and other files
            ]
    ]{
  "version": 1,
  "automatically created by": "elm-review suppress",
  "learn more": "elm-review suppress --help",
  "suppressions": [
    { "count": 7, "filePath": "src/Api.elm" }
  ]
}
review/suppressed/NoDeprecated.json
Jeroen Engels
@jfmengels
Elm Radio