diff --git a/README.md b/README.md index 3a67ebff..5b72529c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ You can read the slides for my [presentation](http://slides.com/jeroenengels/elm - [NoDebug](rules/NoDebug.md) - Forbid the use of `Debug` before it goes into production. - [NoDuplicateImports](rules/NoDuplicateImports.md) - Forbid importing the same module several times in a file. - [NoExposingEverything](rules/NoExposingEverything.md) - Forbid exporting everything in your modules `module Main exposing (..)`, to make your module explicit in what it exposes. +- [NoImportingEverything](rules/NoImportingEverything.md) - Forbid importing everything from your module. This can especially be confusing to newcomers when the exposed functions and types are unknown to them. +- [NoNestedLet](rules/NoNestedLet.md) - Forbid nesting let expressions directly. - [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. diff --git a/example/Main.elm b/example/Main.elm index 0ad3c1af..debbe308 100644 --- a/example/Main.elm +++ b/example/Main.elm @@ -20,6 +20,7 @@ import NoDebug import NoDuplicateImports import NoExposingEverything import NoImportingEverything +import NoNestedLet import NoUnannotatedFunction import NoUnusedVariables import NoUselessIf @@ -40,6 +41,7 @@ rules = , NoDuplicateImports.rule , NoExposingEverything.rule , NoImportingEverything.rule + , NoNestedLet.rule , NoUnannotatedFunction.rule , NoUnusedVariables.rule , NoUselessIf.rule diff --git a/rules/NoNestedLet.elm b/rules/NoNestedLet.elm new file mode 100644 index 00000000..71999622 --- /dev/null +++ b/rules/NoNestedLet.elm @@ -0,0 +1,39 @@ +module NoNestedLet exposing (rule) + +import Lint exposing (lint, doNothing) +import Types exposing (LintRule, Error, Direction(..)) +import Ast.Expression exposing (..) + + +type alias Context = + {} + + +rule : String -> List Error +rule input = + lint input implementation + + +implementation : LintRule Context +implementation = + { statementFn = doNothing + , typeFn = doNothing + , expressionFn = expressionFn + , moduleEndFn = (\ctx -> ( [], ctx )) + , initialContext = Context + } + + +error : Error +error = + Error "NoNestedLet" "Do not nest Let expressions directly" + + +expressionFn : Context -> Direction Expression -> ( List Error, Context ) +expressionFn ctx node = + case node of + Enter (Let declarations (Let _ _)) -> + ( [ error ], ctx ) + + _ -> + ( [], ctx ) diff --git a/tests/Main.elm b/tests/Main.elm index b4b3813e..c7fac62f 100644 --- a/tests/Main.elm +++ b/tests/Main.elm @@ -8,6 +8,7 @@ import NoConstantConditionTest import NoDebugTest import NoDuplicateImportsTest import NoImportingEverythingTest +import NoNestedLetTest import NoUnannotatedFunctionTest import NoUnusedVariablesTest import NoUselessIfTest @@ -32,6 +33,7 @@ all = , NoDebugTest.all , NoDuplicateImportsTest.all , NoImportingEverythingTest.all + , NoNestedLetTest.all , NoUnannotatedFunctionTest.all , NoUnusedVariablesTest.all , NoUselessIfTest.all diff --git a/tests/NoNestedLetTest.elm b/tests/NoNestedLetTest.elm new file mode 100644 index 00000000..7650e86f --- /dev/null +++ b/tests/NoNestedLetTest.elm @@ -0,0 +1,46 @@ +port module NoNestedLetTest exposing (all) + +import Expect +import Test exposing (describe, test, Test) +import NoNestedLet exposing (rule) +import Types exposing (Error) + + +error : Error +error = + Error "NoNestedLet" "Do not nest Let expressions directly" + + +tests : List Test +tests = + [ test "should not report single let expression" <| + \() -> + """a = let b = 1 + in b + """ + |> rule + |> Expect.equal [] + , test "should report let expression inside the body of an other let expression" <| + \() -> + """a = let b = 1 + in let c = 2 + in c + """ + |> rule + |> Expect.equal [ error ] + , test "should not report let expression indirectly inside another " <| + \() -> + """a = let b = 1 + in if foo then + let c = 2 in c + else + 3 + """ + |> rule + |> Expect.equal [] + ] + + +all : Test +all = + describe "NoNestedLet" tests