2020-04-03 16:13:37 +03:00
|
|
|
module NoDebug.Log exposing (rule)
|
2020-03-07 01:03:37 +03:00
|
|
|
|
2020-04-05 10:47:59 +03:00
|
|
|
{-|
|
2020-03-07 01:03:37 +03:00
|
|
|
|
|
|
|
@docs rule
|
|
|
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
import Elm.Syntax.Exposing as Exposing
|
|
|
|
import Elm.Syntax.Expression as Expression exposing (Expression)
|
|
|
|
import Elm.Syntax.Import exposing (Import)
|
|
|
|
import Elm.Syntax.Node as Node exposing (Node)
|
|
|
|
import Review.Rule as Rule exposing (Error, Rule)
|
|
|
|
|
|
|
|
|
|
|
|
{-| Forbid the use of [`Debug.log`](https://package.elm-lang.org/packages/elm/core/latest/Debug) before it goes into production or fails in the CI.
|
|
|
|
|
2020-04-03 16:13:37 +03:00
|
|
|
`Debug.log` is useful to debug your code, but should not be pushed to production.
|
|
|
|
|
2020-03-07 01:03:37 +03:00
|
|
|
config =
|
2020-04-03 16:13:37 +03:00
|
|
|
[ NoDebug.Log.rule
|
2020-03-07 01:03:37 +03:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
## Fail
|
|
|
|
|
|
|
|
if Debug.log "condition" condition then
|
|
|
|
a
|
|
|
|
|
|
|
|
else
|
|
|
|
b
|
|
|
|
|
|
|
|
|
|
|
|
## Success
|
|
|
|
|
|
|
|
if condition then
|
|
|
|
a
|
|
|
|
|
|
|
|
else
|
|
|
|
b
|
|
|
|
|
|
|
|
|
|
|
|
# When (not) to use this rule
|
|
|
|
|
|
|
|
You should use this rule if you're developing a package meant to be published,
|
|
|
|
or an application that is put into production, and wish to know about the use of
|
|
|
|
[`Debug.log`](https://package.elm-lang.org/packages/elm/core/latest/Debug#log)
|
|
|
|
module before committing your changes.
|
|
|
|
|
|
|
|
You should not use this rule if you are developing an application that is not
|
|
|
|
put into production, and you do not care about having stray debug logs, and you
|
|
|
|
do not ship to production.
|
|
|
|
|
2020-08-09 19:55:15 +03:00
|
|
|
|
|
|
|
## Try it out
|
|
|
|
|
|
|
|
You can try this rule out by running the following command:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
elm-review --template jfmengels/review-debug/example --rules NoDebug.Log
|
|
|
|
```
|
|
|
|
|
2020-03-07 01:03:37 +03:00
|
|
|
-}
|
|
|
|
rule : Rule
|
|
|
|
rule =
|
2020-08-09 19:55:15 +03:00
|
|
|
Rule.newModuleRuleSchema "NoDebug.Log" { hasLogBeenImported = False }
|
2020-06-28 08:49:27 +03:00
|
|
|
|> Rule.withImportVisitor importVisitor
|
|
|
|
|> Rule.withExpressionVisitor expressionVisitor
|
|
|
|
|> Rule.fromModuleRuleSchema
|
2020-03-07 01:03:37 +03:00
|
|
|
|
|
|
|
|
|
|
|
type alias Context =
|
|
|
|
{ hasLogBeenImported : Bool
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-25 20:02:37 +03:00
|
|
|
error : Node a -> Error {}
|
2020-03-07 01:03:37 +03:00
|
|
|
error node =
|
|
|
|
Rule.error
|
|
|
|
{ message = "Remove the use of `Debug.log` before shipping to production"
|
|
|
|
, details =
|
|
|
|
[ "`Debug.log` is useful when developing, but is not meant to be shipped to production or published in a package. I suggest removing its use before committing and attempting to push to production."
|
|
|
|
]
|
|
|
|
}
|
|
|
|
(Node.range node)
|
|
|
|
|
|
|
|
|
|
|
|
importVisitor : Node Import -> Context -> ( List nothing, Context )
|
|
|
|
importVisitor node context =
|
|
|
|
let
|
|
|
|
moduleName : List String
|
|
|
|
moduleName =
|
|
|
|
node
|
|
|
|
|> Node.value
|
|
|
|
|> .moduleName
|
|
|
|
|> Node.value
|
|
|
|
in
|
|
|
|
if moduleName == [ "Debug" ] then
|
|
|
|
case node |> Node.value |> .exposingList |> Maybe.map Node.value of
|
|
|
|
Just (Exposing.All _) ->
|
|
|
|
( [], { hasLogBeenImported = True } )
|
|
|
|
|
|
|
|
Just (Exposing.Explicit importedNames) ->
|
|
|
|
( [], { hasLogBeenImported = List.any isLog importedNames } )
|
|
|
|
|
|
|
|
Nothing ->
|
|
|
|
( [], context )
|
|
|
|
|
|
|
|
else
|
|
|
|
( [], context )
|
|
|
|
|
|
|
|
|
|
|
|
isLog : Node Exposing.TopLevelExpose -> Bool
|
|
|
|
isLog node =
|
|
|
|
case Node.value node of
|
|
|
|
Exposing.FunctionExpose "log" ->
|
|
|
|
True
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
False
|
|
|
|
|
|
|
|
|
2020-03-25 20:02:37 +03:00
|
|
|
expressionVisitor : Node Expression -> Rule.Direction -> Context -> ( List (Error {}), Context )
|
2020-03-07 01:03:37 +03:00
|
|
|
expressionVisitor node direction context =
|
|
|
|
case ( direction, Node.value node ) of
|
|
|
|
( Rule.OnEnter, Expression.FunctionOrValue [ "Debug" ] "log" ) ->
|
|
|
|
( [ error node ], context )
|
|
|
|
|
|
|
|
( Rule.OnEnter, Expression.FunctionOrValue [] "log" ) ->
|
|
|
|
if context.hasLogBeenImported then
|
|
|
|
( [ error node ], context )
|
|
|
|
|
|
|
|
else
|
|
|
|
( [], context )
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
( [], context )
|