mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-11-22 22:33:13 +03:00
Apply elm-upgrade
This commit is contained in:
parent
5c56965101
commit
48e3296fc3
@ -1,11 +1,9 @@
|
||||
{
|
||||
"version": "2.0.1",
|
||||
"type": "package",
|
||||
"name": "jfmengels/elm-lint",
|
||||
"summary": "A linter for Elm. Get your code from correct to better.",
|
||||
"repository": "https://github.com/jfmengels/elm-lint.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"version": "2.0.1",
|
||||
"exposed-modules": [
|
||||
"Lint",
|
||||
"Lint.Types",
|
||||
@ -25,12 +23,12 @@
|
||||
"Lint.Rules.SimplifyPropertyAccess",
|
||||
"Lint.Rules.ElmTest.NoDuplicateTestBodies"
|
||||
],
|
||||
"elm-version": "0.19.0 <= v < 0.20.0",
|
||||
"dependencies": {
|
||||
"Bogdanp/elm-ast": "8.0.3 <= v < 9.0.0",
|
||||
"elm-community/list-extra": "5.0.1 <= v < 6.0.0",
|
||||
"elm-community/parser-combinators": "1.1.0 <= v < 2.0.0",
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
"elm/core": "1.0.0 <= v < 2.0.0",
|
||||
"elm/html": "1.0.0 <= v < 2.0.0",
|
||||
"elm/regex": "1.0.0 <= v < 2.0.0",
|
||||
"elm-community/list-extra": "8.1.0 <= v < 9.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
"test-dependencies": {}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
module Lint.Rules.DefaultPatternPosition exposing (rule, Configuration, PatternPosition(..))
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule, Configuration, PatternPosition
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
rules =
|
||||
@ -25,6 +27,7 @@ module Lint.Rules.DefaultPatternPosition exposing (rule, Configuration, PatternP
|
||||
-- LintError, this pattern should appear first
|
||||
_ -> result
|
||||
|
||||
|
||||
# Success
|
||||
|
||||
rules =
|
||||
@ -49,11 +52,12 @@ module Lint.Rules.DefaultPatternPosition exposing (rule, Configuration, PatternP
|
||||
case value of
|
||||
_ -> result
|
||||
Foo -> bar
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (LintRule, Direction(..), LintError, LintRuleImplementation)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import List.Extra exposing (findIndex)
|
||||
import Regex
|
||||
|
||||
@ -88,7 +92,7 @@ implementation configuration =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn configuration
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -113,6 +117,7 @@ isDefaultPattern pattern =
|
||||
Variable names ->
|
||||
if isVariable (String.join "." names) then
|
||||
True
|
||||
|
||||
else
|
||||
False
|
||||
|
||||
@ -138,12 +143,14 @@ expressionFn config ctx node =
|
||||
First ->
|
||||
if index /= 0 then
|
||||
( [ error "Expected default pattern to appear first in the list of patterns" ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
Last ->
|
||||
if index /= (List.length patterns) - 1 then
|
||||
if index /= List.length patterns - 1 then
|
||||
( [ error "Expected default pattern to appear last in the list of patterns" ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
|
@ -1,44 +1,52 @@
|
||||
module Lint.Rules.ElmTest.NoDuplicateTestBodies exposing (rule)
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
module Addition exposing (..)
|
||||
|
||||
import Test exposing (test)
|
||||
|
||||
tests =
|
||||
[ test "foo" <|
|
||||
\() -> 1 + 1
|
||||
|> Expect.equal 2
|
||||
\() ->
|
||||
1
|
||||
+ 1
|
||||
|> Expect.equal 2
|
||||
, test "bar" <|
|
||||
\() -> 1 + 1
|
||||
|> Expect.equal 2
|
||||
\() ->
|
||||
1
|
||||
+ 1
|
||||
|> Expect.equal 2
|
||||
]
|
||||
|
||||
|
||||
# Success
|
||||
|
||||
module Addition exposing (..)
|
||||
|
||||
import Test exposing (test)
|
||||
|
||||
tests =
|
||||
[ test "foo" <|
|
||||
\() -> 1 + 1
|
||||
|> Expect.equal 2
|
||||
\() ->
|
||||
1
|
||||
+ 1
|
||||
|> Expect.equal 2
|
||||
, test "bar" <|
|
||||
\() -> 1 + 2
|
||||
|> Expect.equal 3
|
||||
\() ->
|
||||
1
|
||||
+ 2
|
||||
|> Expect.equal 3
|
||||
]
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
import Ast.Statement exposing (..)
|
||||
import Lint exposing (lint, doNothing)
|
||||
import Lint.Types exposing (LintRule, LintRuleImplementation, LintError, Direction(..))
|
||||
import Dict exposing (Dict)
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
|
||||
|
||||
type alias Context =
|
||||
@ -53,6 +61,7 @@ This may result in specifications that are thought to be implemented but are not
|
||||
rules =
|
||||
[ ElmTest.NoDuplicateTestBodies.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -64,7 +73,7 @@ implementation =
|
||||
{ statementFn = statementFn
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context []
|
||||
}
|
||||
|
||||
@ -97,6 +106,7 @@ filterTests availableTestAliases listItems =
|
||||
BinOp (Variable [ "<|" ]) (Application fn (String title)) testBody ->
|
||||
if isTestFunctionCall availableTestAliases fn then
|
||||
[ ( title, testBody ) ]
|
||||
|
||||
else
|
||||
[]
|
||||
|
||||
@ -124,17 +134,17 @@ expressionFn ctx node =
|
||||
existingTest =
|
||||
Dict.get testBodyAsString dict
|
||||
in
|
||||
case existingTest of
|
||||
Nothing ->
|
||||
{ dict = Dict.insert testBodyAsString title dict, redundant = redundant }
|
||||
case existingTest of
|
||||
Nothing ->
|
||||
{ dict = Dict.insert testBodyAsString title dict, redundant = redundant }
|
||||
|
||||
Just existingTestTitle ->
|
||||
{ dict = dict, redundant = redundant ++ [ ( title, existingTestTitle ) ] }
|
||||
Just existingTestTitle ->
|
||||
{ dict = dict, redundant = redundant ++ [ ( title, existingTestTitle ) ] }
|
||||
)
|
||||
{ dict = Dict.empty, redundant = [] }
|
||||
tests
|
||||
in
|
||||
( List.map error redundantTests.redundant, ctx )
|
||||
( List.map error redundantTests.redundant, ctx )
|
||||
|
||||
_ ->
|
||||
( [], ctx )
|
||||
@ -152,6 +162,7 @@ extractImported exportSet =
|
||||
FunctionExport name ->
|
||||
if name == "test" then
|
||||
[ name ]
|
||||
|
||||
else
|
||||
[]
|
||||
|
||||
@ -172,12 +183,12 @@ statementFn ctx node =
|
||||
moduleFnAccess =
|
||||
computeAlias testAlias ++ ".test"
|
||||
in
|
||||
case exportSet of
|
||||
Nothing ->
|
||||
( [], { availableTestAliases = [ moduleFnAccess ] } )
|
||||
case exportSet of
|
||||
Nothing ->
|
||||
( [], { availableTestAliases = [ moduleFnAccess ] } )
|
||||
|
||||
Just subExportSet ->
|
||||
( [], { availableTestAliases = [ moduleFnAccess ] ++ extractImported subExportSet } )
|
||||
Just subExportSet ->
|
||||
( [], { availableTestAliases = [ moduleFnAccess ] ++ extractImported subExportSet } )
|
||||
|
||||
_ ->
|
||||
( [], ctx )
|
||||
|
@ -1,22 +1,44 @@
|
||||
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
|
||||
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
|
||||
if foo == bar then
|
||||
a
|
||||
|
||||
else
|
||||
b
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
import Lint exposing (lint, doNothing)
|
||||
import Lint.Types exposing (LintRule, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
@ -29,6 +51,7 @@ type alias Context =
|
||||
rules =
|
||||
[ NoConstantCondition.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -40,7 +63,7 @@ implementation =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -74,6 +97,7 @@ isStatic expr =
|
||||
Variable value ->
|
||||
if isStaticVariable value then
|
||||
True
|
||||
|
||||
else
|
||||
False
|
||||
|
||||
@ -87,7 +111,7 @@ isStatic expr =
|
||||
True
|
||||
|
||||
BinOp (Variable op) left right ->
|
||||
(Set.member op comparisonOperators)
|
||||
Set.member op comparisonOperators
|
||||
&& (left == right || (isStatic left && isStatic right))
|
||||
|
||||
_ ->
|
||||
@ -100,6 +124,7 @@ expressionFn ctx node =
|
||||
Enter (If cond _ _) ->
|
||||
if isStatic cond then
|
||||
( [ error ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
|
@ -1,27 +1,38 @@
|
||||
module Lint.Rules.NoDebug exposing (rule)
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
if Debug.log "condition" condition then a else b
|
||||
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, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
|
||||
|
||||
type alias Context =
|
||||
@ -33,6 +44,7 @@ type alias Context =
|
||||
rules =
|
||||
[ NoDebug.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -44,7 +56,7 @@ implementation =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -60,6 +72,7 @@ expressionFn ctx node =
|
||||
Enter (Variable vars) ->
|
||||
if List.member "Debug" vars then
|
||||
( [ error ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
|
@ -1,21 +1,25 @@
|
||||
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, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
@ -30,6 +34,7 @@ type alias Context =
|
||||
rules =
|
||||
[ NoDuplicateImports.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -59,10 +64,11 @@ statementFn ctx node =
|
||||
name =
|
||||
String.join "." names
|
||||
in
|
||||
if Set.member name ctx.imports then
|
||||
( [], { ctx | duplicates = Set.insert name ctx.duplicates } )
|
||||
else
|
||||
( [], { ctx | imports = Set.insert name ctx.imports } )
|
||||
if Set.member name ctx.imports then
|
||||
( [], { ctx | duplicates = Set.insert name ctx.duplicates } )
|
||||
|
||||
else
|
||||
( [], { ctx | imports = Set.insert name ctx.imports } )
|
||||
|
||||
_ ->
|
||||
( [], ctx )
|
||||
@ -75,4 +81,4 @@ moduleEndFn ctx =
|
||||
Set.toList ctx.duplicates
|
||||
|> List.map error
|
||||
in
|
||||
( errors, ctx )
|
||||
( errors, ctx )
|
||||
|
@ -1,21 +1,25 @@
|
||||
module Lint.Rules.NoImportingEverything exposing (rule, Configuration)
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule, Configuration
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
import Html exposing (..)
|
||||
|
||||
|
||||
# Success
|
||||
|
||||
import Html exposing (div, p, textarea)
|
||||
|
||||
-}
|
||||
|
||||
import Set exposing (Set)
|
||||
import Ast.Statement exposing (..)
|
||||
import Lint exposing (lint, doNothing)
|
||||
import Lint.Types exposing (LintRule, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
type alias Context =
|
||||
@ -32,8 +36,9 @@ type alias Configuration =
|
||||
functions and types are unknown to them.
|
||||
|
||||
rules =
|
||||
[ NoImportingEverything.rule { exceptions = ["Html"]}
|
||||
[ NoImportingEverything.rule { exceptions = [ "Html" ] }
|
||||
]
|
||||
|
||||
-}
|
||||
rule : Configuration -> LintRule
|
||||
rule exceptions input =
|
||||
@ -45,7 +50,7 @@ implementation config =
|
||||
{ statementFn = statementFn
|
||||
, typeFn = doNothing
|
||||
, expressionFn = doNothing
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context (Set.fromList config.exceptions)
|
||||
}
|
||||
|
||||
@ -63,10 +68,11 @@ statementFn ctx node =
|
||||
name =
|
||||
String.join "." names
|
||||
in
|
||||
if Set.member name ctx.exceptions then
|
||||
( [], ctx )
|
||||
else
|
||||
( [ error name ], ctx )
|
||||
if Set.member name ctx.exceptions then
|
||||
( [], ctx )
|
||||
|
||||
else
|
||||
( [ error name ], ctx )
|
||||
|
||||
_ ->
|
||||
( [], ctx )
|
||||
|
@ -1,23 +1,27 @@
|
||||
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, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
@ -31,6 +35,7 @@ type alias Context =
|
||||
rules =
|
||||
[ NoUnannotatedFunction.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -42,7 +47,7 @@ implementation =
|
||||
{ statementFn = statementFn
|
||||
, typeFn = doNothing
|
||||
, expressionFn = doNothing
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context Set.empty
|
||||
}
|
||||
|
||||
@ -61,6 +66,7 @@ statementFn ctx node =
|
||||
Enter (FunctionDeclaration name params body) ->
|
||||
if Set.member name ctx.annotatedFunctions then
|
||||
( [], ctx )
|
||||
|
||||
else
|
||||
( [ createError name ], ctx )
|
||||
|
||||
|
@ -1,26 +1,32 @@
|
||||
module Lint.Rules.NoUnusedVariables exposing (rule)
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
module Main exposing (a)
|
||||
|
||||
a n =
|
||||
n + 1
|
||||
b = a 2
|
||||
|
||||
b =
|
||||
a 2
|
||||
|
||||
|
||||
# Success
|
||||
|
||||
module Main exposing (a)
|
||||
|
||||
a n =
|
||||
n + 1
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
import Ast.Statement exposing (..)
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (LintRule, Direction(..), LintError, LintRuleImplementation)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
@ -46,6 +52,7 @@ emptyScope =
|
||||
rules =
|
||||
[ NoUnusedVariables.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -78,7 +85,7 @@ addUsedToStack scopes variables =
|
||||
Just scope ->
|
||||
{ scope | used = Set.union scope.used (Set.fromList variables) }
|
||||
in
|
||||
lastScope :: (List.drop 1 scopes)
|
||||
lastScope :: List.drop 1 scopes
|
||||
|
||||
|
||||
addFoundToStack : List Scope -> List String -> List Scope
|
||||
@ -92,7 +99,7 @@ addFoundToStack scopes variables =
|
||||
Just scope ->
|
||||
{ scope | declared = Set.union scope.declared (Set.fromList variables) }
|
||||
in
|
||||
lastScope :: (List.drop 1 scopes)
|
||||
lastScope :: List.drop 1 scopes
|
||||
|
||||
|
||||
makeReport : Maybe Scope -> ( List LintError, Set String )
|
||||
@ -115,7 +122,7 @@ makeReport scope =
|
||||
|> List.sort
|
||||
|> List.map createError
|
||||
in
|
||||
( errors, variablesUsedButNotFromThisScope )
|
||||
( errors, variablesUsedButNotFromThisScope )
|
||||
|
||||
|
||||
variableName : Expression -> Maybe (List String)
|
||||
@ -153,7 +160,7 @@ expressionFn ctx node =
|
||||
newScope =
|
||||
Scope variables Set.empty
|
||||
in
|
||||
( [], { ctx | scopes = newScope :: ctx.scopes } )
|
||||
( [], { ctx | scopes = newScope :: ctx.scopes } )
|
||||
|
||||
Exit (Let _ _) ->
|
||||
let
|
||||
@ -165,7 +172,7 @@ expressionFn ctx node =
|
||||
newScopes =
|
||||
List.drop 1 ctx.scopes
|
||||
in
|
||||
( errors, { ctx | scopes = addUsedToStack newScopes (Set.toList variablesUsedButNotFromThisScope) } )
|
||||
( errors, { ctx | scopes = addUsedToStack newScopes (Set.toList variablesUsedButNotFromThisScope) } )
|
||||
|
||||
_ ->
|
||||
( [], ctx )
|
||||
@ -226,7 +233,7 @@ statementFn ctx node =
|
||||
[]
|
||||
imported
|
||||
in
|
||||
( [], { ctx | scopes = addFoundToStack ctx.scopes variables } )
|
||||
( [], { ctx | scopes = addFoundToStack ctx.scopes variables } )
|
||||
|
||||
Enter (ModuleDeclaration names exportType) ->
|
||||
( [], addExposedVariables ctx exportType )
|
||||
@ -244,9 +251,10 @@ moduleEndFn ctx =
|
||||
( errors, _ ) =
|
||||
if ctx.exportsEverything then
|
||||
( [], Set.empty )
|
||||
|
||||
else
|
||||
ctx.scopes
|
||||
|> List.head
|
||||
|> makeReport
|
||||
in
|
||||
( errors, ctx )
|
||||
( errors, ctx )
|
||||
|
@ -1,26 +1,32 @@
|
||||
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, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
|
||||
|
||||
type alias Context =
|
||||
@ -32,6 +38,7 @@ type alias Context =
|
||||
rules =
|
||||
[ NoUselessIf.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -43,7 +50,7 @@ implementation =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -59,6 +66,7 @@ expressionFn ctx node =
|
||||
Enter (If cond then_ else_) ->
|
||||
if then_ == else_ then
|
||||
( [ error ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
|
@ -1,37 +1,59 @@
|
||||
module Lint.Rules.NoUselessPatternMatching exposing (rule)
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
-- Useless pattern matching
|
||||
case value of
|
||||
Foo -> 1
|
||||
Bar -> 1
|
||||
_ -> 1
|
||||
Foo ->
|
||||
1
|
||||
|
||||
Bar ->
|
||||
1
|
||||
|
||||
_ ->
|
||||
1
|
||||
|
||||
-- Useless pattern `Bar`, it's the same as the default pattern
|
||||
case value of
|
||||
Foo -> 2
|
||||
Bar -> 1
|
||||
_ -> 1
|
||||
Foo ->
|
||||
2
|
||||
|
||||
Bar ->
|
||||
1
|
||||
|
||||
_ ->
|
||||
1
|
||||
|
||||
|
||||
# Success
|
||||
|
||||
case value of
|
||||
Foo -> 1
|
||||
Bar -> 2
|
||||
_ -> 3
|
||||
Foo ->
|
||||
1
|
||||
|
||||
Bar ->
|
||||
2
|
||||
|
||||
_ ->
|
||||
3
|
||||
|
||||
case value of
|
||||
Foo n -> n
|
||||
Bar n -> n
|
||||
Foo n ->
|
||||
n
|
||||
|
||||
Bar n ->
|
||||
n
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
import Lint exposing (lint, visitExpression, doNothing)
|
||||
import Lint.Types exposing (LintRule, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint, visitExpression)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import Regex
|
||||
import Set exposing (Set)
|
||||
|
||||
@ -46,6 +68,7 @@ pattern will lead to the same value as the default pattern.
|
||||
rules =
|
||||
[ NoUselessPatternMatching.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -57,7 +80,7 @@ implementation =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -67,7 +90,7 @@ variableFinder =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = findVariable
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Set.empty
|
||||
}
|
||||
|
||||
@ -104,7 +127,7 @@ subPatternMatchingVariables pattern =
|
||||
[ String.join "." a ]
|
||||
|
||||
Application object variable ->
|
||||
(subPatternMatchingVariables object) ++ (subPatternMatchingVariables variable)
|
||||
subPatternMatchingVariables object ++ subPatternMatchingVariables variable
|
||||
|
||||
_ ->
|
||||
[]
|
||||
@ -145,7 +168,7 @@ patternsAreAllTheSame patterns =
|
||||
|> Set.fromList
|
||||
|> (\set -> Set.size set == 1)
|
||||
in
|
||||
(not anyUseVariables) && bodiesAreIdentical
|
||||
not anyUseVariables && bodiesAreIdentical
|
||||
|
||||
|
||||
defaultPattern : List ( Expression, Expression, Set String, Set String ) -> Maybe ( Expression, Expression, Set String, Set String )
|
||||
@ -161,6 +184,7 @@ defaultPattern patterns =
|
||||
Variable names ->
|
||||
if isVariable (String.join "." names) then
|
||||
Just ( pattern, body, used, declared )
|
||||
|
||||
else
|
||||
Nothing
|
||||
|
||||
@ -193,18 +217,17 @@ thereAreUselessPatterns patterns =
|
||||
justDefault =
|
||||
Maybe.withDefault ( Integer 1, Integer 1, Set.empty, Set.empty ) default
|
||||
in
|
||||
hasDefault
|
||||
&& (List.foldl
|
||||
(\pattern res ->
|
||||
res
|
||||
|| ((pattern /= justDefault)
|
||||
&& (patternBody pattern == patternBody justDefault)
|
||||
&& not (usesIntroducedVariable pattern)
|
||||
)
|
||||
)
|
||||
False
|
||||
patterns
|
||||
)
|
||||
hasDefault
|
||||
&& List.foldl
|
||||
(\pattern res ->
|
||||
res
|
||||
|| ((pattern /= justDefault)
|
||||
&& (patternBody pattern == patternBody justDefault)
|
||||
&& not (usesIntroducedVariable pattern)
|
||||
)
|
||||
)
|
||||
False
|
||||
patterns
|
||||
|
||||
|
||||
expressionFn : Context -> Direction Expression -> ( List LintError, Context )
|
||||
@ -219,12 +242,14 @@ expressionFn ctx node =
|
||||
( pattern, body, Tuple.second <| visitExpression variableFinder body, patternMatchingVariables pattern )
|
||||
)
|
||||
in
|
||||
if patternsAreAllTheSame analyzedPatterns then
|
||||
( [ uselessPatternMatchingError ], ctx )
|
||||
else if thereAreUselessPatterns analyzedPatterns then
|
||||
( [ uselessPatternError ], ctx )
|
||||
else
|
||||
( [], ctx )
|
||||
if patternsAreAllTheSame analyzedPatterns then
|
||||
( [ uselessPatternMatchingError ], ctx )
|
||||
|
||||
else if thereAreUselessPatterns analyzedPatterns then
|
||||
( [ uselessPatternError ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
_ ->
|
||||
( [], ctx )
|
||||
|
@ -1,22 +1,30 @@
|
||||
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 (LintRule, Direction(..), LintError, LintRuleImplementation)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
|
||||
|
||||
type alias Context =
|
||||
@ -28,6 +36,7 @@ type alias Context =
|
||||
rules =
|
||||
[ NoWarningComments.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -39,7 +48,7 @@ implementation =
|
||||
{ statementFn = statementFn
|
||||
, typeFn = doNothing
|
||||
, expressionFn = doNothing
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -53,16 +62,22 @@ findWarning : String -> Maybe LintError
|
||||
findWarning text =
|
||||
if String.contains "TODO" text then
|
||||
Just <| error "TODO"
|
||||
|
||||
else if String.contains "todo" text then
|
||||
Just <| error "todo"
|
||||
|
||||
else if String.contains "FIXME" text then
|
||||
Just <| error "FIXME"
|
||||
|
||||
else if String.contains "fixme" text then
|
||||
Just <| error "fixme"
|
||||
|
||||
else if String.contains "XXX" text then
|
||||
Just <| error "XXX"
|
||||
|
||||
else if String.contains "xxx" text then
|
||||
Just <| error "xxx"
|
||||
|
||||
else
|
||||
Nothing
|
||||
|
||||
@ -75,12 +90,12 @@ statementFn ctx node =
|
||||
warning =
|
||||
findWarning text
|
||||
in
|
||||
case warning of
|
||||
Just err ->
|
||||
( [ err ], ctx )
|
||||
case warning of
|
||||
Just err ->
|
||||
( [ err ], ctx )
|
||||
|
||||
Nothing ->
|
||||
( [], ctx )
|
||||
Nothing ->
|
||||
( [], ctx )
|
||||
|
||||
_ ->
|
||||
( [], ctx )
|
||||
|
@ -1,23 +1,29 @@
|
||||
module Lint.Rules.SimplifyPiping exposing (rule)
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
a = values
|
||||
|> List.map foo
|
||||
|> List.map bar
|
||||
a =
|
||||
values
|
||||
|> List.map foo
|
||||
|> List.map bar
|
||||
|
||||
|
||||
# Success
|
||||
|
||||
a = values
|
||||
|> List.map (foo >> bar)
|
||||
a =
|
||||
values
|
||||
|> List.map (foo >> bar)
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
import Lint exposing (lint, doNothing)
|
||||
import Lint.Types exposing (LintRule, LintRuleImplementation, LintError, Direction(..))
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
@ -30,6 +36,7 @@ type alias Context =
|
||||
rules =
|
||||
[ SimplifyPiping.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -41,7 +48,7 @@ implementation =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -76,6 +83,7 @@ reportIfSimplifiableMethod op left right =
|
||||
[ Application (Access (Variable names1) fns1) _, Application (Access (Variable names2) fns2) _ ] ->
|
||||
if [ names1, fns1 ] == [ names2, fns2 ] && Set.member (nameOfMethod [ names1, fns1 ]) simplifiableFns then
|
||||
[ error op <| nameOfMethod [ names1, fns1 ] ]
|
||||
|
||||
else
|
||||
[]
|
||||
|
||||
|
@ -1,21 +1,27 @@
|
||||
module Lint.Rules.SimplifyPropertyAccess exposing (rule)
|
||||
|
||||
{-|
|
||||
|
||||
@docs rule
|
||||
|
||||
|
||||
# Fail
|
||||
|
||||
a = List.map (\x -> x.foo) values
|
||||
a =
|
||||
List.map (\x -> x.foo) values
|
||||
|
||||
|
||||
# Success
|
||||
|
||||
a = List.map .foo values
|
||||
a =
|
||||
List.map .foo values
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Statement exposing (..)
|
||||
import Ast.Expression exposing (..)
|
||||
import Lint exposing (lint, doNothing)
|
||||
import Lint.Types exposing (LintRule, LintRuleImplementation, LintError, Direction(..))
|
||||
import Ast.Statement exposing (..)
|
||||
import Lint exposing (doNothing, lint)
|
||||
import Lint.Types exposing (Direction(..), LintError, LintRule, LintRuleImplementation)
|
||||
|
||||
|
||||
type alias Context =
|
||||
@ -27,6 +33,7 @@ type alias Context =
|
||||
rules =
|
||||
[ SimplifyPropertyAccess.rule
|
||||
]
|
||||
|
||||
-}
|
||||
rule : LintRule
|
||||
rule input =
|
||||
@ -38,7 +45,7 @@ implementation =
|
||||
{ statementFn = statementFn
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
@ -54,6 +61,7 @@ expressionFn ctx node =
|
||||
Enter (Lambda [ Variable paramNames ] (Access (Variable varName) properties)) ->
|
||||
if List.length properties == 1 && varName == paramNames then
|
||||
( [ String.join "" properties |> error ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
@ -67,6 +75,7 @@ statementFn ctx node =
|
||||
Enter (FunctionDeclaration _ [ Variable paramNames ] (Access (Variable varName) properties)) ->
|
||||
if List.length properties == 1 && varName == paramNames then
|
||||
( [ String.join "" properties |> error ], ctx )
|
||||
|
||||
else
|
||||
( [], ctx )
|
||||
|
||||
|
@ -1,31 +1,32 @@
|
||||
module Lint.Types
|
||||
exposing
|
||||
( Direction(..)
|
||||
, File
|
||||
, LintError
|
||||
, LintImplementation
|
||||
, LintResult
|
||||
, LintRule
|
||||
, LintRuleImplementation
|
||||
, Reporter
|
||||
, Severity
|
||||
, Severity(..)
|
||||
, Visitor
|
||||
)
|
||||
module Lint.Types exposing
|
||||
( LintError, Direction(..)
|
||||
, LintRule, Severity(..), Reporter
|
||||
, LintRuleImplementation, LintImplementation
|
||||
, Visitor, LintResult, File
|
||||
)
|
||||
|
||||
{-| This module contains types that are used for writing rules.
|
||||
|
||||
|
||||
# Elementary types
|
||||
|
||||
@docs LintError, Direction
|
||||
|
||||
|
||||
# Configuration
|
||||
|
||||
@docs LintRule, Severity, Reporter
|
||||
|
||||
|
||||
# Writing rules
|
||||
|
||||
@docs LintRuleImplementation, LintImplementation
|
||||
|
||||
|
||||
# Internal types
|
||||
|
||||
@docs Visitor, LintResult, File
|
||||
|
||||
-}
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
@ -38,6 +39,7 @@ a description of the error.
|
||||
error : LintError
|
||||
error =
|
||||
LintError "NoDebug" "Forbidden use of Debug"
|
||||
|
||||
-}
|
||||
type alias LintError =
|
||||
{ rule : String
|
||||
@ -63,31 +65,35 @@ enforce.
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, moduleEndFn = \ctx -> ( [], ctx )
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
-}
|
||||
type alias LintImplementation nodeType context =
|
||||
context -> Direction nodeType -> ( List LintError, context )
|
||||
|
||||
|
||||
{-| When visiting the AST, nodes are visited twice:
|
||||
- on Enter, before the children of the node will be visited
|
||||
- on Exit, after the children of the node have been visited
|
||||
|
||||
- on Enter, before the children of the node will be visited
|
||||
|
||||
- on Exit, after the children of the node have been visited
|
||||
|
||||
expressionFn : Context -> Direction Expression -> ( List LintError, Context )
|
||||
expressionFn ctx node =
|
||||
case node of
|
||||
Enter (Variable names) ->
|
||||
( [], markVariableAsUsed ctx names )
|
||||
case node of
|
||||
Enter (Variable names) ->
|
||||
( [], markVariableAsUsed ctx names )
|
||||
|
||||
-- Find variables declared in `let .. in ..` expression
|
||||
Enter (Let declarations body) ->
|
||||
( [], registerVariables ctx declarations )
|
||||
-- Find variables declared in `let .. in ..` expression
|
||||
Enter (Let declarations body) ->
|
||||
( [], registerVariables ctx declarations )
|
||||
|
||||
-- When exiting the `let .. in ..` expression, report the variables that were not used.
|
||||
Exit (Let _ _) ->
|
||||
( unusedVariables ctx |> List.map createError, ctx )
|
||||
|
||||
-- When exiting the `let .. in ..` expression, report the variables that were not used.
|
||||
Exit (Let _ _) ->
|
||||
( unusedVariables ctx |> List.map createError, ctx )
|
||||
-}
|
||||
type Direction node
|
||||
= Enter node
|
||||
@ -95,25 +101,31 @@ type Direction node
|
||||
|
||||
|
||||
{-| A LintRuleImplementation is the implementation of a rule. It is a record that contains:
|
||||
- initialContext: An initial context
|
||||
- statementFn: A LintImplementation for Statement nodes
|
||||
- typeFn: A LintImplementation for Type nodes
|
||||
- expressionFn: A LintImplementation for Expression nodes
|
||||
- moduleEndFn: A function that takes a context and returns a list of error. Similar to a LintImplementation, but will
|
||||
be called after visiting the whole AST.
|
||||
|
||||
- initialContext: An initial context
|
||||
|
||||
- statementFn: A LintImplementation for Statement nodes
|
||||
|
||||
- typeFn: A LintImplementation for Type nodes
|
||||
|
||||
- expressionFn: A LintImplementation for Expression nodes
|
||||
|
||||
- moduleEndFn: A function that takes a context and returns a list of error. Similar to a LintImplementation, but will
|
||||
be called after visiting the whole AST.
|
||||
|
||||
rule : LintRule
|
||||
rule input =
|
||||
lint input implementation
|
||||
lint input implementation
|
||||
|
||||
implementation : LintRuleImplementation Context
|
||||
implementation =
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\ctx -> ( [], ctx ))
|
||||
, initialContext = Context
|
||||
}
|
||||
{ statementFn = doNothing
|
||||
, typeFn = doNothing
|
||||
, expressionFn = expressionFn
|
||||
, moduleEndFn = (\\ctx -> ( [], ctx ))
|
||||
, initialContext = Context
|
||||
}
|
||||
|
||||
-}
|
||||
type alias LintRuleImplementation context =
|
||||
{ statementFn : LintImplementation Statement context
|
||||
@ -140,6 +152,7 @@ type alias LintRule =
|
||||
A Visitor represents a node and calls the appropriate function for the given node type.
|
||||
|
||||
Note: this is internal API, and will be removed in a future version.
|
||||
|
||||
-}
|
||||
type alias Visitor context =
|
||||
LintRuleImplementation context -> context -> ( List LintError, context )
|
||||
@ -147,9 +160,10 @@ type alias Visitor context =
|
||||
|
||||
{-| Severity associated to a rule.
|
||||
|
||||
- Critical: Transgressions reported by the rule will make the linting process fail.
|
||||
- Warning: Transgressions reported by the rule will not make the linting process fail.
|
||||
- Disabled: Rule will not be enforced.
|
||||
- Critical: Transgressions reported by the rule will make the linting process fail.
|
||||
- Warning: Transgressions reported by the rule will not make the linting process fail.
|
||||
- Disabled: Rule will not be enforced.
|
||||
|
||||
-}
|
||||
type Severity
|
||||
= Disabled
|
||||
|
@ -1,8 +1,8 @@
|
||||
module Lint.Visitor exposing (transformStatementsIntoVisitors, expressionToVisitors)
|
||||
module Lint.Visitor exposing (expressionToVisitors, transformStatementsIntoVisitors)
|
||||
|
||||
import Ast.Expression exposing (..)
|
||||
import Ast.Statement exposing (..)
|
||||
import Lint.Types exposing (LintRule, Direction(..), Visitor)
|
||||
import Lint.Types exposing (Direction(..), LintRule, Visitor)
|
||||
|
||||
|
||||
createExitAndEnterWithChildren : (Direction nodeType -> Visitor context) -> nodeType -> List (Visitor context) -> List (Visitor context)
|
||||
@ -92,7 +92,7 @@ expressionToVisitors node =
|
||||
childrenVisitors =
|
||||
List.concatMap expressionToVisitors children
|
||||
in
|
||||
createExitAndEnterWithChildren expressionVisitor node childrenVisitors
|
||||
createExitAndEnterWithChildren expressionVisitor node childrenVisitors
|
||||
|
||||
|
||||
typeToVisitors : Type -> List (Visitor context)
|
||||
@ -114,7 +114,7 @@ statementToVisitors node =
|
||||
_ ->
|
||||
[]
|
||||
in
|
||||
createExitAndEnterWithChildren statementVisitor node childrenVisitors
|
||||
createExitAndEnterWithChildren statementVisitor node childrenVisitors
|
||||
|
||||
|
||||
transformStatementsIntoVisitors : List Statement -> List (Visitor context)
|
||||
|
Loading…
Reference in New Issue
Block a user