mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-12-25 10:41:47 +03:00
NoUnused.CustomTypeConstructors: Transform into a project rule
This commit is contained in:
parent
b2fd92f529
commit
ce1c059d4c
@ -14,6 +14,7 @@ import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
||||
import Elm.Syntax.Exposing as Exposing exposing (Exposing, TopLevelExpose)
|
||||
import Elm.Syntax.Expression as Expression exposing (Expression)
|
||||
import Elm.Syntax.Module as Module exposing (Module)
|
||||
import Elm.Syntax.ModuleName exposing (ModuleName)
|
||||
import Elm.Syntax.Node as Node exposing (Node)
|
||||
import Elm.Syntax.Signature as Signature exposing (Signature)
|
||||
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
||||
@ -73,16 +74,25 @@ in your editor, rather than when running your tests or [elm-xref](https://github
|
||||
-}
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoUnused.CustomTypeConstructors" initialContext
|
||||
|> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
|
||||
|> Rule.withDeclarationListVisitor declarationListVisitor
|
||||
|> Rule.withDeclarationVisitor declarationVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withFinalModuleEvaluation finalEvaluation
|
||||
|> Rule.fromModuleRuleSchema
|
||||
Rule.newProjectRuleSchema "NoUnused.CustomTypeConstructors"
|
||||
{ moduleVisitor = moduleVisitor
|
||||
, initProjectContext = initProjectContext
|
||||
, fromProjectToModule = fromProjectToModule
|
||||
, fromModuleToProject = fromModuleToProject
|
||||
, foldProjectContexts = foldProjectContexts
|
||||
}
|
||||
|> Rule.fromProjectRuleSchema
|
||||
|
||||
|
||||
type alias Context =
|
||||
|
||||
-- CONTEXT
|
||||
|
||||
|
||||
type alias ProjectContext =
|
||||
{}
|
||||
|
||||
|
||||
type alias ModuleContext =
|
||||
{ exposedCustomTypesWithConstructors : Set String
|
||||
, exposesEverything : Bool
|
||||
, declaredTypesWithConstructors : Dict String (Node String)
|
||||
@ -91,8 +101,13 @@ type alias Context =
|
||||
}
|
||||
|
||||
|
||||
initialContext : Context
|
||||
initialContext =
|
||||
initProjectContext : ProjectContext
|
||||
initProjectContext =
|
||||
{}
|
||||
|
||||
|
||||
fromProjectToModule : Rule.ModuleKey -> Node ModuleName -> ProjectContext -> ModuleContext
|
||||
fromProjectToModule _ _ projectContext =
|
||||
{ exposedCustomTypesWithConstructors = Set.empty
|
||||
, exposesEverything = False
|
||||
, declaredTypesWithConstructors = Dict.empty
|
||||
@ -101,6 +116,16 @@ initialContext =
|
||||
}
|
||||
|
||||
|
||||
fromModuleToProject : Rule.ModuleKey -> Node ModuleName -> ModuleContext -> ProjectContext
|
||||
fromModuleToProject _ _ moduleContext =
|
||||
{}
|
||||
|
||||
|
||||
foldProjectContexts : ProjectContext -> ProjectContext -> ProjectContext
|
||||
foldProjectContexts _ previousContext =
|
||||
previousContext
|
||||
|
||||
|
||||
error : Node String -> Error
|
||||
error node =
|
||||
Rule.error
|
||||
@ -115,10 +140,25 @@ error node =
|
||||
|
||||
|
||||
|
||||
-- MODULE VISITOR
|
||||
|
||||
|
||||
moduleVisitor : Rule.ModuleRuleSchema {} ModuleContext -> Rule.ModuleRuleSchema { hasAtLeastOneVisitor : () } ModuleContext
|
||||
moduleVisitor schema =
|
||||
schema
|
||||
|> Rule.withModuleDefinitionVisitor (\_ context -> ( [], context ))
|
||||
|> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
|
||||
|> Rule.withDeclarationListVisitor declarationListVisitor
|
||||
|> Rule.withDeclarationVisitor declarationVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withFinalModuleEvaluation finalEvaluation
|
||||
|
||||
|
||||
|
||||
-- MODULE DEFINITION VISITOR
|
||||
|
||||
|
||||
moduleDefinitionVisitor : Node Module -> Context -> ( List nothing, Context )
|
||||
moduleDefinitionVisitor : Node Module -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
moduleDefinitionVisitor moduleNode context =
|
||||
case Module.exposingList (Node.value moduleNode) of
|
||||
Exposing.All _ ->
|
||||
@ -156,12 +196,12 @@ moduleDefinitionVisitor moduleNode context =
|
||||
-- DECLARATION LIST VISITOR
|
||||
|
||||
|
||||
declarationListVisitor : List (Node Declaration) -> Context -> ( List nothing, Context )
|
||||
declarationListVisitor : List (Node Declaration) -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
declarationListVisitor nodes context =
|
||||
( [], List.foldl register context nodes )
|
||||
|
||||
|
||||
register : Node Declaration -> Context -> Context
|
||||
register : Node Declaration -> ModuleContext -> ModuleContext
|
||||
register node context =
|
||||
case Node.value node of
|
||||
Declaration.CustomTypeDeclaration { name, generics, constructors } ->
|
||||
@ -191,7 +231,7 @@ register node context =
|
||||
-- DECLARATION VISITOR
|
||||
|
||||
|
||||
declarationVisitor : Node Declaration -> Direction -> Context -> ( List nothing, Context )
|
||||
declarationVisitor : Node Declaration -> Direction -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
declarationVisitor node direction context =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Declaration.CustomTypeDeclaration { name, constructors } ) ->
|
||||
@ -200,7 +240,7 @@ declarationVisitor node direction context =
|
||||
|
||||
else
|
||||
let
|
||||
newContext : Context
|
||||
newContext : ModuleContext
|
||||
newContext =
|
||||
List.foldl
|
||||
(\constructor ctx ->
|
||||
@ -233,7 +273,7 @@ declarationVisitor node direction context =
|
||||
-- EXPRESSION VISITOR
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Direction -> Context -> ( List nothing, Context )
|
||||
expressionVisitor : Node Expression -> Direction -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
expressionVisitor node direction context =
|
||||
if context.exposesEverything then
|
||||
( [], context )
|
||||
@ -266,7 +306,7 @@ expressionVisitor node direction context =
|
||||
-- FINAL EVALUATION
|
||||
|
||||
|
||||
finalEvaluation : Context -> List Error
|
||||
finalEvaluation : ModuleContext -> List Error
|
||||
finalEvaluation context =
|
||||
if context.exposesEverything then
|
||||
[]
|
||||
@ -282,7 +322,7 @@ finalEvaluation context =
|
||||
-- TYPE ANNOTATION UTILITARY FUNCTIONS
|
||||
|
||||
|
||||
markPhantomTypesFromTypeSignatureAsUsed : Maybe (Node Signature) -> Context -> Context
|
||||
markPhantomTypesFromTypeSignatureAsUsed : Maybe (Node Signature) -> ModuleContext -> ModuleContext
|
||||
markPhantomTypesFromTypeSignatureAsUsed maybeSignature context =
|
||||
let
|
||||
used : List String
|
||||
|
@ -103,7 +103,8 @@ exposingTypeConstructors =
|
||||
describe "Exposed constructors"
|
||||
[ test "should not report unused type constructors when package module is exposing all and module is exposed" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (..)
|
||||
"""
|
||||
module MyModule exposing (..)
|
||||
type Foo = Bar | Baz
|
||||
"""
|
||||
|> Review.Test.runWithProjectData packageProject rule
|
||||
@ -116,13 +117,15 @@ unusedTests typeOfProject project =
|
||||
describe ("Unused variables for " ++ typeOfProject)
|
||||
[ test "should not report non-exposed variables" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (b)
|
||||
"""
|
||||
module MyModule exposing (b)
|
||||
a = 1"""
|
||||
|> Review.Test.runWithProjectData project rule
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should not report used type constructors" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (b)
|
||||
"""
|
||||
module MyModule exposing (b)
|
||||
type Foo = Bar | Baz
|
||||
a = Bar
|
||||
b = Baz"""
|
||||
@ -130,21 +133,24 @@ b = Baz"""
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should not report unused type constructors when module is exposing all" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (..)
|
||||
"""
|
||||
module MyModule exposing (..)
|
||||
type Foo = Bar | Baz
|
||||
"""
|
||||
|> Review.Test.runWithProjectData project rule
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should not report unused type constructors when module is exposing the constructors of that type" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (Foo(..))
|
||||
"""
|
||||
module MyModule exposing (Foo(..))
|
||||
type Foo = Bar | Baz
|
||||
"""
|
||||
|> Review.Test.runWithProjectData project rule
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should report unused type constructors" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (b)
|
||||
"""
|
||||
module MyModule exposing (b)
|
||||
type Foo = Bar | Baz"""
|
||||
|> Review.Test.runWithProjectData project rule
|
||||
|> Review.Test.expectErrors
|
||||
@ -161,7 +167,8 @@ type Foo = Bar | Baz"""
|
||||
]
|
||||
, test "should report unused type constructors, even if the type is exposed" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (Foo)
|
||||
"""
|
||||
module MyModule exposing (Foo)
|
||||
type Foo = Bar | Baz"""
|
||||
|> Review.Test.runWithProjectData project rule
|
||||
|> Review.Test.expectErrors
|
||||
@ -184,7 +191,8 @@ phantomTypeTests typeOfProject project =
|
||||
describe ("Phantom type for " ++ typeOfProject)
|
||||
[ test "should not report a custom type with one constructor, when it is used in the stead of a phantom variable" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type User = User
|
||||
type Id a = Id
|
||||
|
||||
@ -195,7 +203,8 @@ id = Id
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should not report a custom type with one constructor, when it is used in the stead of a phantom variable in a let variable" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type User = User
|
||||
type Id a = Id
|
||||
|
||||
@ -211,7 +220,8 @@ id =
|
||||
|> Review.Test.expectNoErrors
|
||||
, test "should report a custom type with multiple constructors, when it is used in the stead of a phantom variable" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type Something = A | B
|
||||
type Id a = Id
|
||||
|
||||
@ -233,7 +243,8 @@ id = Id
|
||||
]
|
||||
, test "should report a custom type with one constructor, when there is a phantom type available but it isn't used" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type User = User
|
||||
type Id a = Id
|
||||
id = Id
|
||||
@ -245,11 +256,12 @@ id = Id
|
||||
, details = details
|
||||
, under = "User"
|
||||
}
|
||||
|> Review.Test.atExactly { start = { row = 2, column = 13 }, end = { row = 2, column = 17 } }
|
||||
|> Review.Test.atExactly { start = { row = 3, column = 13 }, end = { row = 3, column = 17 } }
|
||||
]
|
||||
, test "should report a custom type with one constructor when the constructor is named differently than the type, even when it is used in the stead of a phantom variable" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type User = UserConstructor
|
||||
type Id a = Id
|
||||
|
||||
@ -266,7 +278,8 @@ id = Id
|
||||
]
|
||||
, test "should report a custom type with one constructor, when it is used in the stead of a non-phantom variable" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type User = User
|
||||
type Id a = Id a
|
||||
|
||||
@ -280,11 +293,12 @@ id = Id
|
||||
, details = details
|
||||
, under = "User"
|
||||
}
|
||||
|> Review.Test.atExactly { start = { row = 2, column = 13 }, end = { row = 2, column = 17 } }
|
||||
|> Review.Test.atExactly { start = { row = 3, column = 13 }, end = { row = 3, column = 17 } }
|
||||
]
|
||||
, test "should report a custom type with a type variable, when it is used in the stead of a phantom variable" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type User something = User
|
||||
type Id a = Id a
|
||||
|
||||
@ -298,11 +312,12 @@ id = Id
|
||||
, details = details
|
||||
, under = "User"
|
||||
}
|
||||
|> Review.Test.atExactly { start = { row = 2, column = 23 }, end = { row = 2, column = 27 } }
|
||||
|> Review.Test.atExactly { start = { row = 3, column = 23 }, end = { row = 3, column = 27 } }
|
||||
]
|
||||
, test "should report a custom type with one constructor that has arguments, when it is used in the stead of a phantom variable" <|
|
||||
\() ->
|
||||
"""module MyModule exposing (id)
|
||||
"""
|
||||
module MyModule exposing (id)
|
||||
type User = User Something
|
||||
type Id a = Id a
|
||||
|
||||
@ -316,6 +331,6 @@ id = Id
|
||||
, details = details
|
||||
, under = "User"
|
||||
}
|
||||
|> Review.Test.atExactly { start = { row = 2, column = 13 }, end = { row = 2, column = 17 } }
|
||||
|> Review.Test.atExactly { start = { row = 3, column = 13 }, end = { row = 3, column = 17 } }
|
||||
]
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user