elm-review/tests/NoUnusedVariablesTest.elm

340 lines
12 KiB
Elm
Raw Normal View History

2018-11-22 21:19:19 +03:00
module NoUnusedVariablesTest exposing (all)
import Elm.Syntax.Range exposing (Location, Range)
import Lint exposing (Rule)
import Lint.Error exposing (Error)
import Lint.Rule exposing (LintResult)
import Lint.Rule.NoUnusedVariables exposing (rule)
import Test exposing (Test, describe, test)
import TestUtil exposing (expectErrors, ruleTester)
testRule : String -> LintResult
testRule =
ruleTester rule
error : String -> Range -> Error
error =
Error "NoUnusedVariables"
location : Int -> Int -> Int -> Range
location row columnStart columnEnd =
{ start = { row = row, column = columnStart }
, end = { row = row, column = columnEnd }
}
tests : List Test
tests =
[ test "should not report exposed top-level variables" <|
\() ->
testRule """module A exposing (a)
a = 1"""
|> expectErrors []
, test "should not report used top-level variables" <|
\() ->
testRule """module A exposing (b)
a n = 1
b = a 1"""
|> expectErrors []
, test "should report unused top-level variables" <|
\() ->
testRule """module A exposing (b)
a = 1"""
|> expectErrors [ error "Variable `a` is not used" (location 2 1 2) ]
, test "should report unused top-level variables even if they are annotated" <|
\() ->
testRule """module A exposing (b)
a: Int
a = 1"""
|> expectErrors [ error "Variable `a` is not used" (location 3 1 2) ]
, test "should not report unused top-level variables if everything is exposed" <|
\() ->
testRule """module A exposing (..)
a n = 1
b = a 1"""
|> expectErrors []
, test "should not report unused top-level variables that are exposed by name" <|
\() ->
testRule """module A exposing (a, b)
a = 1
b = 2"""
|> expectErrors []
, test "should not report unused top-level variables that are exposed by name, but report others" <|
\() ->
testRule """module A exposing (a, b)
a = 1
b = 2
c = 3"""
|> expectErrors [ error "Variable `c` is not used" (location 4 1 2) ]
, test "should not report unused top-level variables if everything is exposed (port module)" <|
\() ->
testRule """port module A exposing (..)
a n = 1
b = a 1"""
|> expectErrors []
, test "should not report unused top-level variables that are exposed by name (port module)" <|
\() ->
testRule """port module A exposing (a, b)
a = 1
b = 2"""
|> expectErrors []
, test "should not report unused top-level variables that are exposed by name, but report others (port module)" <|
\() ->
testRule """port module A exposing (a, b)
a = 1
b = 2
c = 3"""
|> expectErrors [ error "Variable `c` is not used" (location 4 1 2) ]
, test "should report unused variables from let declarations" <|
\() ->
testRule """module A exposing (a)
a = let b = 1
in 2"""
|> expectErrors [ error "Variable `b` is not used" (location 2 9 10) ]
, test "should report unused variables from let even if they are exposed by name" <|
\() ->
testRule """module A exposing (a, b)
a = let b = 1
in 2"""
|> expectErrors [ error "Variable `b` is not used" (location 2 9 10) ]
, test "should report unused functions from let even if they are exposed by name" <|
\() ->
testRule """module A exposing (a)
a = let b param = 1
in 2"""
|> expectErrors [ error "Variable `b` is not used" (location 2 9 10) ]
, test "should report unused variables from let even if everything is exposed" <|
\() ->
testRule """module A exposing (..)
a = let b = 1
in 2"""
|> expectErrors [ error "Variable `b` is not used" (location 2 9 10) ]
, test "should not report top-level variables used inside a let expression" <|
\() ->
testRule """module A exposing (a)
b = 1
a = let c = 1
in b + c"""
|> expectErrors []
, test "should not report top-level variables used inside let declarations" <|
\() ->
testRule """module A exposing (a)
b = 1
a = let c = b
in c"""
|> expectErrors []
, test "should not report top-level variables used in nested lets" <|
\() ->
testRule """module A exposing (a)
b = 1
a = let
c = b
d = let
e = 1
in
b + c + e
in
d"""
|> expectErrors []
, test "should not report variables from let declarations that are used in the expression" <|
\() ->
testRule """module A exposing (a)
a = let c = 1
in c"""
|> expectErrors []
, test "should not report unused function parameters" <|
\() ->
testRule """module A exposing (a)
a n = 1"""
|> expectErrors []
, test "should report unused imported functions" <|
\() ->
testRule """module A exposing (b)
import Foo exposing (a)"""
|> expectErrors [ error "Variable `a` is not used" (location 2 22 23) ]
, test "should report unused imported functions (multiple imports)" <|
\() ->
testRule """module A exposing (d)
import Foo exposing (C, a, b)"""
|> expectErrors
2018-11-26 20:12:36 +03:00
[ error "Variable `C` is not used" (location 2 22 23)
, error "Variable `a` is not used" (location 2 25 26)
2018-11-22 21:19:19 +03:00
, error "Variable `b` is not used" (location 2 28 29)
]
-- Needs to be improved, every case should create a new scope stack
-- Right now, every parameter is considered used, which is not great
, test "should not report unused pattern matching parameters" <|
\() ->
testRule """module A exposing (a)
a = case thing of
Foo b c -> []"""
|> expectErrors []
-- Should B and C be reported if they are not used? Probably.
, test "should report unused custom type declarations" <|
\() ->
testRule """module A exposing (a)
type A = B | C"""
2018-11-26 20:39:46 +03:00
|> expectErrors [ error "Type `A` is not used" (location 2 6 7) ]
2018-11-22 21:19:19 +03:00
, test "should report unused type aliases declarations" <|
\() ->
testRule """module A exposing (a)
type alias A = { a : B }"""
2018-11-26 20:39:46 +03:00
|> expectErrors [ error "Type `A` is not used" (location 2 12 13) ]
2018-11-22 21:19:19 +03:00
, test "should not report type used in a signature" <|
\() ->
testRule """module A exposing (a)
type alias A = { a : B }
a : A
a = {a = 1}"""
|> expectErrors []
, test "should not report type used in a signature with multiple arguments" <|
\() ->
testRule """module A exposing (a)
type alias A = { a : B }
a : String -> A
a str = {a = str}"""
|> expectErrors []
, test "should not report type used in a signature with parameterized types (as generic type)" <|
\() ->
testRule """module A exposing (a)
type alias A = { a : B }
a : A B
a = []"""
|> expectErrors []
, test "should not report type used in a signature with parameterized types (as parameter)" <|
\() ->
testRule """module A exposing (a)
type alias A = { a : B }
a : List A
a = []"""
|> expectErrors []
, test "should not report type used in a signature with a record" <|
\() ->
testRule """module A exposing (a)
type alias A = { a : B }
a : { c: A }
a str = {c = str}"""
|> expectErrors []
, test "should not report type used in a signature with a generic record" <|
\() ->
testRule """module A exposing (a)
type alias A = { a : B }
a : { r | c: A }
a str = {c = str}"""
|> expectErrors []
, test "should not report type if it's exposed" <|
\() ->
testRule """module A exposing (A)
type A a = B a"""
|> expectErrors []
, test "should not report custom type if it's exposed with its sub-types" <|
\() ->
testRule """module A exposing (A(..))
type A = B | C | D"""
|> expectErrors []
, test "should report unused variable even if it's present in a generic type" <|
\() ->
testRule """module A exposing (A)
a = 1
type A a = B a"""
|> expectErrors [ error "Variable `a` is not used" (location 2 1 2) ]
, test "should report unused variable even if it's present in a generic record type" <|
\() ->
testRule """module A exposing (a)
r = 1
a : { r | c: A }
a str = {c = str}"""
|> expectErrors [ error "Variable `r` is not used" (location 2 1 2) ]
, test "should report unused operator import" <|
\() ->
testRule """module A exposing (a)
import Parser exposing ((</>))"""
|> expectErrors [ error "Variable `</>` is not used" (location 2 25 30) ]
, test "should not report used operator (infix)" <|
\() ->
testRule """module A exposing (a)
import Parser exposing ((</>))
a = 1 </> 2"""
|> expectErrors []
, test "should not report used operator (prefix)" <|
\() ->
testRule """module A exposing (a)
import Parser exposing ((</>))
a = (</>) 2"""
|> expectErrors []
2018-11-24 19:41:13 +03:00
, test "should report unused opaque types" <|
\() ->
testRule """module A exposing (a)
type A = A Int"""
2018-11-26 20:39:46 +03:00
|> expectErrors [ error "Type `A` is not used" (location 2 6 7) ]
2018-11-24 19:41:13 +03:00
, test "should not report used opaque types" <|
\() ->
testRule """module A exposing (a)
type A = A Int
a : A
a = 1"""
|> expectErrors []
2018-11-26 13:22:43 +03:00
, test "should report unused import" <|
\() ->
testRule """module A exposing (a)
import Html"""
2018-11-26 20:39:46 +03:00
|> expectErrors [ error "Imported module `Html` is not used" (location 2 8 12) ]
2018-11-26 13:22:43 +03:00
, test "should report unused import (multiples segments)" <|
\() ->
testRule """module A exposing (a)
import Html.Styled.Attributes"""
2018-11-26 20:39:46 +03:00
|> expectErrors [ error "Imported module `Html.Styled.Attributes` is not used" (location 2 8 30) ]
2018-11-26 13:22:43 +03:00
, test "should not report import if it exposes all (should be improved by detecting if any exposed value is used)" <|
\() ->
testRule """module A exposing (a)
import Html.Styled.Attributes exposing (..)"""
|> expectErrors []
, test "should report unused variable even if a homonym from a module is used" <|
\() ->
testRule """module A exposing (a)
href = 1
a = Html.Styled.Attributes.href"""
|> expectErrors [ error "Variable `href` is not used" (location 2 1 5) ]
, test "should not report used import (function access)" <|
\() ->
testRule """module A exposing (a)
import Html.Styled.Attributes
a = Html.Styled.Attributes.href"""
|> expectErrors []
, test "should not report unused import if it is aliased" <|
\() ->
testRule """module A exposing (a)
import Html.Styled.Attributes as Html
a = Html.href"""
|> expectErrors []
, test "should report unused import alias" <|
\() ->
testRule """module A exposing (a)
import Html.Styled.Attributes as Html"""
2018-11-26 20:39:46 +03:00
|> expectErrors [ error "Module alias `Html` is not used" (location 2 34 38) ]
2018-11-26 20:12:36 +03:00
, test "should not report import that exposes a used exposed type" <|
\() ->
testRule """module A exposing (a)
import B exposing (C(..))
a : C
a = 1"""
|> expectErrors []
, test "should not report import that exposes an unused exposed type (but whose subtype is potentially used)" <|
\() ->
testRule """module A exposing (a)
import B exposing (C(..))
a : D
a = 1"""
|> expectErrors []
2018-11-22 21:19:19 +03:00
]
all : Test
all =
describe "NoUnusedVariables" tests