Add documentation for every rule inside the source

This commit is contained in:
Jeroen Engels 2017-01-29 22:31:51 +01:00
parent e32f51e62f
commit a64a719cdf
14 changed files with 331 additions and 3 deletions

View File

@ -1,6 +1,7 @@
# elm-lint
An [Elm](http://elm-lang.org/) linter written in Elm. Get your code from correct to better.
You can learn about the API and the rules it provides on the [package documentation](http://package.elm-lang.org/packages/jfmengels/elm-ast).
## Try it
@ -28,7 +29,7 @@ You can read the slides for my [presentation](http://slides.com/jeroenengels/elm
- [NoUnannotatedFunction](rules/NoUnannotatedFunction.md) - Ensure every top-level function declaration has a type annotation.
- [NoUnusedVariables](rules/NoUnusedVariables.md) - Reports variables that are declared but never used.
- [NoUselessIf](rules/NoUselessIf.md) - Reports when both paths of an If expression result will lead to the same value.
- [NoUselessPatternMatching](rules/NoUselessPatternMatching.md) - Reports case expressions that can be simplified. Either when all patterns will lead to the same value, or when a patter will lead to the same value as the default pattern.
- [NoUselessPatternMatching](rules/NoUselessPatternMatching.md) - Reports case expressions that can be simplified. Either when all patterns will lead to the same value, or when a pattern will lead to the same value as the default pattern.
- [NoWarningComments](rules/NoWarningComments.md) - Detect comments containing words like `TODO`, `FIXME` and `XXX`.
- [SimplifyPiping](rules/SimplifyPiping.md) - Simplify piped functions like `List.map f >> List.map g` to `List.map (f >> g)`

View File

@ -1,5 +1,56 @@
module Lint.Rules.DefaultPatternPosition exposing (rule, PatternPosition(..))
{-|
@docs rule, PatternPosition
# Fail
rules =
[ DefaultPatternPosition.rule { position = Lint.Rules.DefaultPatternPosition.Last }
]
case value of
-- Error, this pattern should appear last
_ -> result
Foo -> bar
-- --------------------
rules =
[ DefaultPatternPosition.rule { position = Lint.Rules.DefaultPatternPosition.First }
]
case value of
Foo -> bar
-- Error, this pattern should appear first
_ -> result
# Success
rules =
[ DefaultPatternPosition.rule { position = Lint.Rules.DefaultPatternPosition.Last }
]
case value of
Foo -> bar
_ -> result
case value of
-- No default pattern
Foo -> bar
Bar -> foo
-- --------------------
rules =
[ DefaultPatternPosition.rule { position = Lint.Rules.DefaultPatternPosition.First }
]
case value of
_ -> result
Foo -> bar
-}
import Ast.Expression exposing (..)
import Lint exposing (doNothing, lint)
import Lint.Types exposing (Direction(..), Error, LintRule)
@ -11,6 +62,8 @@ type alias Context =
{}
{-| Configures whether the default pattern should appear first or last.
-}
type PatternPosition
= First
| Last
@ -21,6 +74,8 @@ type alias Configuration =
}
{-| Enforce the default pattern to always appear first or last.
-}
rule : Configuration -> String -> List Error
rule config input =
lint input (implementation config)
@ -41,8 +96,10 @@ error =
Error "DefaultPatternPosition"
{-| TODO Share this in a util file, already defined in NoUselessPatternMatching
-}
{- TODO Share isVariable this in a util file, already defined in NoUselessPatternMatching -}
isVariable : String -> Bool
isVariable =
Regex.contains (Regex.regex "^[_a-z][\\w\\d]*$")

View File

@ -1,5 +1,19 @@
module Lint.Rules.NoConstantCondition exposing (rule)
{-|
@docs rule
# Fail
if True then a else b
if False then a else b
if foo == foo then a else b
# Success
if foo == bar then a else b
-}
import Ast.Expression exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -10,6 +24,12 @@ type alias Context =
{}
{-| Forbid the use of expressions in an If condition whose value are always the same.
rules =
[ NoConstantCondition.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,24 @@
module Lint.Rules.NoDebug exposing (rule)
{-|
@docs rule
# Fail
if Debug.log "condition" condition then a else b
if condition then
Debug.crash "Nooo!"
else
value
# Success
if condition then
a
else
b
-}
import Ast.Expression exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -9,6 +28,12 @@ type alias Context =
{}
{-| Forbid the use of `Debug` before it goes into production.
rules =
[ NoDebug.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,18 @@
module Lint.Rules.NoDuplicateImports exposing (rule)
{-|
@docs rule
# Fail
import Set
import Set exposing (Set)
# Success
import Set exposing (Set)
-}
import Ast.Statement exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -12,6 +25,12 @@ type alias Context =
}
{-| Forbid importing the same module several times in a file.
rules =
[ NoDuplicateImports.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,17 @@
module Lint.Rules.NoExposingEverything exposing (rule)
{-|
@docs rule
# Fail
module Main exposing (..)
# Success
module Main exposing (a, b, C)
-}
import Ast.Statement exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -9,6 +21,12 @@ type alias Context =
{}
{-| Forbid exporting everything in your modules `module Main exposing (..)`, to make your module explicit in what it exposes.
rules =
[ NoExposingEverything.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,17 @@
module Lint.Rules.NoImportingEverything exposing (rule)
{-|
@docs rule
# Fail
import Html exposing (..)
# Success
import Html exposing (div, p, textarea)
-}
import Ast.Statement exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -9,6 +21,13 @@ type alias Context =
{}
{-| Forbid importing everything from your module. This can especially be confusing to newcomers when the exposed
functions and types are unknown to them.
rules =
[ NoImportingEverything.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,23 @@
module Lint.Rules.NoNestedLet exposing (rule)
{-|
@docs rule
# Fail
a = let b = 1
in let c = 2
in b + c
# Success
a = let
b = 1
c = 2
in
b + c
-}
import Ast.Expression exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -9,6 +27,12 @@ type alias Context =
{}
{-| Forbid nesting let expressions directly.
rules =
[ NoNestedLet.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,20 @@
module Lint.Rules.NoUnannotatedFunction exposing (rule)
{-|
@docs rule
# Fail
a n =
n + 1
# Success
a : Int -> Int
a n =
n + 1
-}
import Ast.Statement exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -11,6 +26,12 @@ type alias Context =
}
{-| Ensure every top-level function declaration has a type annotation.
rules =
[ NoUnannotatedFunction.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,22 @@
module Lint.Rules.NoUnusedVariables exposing (rule)
{-|
@docs rule
# Fail
module Main exposing (a)
a n =
n + 1
b = a 2
# Success
module Main exposing (a)
a n =
n + 1
-}
import Ast.Expression exposing (..)
import Ast.Statement exposing (..)
import Lint exposing (lint, doNothing)
@ -24,6 +41,12 @@ emptyScope =
Scope Set.empty Set.empty
{-| Reports variables that are declared but never used.
rules =
[ NoUnusedVariables.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,23 @@
module Lint.Rules.NoUselessIf exposing (rule)
{-|
@docs rule
# Fail
if condition then
value
else
value
# Success
if condition then
value1
else
value2
-}
import Ast.Expression exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -9,6 +27,12 @@ type alias Context =
{}
{-| Reports when both paths of an If expression result will lead to the same value.
rules =
[ NoUselessIf.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,34 @@
module Lint.Rules.NoUselessPatternMatching exposing (rule)
{-|
@docs rule
# Fail
-- Useless pattern matching
case value of
Foo -> 1
Bar -> 1
_ -> 1
-- Useless pattern `Bar`, it's the same as the default pattern
case value of
Foo -> 2
Bar -> 1
_ -> 1
# Success
case value of
Foo -> 1
Bar -> 2
_ -> 3
case value of
Foo n -> n
Bar n -> n
-}
import Ast.Expression exposing (..)
import Lint exposing (lint, visitExpression, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -11,6 +40,13 @@ type alias Context =
{}
{-| Reports case expressions that can be simplified. Either when all patterns will lead to the same value, or when a
pattern will lead to the same value as the default pattern.
rules =
[ NoUselessPatternMatching.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,19 @@
module Lint.Rules.NoWarningComments exposing (rule)
{-|
@docs rule
# Fail
-- TODO Refactor this part of the code
-- FIXME Broken because of...
-- XXX This should not be done like this
# Success
-- Regular comment
-}
import Ast.Statement exposing (..)
import Lint exposing (doNothing, lint)
import Lint.Types exposing (Direction(..), Error, LintRule)
@ -10,6 +24,12 @@ type alias Context =
{}
{-| Detect comments containing words like `TODO`, `FIXME` and `XXX`.
rules =
[ NoWarningComments.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation

View File

@ -1,5 +1,20 @@
module Lint.Rules.SimplifyPiping exposing (rule)
{-|
@docs rule
# Fail
a = values
|> List.map foo
|> List.map bar
# Success
a = values
|> List.map (foo >> bar)
-}
import Ast.Expression exposing (..)
import Lint exposing (lint, doNothing)
import Lint.Types exposing (LintRule, Error, Direction(..))
@ -10,6 +25,12 @@ type alias Context =
{}
{-| Simplify piped functions like `List.map f >> List.map g` to `List.map (f >> g)`
rules =
[ SimplifyPiping.rule
]
-}
rule : String -> List Error
rule input =
lint input implementation