From ce1c059d4cb4e86fd62deb099165ed735fb65250 Mon Sep 17 00:00:00 2001 From: Jeroen Engels Date: Thu, 12 Mar 2020 16:55:15 +0100 Subject: [PATCH] NoUnused.CustomTypeConstructors: Transform into a project rule --- src/NoUnused/CustomTypeConstructors.elm | 76 +++++++++++++++----- tests/NoUnusedCustomTypeConstructorsTest.elm | 53 +++++++++----- 2 files changed, 92 insertions(+), 37 deletions(-) diff --git a/src/NoUnused/CustomTypeConstructors.elm b/src/NoUnused/CustomTypeConstructors.elm index d0cd916b..d91ddd6f 100644 --- a/src/NoUnused/CustomTypeConstructors.elm +++ b/src/NoUnused/CustomTypeConstructors.elm @@ -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 diff --git a/tests/NoUnusedCustomTypeConstructorsTest.elm b/tests/NoUnusedCustomTypeConstructorsTest.elm index 49498443..3b08aca9 100644 --- a/tests/NoUnusedCustomTypeConstructorsTest.elm +++ b/tests/NoUnusedCustomTypeConstructorsTest.elm @@ -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 } } ] ]