mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-12-23 17:53:35 +03:00
Backport changes from review dependencies
This commit is contained in:
parent
97179db534
commit
c9e8f9680d
@ -42,4 +42,5 @@ config =
|
||||
--, NoTodoComment.rule
|
||||
-- |> Rule.ignoreErrorsForFiles [ "NoTodoComment" ]
|
||||
]
|
||||
|> List.map (Rule.ignoreErrorsForDirectories [ "src/Vendor/" ])
|
||||
|> List.map (Rule.ignoreErrorsForDirectories [ "src/Vendor/"])
|
||||
|> List.map (Rule.ignoreErrorsForFiles [ "tests/NoUnused/Patterns/NameVisitor.elm"])
|
||||
|
@ -218,14 +218,14 @@ moduleRule =
|
||||
moduleVisitor : Rule.ModuleRuleSchema schemaState ModuleContext -> Rule.ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } ModuleContext
|
||||
moduleVisitor schema =
|
||||
schema
|
||||
|> Rule.withExpressionEnterVisitor expressionVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withFinalModuleEvaluation finalEvaluation
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
expressionVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.FunctionOrValue moduleName name ->
|
||||
expressionVisitor : Node Expression -> Rule.Direction -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
expressionVisitor node direction context =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Expression.FunctionOrValue moduleName name ) ->
|
||||
let
|
||||
nameInCode : String
|
||||
nameInCode =
|
||||
|
@ -70,8 +70,8 @@ rule =
|
||||
moduleVisitor : Rule.ModuleRuleSchema schemaState ModuleContext -> Rule.ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } ModuleContext
|
||||
moduleVisitor schema =
|
||||
schema
|
||||
|> Rule.withDeclarationVisitor declarationVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withDeclarationEnterVisitor declarationVisitor
|
||||
|> Rule.withExpressionEnterVisitor expressionVisitor
|
||||
|> Rule.withFinalModuleEvaluation finalEvaluation
|
||||
|
||||
|
||||
@ -134,41 +134,10 @@ foldProjectContexts newContext previousContext =
|
||||
}
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Rule.Direction -> ModuleContext -> ( List (Error {}), ModuleContext )
|
||||
expressionVisitor node direction moduleContext =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Expression.FunctionOrValue moduleName "update" ) ->
|
||||
let
|
||||
realModuleName : List String
|
||||
realModuleName =
|
||||
Scope.moduleNameForValue moduleContext.scope "update" moduleName
|
||||
in
|
||||
if Set.member realModuleName moduleContext.modulesThatExposeSubscriptionsAndUpdate then
|
||||
( [], { moduleContext | usesUpdateOfModule = Dict.insert realModuleName (Node.range node) moduleContext.usesUpdateOfModule } )
|
||||
|
||||
else
|
||||
( [], moduleContext )
|
||||
|
||||
( Rule.OnEnter, Expression.FunctionOrValue moduleName "subscriptions" ) ->
|
||||
let
|
||||
realModuleName : List String
|
||||
realModuleName =
|
||||
Scope.moduleNameForValue moduleContext.scope "subscriptions" moduleName
|
||||
in
|
||||
if Set.member realModuleName moduleContext.modulesThatExposeSubscriptionsAndUpdate then
|
||||
( [], { moduleContext | usesSubscriptionsOfModule = Set.insert realModuleName moduleContext.usesSubscriptionsOfModule } )
|
||||
|
||||
else
|
||||
( [], moduleContext )
|
||||
|
||||
_ ->
|
||||
( [], moduleContext )
|
||||
|
||||
|
||||
declarationVisitor : Node Declaration -> Rule.Direction -> ModuleContext -> ( List (Error nothing), ModuleContext )
|
||||
declarationVisitor declaration direction moduleContext =
|
||||
case ( direction, Node.value declaration ) of
|
||||
( Rule.OnEnter, Declaration.FunctionDeclaration function ) ->
|
||||
declarationVisitor : Node Declaration -> ModuleContext -> ( List (Error nothing), ModuleContext )
|
||||
declarationVisitor node moduleContext =
|
||||
case Node.value node of
|
||||
Declaration.FunctionDeclaration function ->
|
||||
case
|
||||
function.declaration
|
||||
|> Node.value
|
||||
@ -188,6 +157,37 @@ declarationVisitor declaration direction moduleContext =
|
||||
( [], moduleContext )
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> ModuleContext -> ( List (Error {}), ModuleContext )
|
||||
expressionVisitor node moduleContext =
|
||||
case Node.value node of
|
||||
Expression.FunctionOrValue moduleName "update" ->
|
||||
let
|
||||
realModuleName : List String
|
||||
realModuleName =
|
||||
Scope.moduleNameForValue moduleContext.scope "update" moduleName
|
||||
in
|
||||
if Set.member realModuleName moduleContext.modulesThatExposeSubscriptionsAndUpdate then
|
||||
( [], { moduleContext | usesUpdateOfModule = Dict.insert realModuleName (Node.range node) moduleContext.usesUpdateOfModule } )
|
||||
|
||||
else
|
||||
( [], moduleContext )
|
||||
|
||||
Expression.FunctionOrValue moduleName "subscriptions" ->
|
||||
let
|
||||
realModuleName : List String
|
||||
realModuleName =
|
||||
Scope.moduleNameForValue moduleContext.scope "subscriptions" moduleName
|
||||
in
|
||||
if Set.member realModuleName moduleContext.modulesThatExposeSubscriptionsAndUpdate then
|
||||
( [], { moduleContext | usesSubscriptionsOfModule = Set.insert realModuleName moduleContext.usesSubscriptionsOfModule } )
|
||||
|
||||
else
|
||||
( [], moduleContext )
|
||||
|
||||
_ ->
|
||||
( [], moduleContext )
|
||||
|
||||
|
||||
finalEvaluation : ModuleContext -> List (Error {})
|
||||
finalEvaluation moduleContext =
|
||||
moduleContext.usesUpdateOfModule
|
||||
|
@ -55,8 +55,8 @@ To add the rule to your configuration:
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoRecursiveUpdate" { isInUpdateFunction = False }
|
||||
|> Rule.withDeclarationVisitor declarationVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withDeclarationEnterVisitor declarationVisitor
|
||||
|> Rule.withExpressionEnterVisitor expressionVisitor
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
|
||||
@ -65,10 +65,10 @@ type alias Context =
|
||||
}
|
||||
|
||||
|
||||
declarationVisitor : Node Declaration -> Rule.Direction -> Context -> ( List nothing, Context )
|
||||
declarationVisitor declaration direction _ =
|
||||
case ( direction, Node.value declaration ) of
|
||||
( Rule.OnEnter, Declaration.FunctionDeclaration function ) ->
|
||||
declarationVisitor : Node Declaration -> Context -> ( List nothing, Context )
|
||||
declarationVisitor node _ =
|
||||
case Node.value node of
|
||||
Declaration.FunctionDeclaration function ->
|
||||
( []
|
||||
, { isInUpdateFunction =
|
||||
(function.declaration
|
||||
@ -84,11 +84,11 @@ declarationVisitor declaration direction _ =
|
||||
( [], { isInUpdateFunction = False } )
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Rule.Direction -> Context -> ( List (Error {}), Context )
|
||||
expressionVisitor node direction context =
|
||||
expressionVisitor : Node Expression -> Context -> ( List (Error {}), Context )
|
||||
expressionVisitor node context =
|
||||
if context.isInUpdateFunction then
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Expression.FunctionOrValue [] "update" ) ->
|
||||
case Node.value node of
|
||||
Expression.FunctionOrValue [] "update" ->
|
||||
( [ Rule.error
|
||||
{ message = "`update` shouldn't call itself"
|
||||
, details = [ "If you wish to have the same behavior for different messages, move that behavior into a new function and call have it called in the handling of both messages." ]
|
||||
|
@ -20,7 +20,7 @@ import Elm.Syntax.ModuleName exposing (ModuleName)
|
||||
import Elm.Syntax.Node as Node exposing (Node)
|
||||
import Elm.Syntax.Signature exposing (Signature)
|
||||
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
||||
import Review.Rule as Rule exposing (Direction, Error, Rule)
|
||||
import Review.Rule as Rule exposing (Error, Rule)
|
||||
import Scope
|
||||
import Set exposing (Set)
|
||||
|
||||
@ -129,8 +129,8 @@ moduleVisitor schema =
|
||||
schema
|
||||
|> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
|
||||
|> Rule.withDeclarationListVisitor declarationListVisitor
|
||||
|> Rule.withDeclarationVisitor declarationVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withDeclarationEnterVisitor declarationVisitor
|
||||
|> Rule.withExpressionEnterVisitor expressionVisitor
|
||||
|
||||
|
||||
|
||||
@ -385,10 +385,10 @@ register node context =
|
||||
-- DECLARATION VISITOR
|
||||
|
||||
|
||||
declarationVisitor : Node Declaration -> Direction -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
declarationVisitor node direction context =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Declaration.CustomTypeDeclaration { name, constructors } ) ->
|
||||
declarationVisitor : Node Declaration -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
declarationVisitor node context =
|
||||
case Node.value node of
|
||||
Declaration.CustomTypeDeclaration { name, constructors } ->
|
||||
let
|
||||
constructorsForCustomType : Dict String (Node String)
|
||||
constructorsForCustomType =
|
||||
@ -417,7 +417,7 @@ declarationVisitor node direction context =
|
||||
}
|
||||
)
|
||||
|
||||
( Rule.OnEnter, Declaration.FunctionDeclaration function ) ->
|
||||
Declaration.FunctionDeclaration function ->
|
||||
( [], markPhantomTypesFromTypeSignatureAsUsed function.signature context )
|
||||
|
||||
_ ->
|
||||
@ -428,13 +428,13 @@ declarationVisitor node direction context =
|
||||
-- EXPRESSION VISITOR
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Direction -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
expressionVisitor node direction moduleContext =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Expression.FunctionOrValue moduleName name ) ->
|
||||
expressionVisitor : Node Expression -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
expressionVisitor node moduleContext =
|
||||
case Node.value node of
|
||||
Expression.FunctionOrValue moduleName name ->
|
||||
( [], registerUsedFunctionOrValue moduleName name moduleContext )
|
||||
|
||||
( Rule.OnEnter, Expression.LetExpression { declarations } ) ->
|
||||
Expression.LetExpression { declarations } ->
|
||||
( []
|
||||
, declarations
|
||||
|> List.filterMap
|
||||
|
@ -63,7 +63,7 @@ moduleVisitor schema =
|
||||
|> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
|
||||
|> Rule.withImportVisitor importVisitor
|
||||
|> Rule.withDeclarationListVisitor declarationListVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withExpressionEnterVisitor expressionVisitor
|
||||
|
||||
|
||||
|
||||
@ -609,10 +609,10 @@ collectTypesFromTypeAnnotation scope node =
|
||||
-- EXPRESSION VISITOR
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Rule.Direction -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
expressionVisitor node direction moduleContext =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Expression.FunctionOrValue moduleName name ) ->
|
||||
expressionVisitor : Node Expression -> ModuleContext -> ( List nothing, ModuleContext )
|
||||
expressionVisitor node moduleContext =
|
||||
case Node.value node of
|
||||
Expression.FunctionOrValue moduleName name ->
|
||||
( []
|
||||
, registerAsUsed
|
||||
( Scope.moduleNameForValue moduleContext.scope name moduleName, name )
|
||||
|
@ -53,38 +53,54 @@ Value `something` is not used:
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoUnused.Parameters" initialContext
|
||||
|> Rule.withDeclarationVisitor declarationVisitor
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withDeclarationEnterVisitor declarationEnterVisitor
|
||||
|> Rule.withDeclarationExitVisitor declarationExitVisitor
|
||||
|> Rule.withExpressionEnterVisitor expressionEnterVisitor
|
||||
|> Rule.withExpressionExitVisitor expressionExitVisitor
|
||||
|> NameVisitor.withValueVisitor valueVisitor
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
|
||||
declarationVisitor : Node Declaration -> Rule.Direction -> Context -> ( List (Rule.Error {}), Context )
|
||||
declarationVisitor node direction context =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Declaration.FunctionDeclaration { declaration } ) ->
|
||||
declarationEnterVisitor : Node Declaration -> Context -> ( List (Rule.Error {}), Context )
|
||||
declarationEnterVisitor node context =
|
||||
case Node.value node of
|
||||
Declaration.FunctionDeclaration { declaration } ->
|
||||
( [], rememberFunctionImplementation declaration context )
|
||||
|
||||
( Rule.OnExit, Declaration.FunctionDeclaration { declaration } ) ->
|
||||
_ ->
|
||||
( [], context )
|
||||
|
||||
|
||||
declarationExitVisitor : Node Declaration -> Context -> ( List (Rule.Error {}), Context )
|
||||
declarationExitVisitor node context =
|
||||
case Node.value node of
|
||||
Declaration.FunctionDeclaration { declaration } ->
|
||||
errorsForFunctionImplementation declaration context
|
||||
|
||||
_ ->
|
||||
( [], context )
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Rule.Direction -> Context -> ( List (Rule.Error {}), Context )
|
||||
expressionVisitor (Node _ expression) direction context =
|
||||
case ( direction, expression ) of
|
||||
( Rule.OnEnter, Expression.LambdaExpression { args } ) ->
|
||||
expressionEnterVisitor : Node Expression -> Context -> ( List (Rule.Error {}), Context )
|
||||
expressionEnterVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.LambdaExpression { args } ->
|
||||
( [], rememberPatternList args context )
|
||||
|
||||
( Rule.OnExit, Expression.LambdaExpression { args } ) ->
|
||||
errorsForPatternList Lambda args context
|
||||
|
||||
( Rule.OnEnter, Expression.LetExpression { declarations } ) ->
|
||||
Expression.LetExpression { declarations } ->
|
||||
( [], rememberLetDeclarationList declarations context )
|
||||
|
||||
( Rule.OnExit, Expression.LetExpression { declarations } ) ->
|
||||
_ ->
|
||||
( [], context )
|
||||
|
||||
|
||||
expressionExitVisitor : Node Expression -> Context -> ( List (Rule.Error {}), Context )
|
||||
expressionExitVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.LambdaExpression { args } ->
|
||||
errorsForPatternList Lambda args context
|
||||
|
||||
Expression.LetExpression { declarations } ->
|
||||
errorsForLetDeclarationList declarations context
|
||||
|
||||
_ ->
|
||||
|
@ -55,24 +55,32 @@ Value `something` is not used:
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoUnused.Patterns" initialContext
|
||||
|> Rule.withExpressionVisitor expressionVisitor
|
||||
|> Rule.withExpressionEnterVisitor expressionEnterVisitor
|
||||
|> Rule.withExpressionExitVisitor expressionExitVisitor
|
||||
|> NameVisitor.withValueVisitor valueVisitor
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Rule.Direction -> Context -> ( List (Rule.Error {}), Context )
|
||||
expressionVisitor (Node _ expression) direction context =
|
||||
case ( direction, expression ) of
|
||||
( Rule.OnEnter, Expression.LetExpression { declarations } ) ->
|
||||
expressionEnterVisitor : Node Expression -> Context -> ( List (Rule.Error {}), Context )
|
||||
expressionEnterVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.LetExpression { declarations } ->
|
||||
( [], rememberLetDeclarationList declarations context )
|
||||
|
||||
( Rule.OnExit, Expression.LetExpression { declarations } ) ->
|
||||
errorsForLetDeclarationList declarations context
|
||||
|
||||
( Rule.OnEnter, Expression.CaseExpression { cases } ) ->
|
||||
Expression.CaseExpression { cases } ->
|
||||
( [], rememberCaseList cases context )
|
||||
|
||||
( Rule.OnExit, Expression.CaseExpression { cases } ) ->
|
||||
_ ->
|
||||
( [], context )
|
||||
|
||||
|
||||
expressionExitVisitor : Node Expression -> Context -> ( List (Rule.Error {}), Context )
|
||||
expressionExitVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.LetExpression { declarations } ->
|
||||
errorsForLetDeclarationList declarations context
|
||||
|
||||
Expression.CaseExpression { cases } ->
|
||||
errorsForCaseList cases context
|
||||
|
||||
_ ->
|
||||
|
@ -2,14 +2,16 @@ module NoUnused.Patterns.NameVisitor exposing (withValueVisitor)
|
||||
|
||||
{-| Visit each name in the module.
|
||||
|
||||
A "name" is a `Node ( ModuleName, String )` and represents a value or type reference. Here are some value examples:
|
||||
A "name" is a `Node ( ModuleName, String )` and represents a value or type reference. Here are some examples:
|
||||
|
||||
- `Json.Encode.Value` -> `( [ "Json", "Encode" ], "Value" )`
|
||||
- `Html.Attributes.class` -> `( [ "Html", "Attributes" ], "class" )`
|
||||
- `Page` -> `( [], "Page" )`
|
||||
- `view` -> `( [], "view" )`
|
||||
|
||||
These can appear in many places throughout declarations and expressions, and picking them out each time is a lot of work. Instead of writing 1000 lines of code and tests each time, you can write one `nameVisitor` and plug it straight into your module schema, or separate `valueVisitor` and `typeVisitor`s.
|
||||
|
||||
@docs withValueVisitor
|
||||
@docs withNameVisitor, withValueVisitor, withTypeVisitor, withValueAndTypeVisitors
|
||||
|
||||
|
||||
## Scope
|
||||
@ -18,6 +20,11 @@ This makes no attempt to resolve module names from imports, it just returns what
|
||||
|
||||
[elm-review-scope]: http://github.com/jfmengels/elm-review-scope/
|
||||
|
||||
|
||||
## Version
|
||||
|
||||
Version: 0.2.0
|
||||
|
||||
-}
|
||||
|
||||
import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
||||
@ -25,25 +32,148 @@ import Elm.Syntax.Expression as Expression exposing (Expression)
|
||||
import Elm.Syntax.ModuleName exposing (ModuleName)
|
||||
import Elm.Syntax.Node as Node exposing (Node(..))
|
||||
import Elm.Syntax.Pattern as Pattern exposing (Pattern)
|
||||
import Elm.Syntax.Signature exposing (Signature)
|
||||
import Elm.Syntax.Type as Type
|
||||
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
||||
import Review.Rule as Rule exposing (Error)
|
||||
|
||||
|
||||
type Visitor context
|
||||
= NameVisitor (VisitorFunction context)
|
||||
| ValueVisitor (VisitorFunction context)
|
||||
| TypeVisitor (VisitorFunction context)
|
||||
| ValueAndTypeVisitor (VisitorFunction context) (VisitorFunction context)
|
||||
|
||||
|
||||
type alias VisitorFunction context =
|
||||
Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
|
||||
|
||||
type Name
|
||||
= Value (Node ( ModuleName, String ))
|
||||
| Type (Node ( ModuleName, String ))
|
||||
|
||||
|
||||
{-| This will apply the `nameVisitor` to every value and type in the module, you will get no information about whether the name is a value or type.
|
||||
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoInconsistentAliases" initialContext
|
||||
|> NameVisitor.withNameVisitor nameVisitor
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
nameVisitor : Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
nameVisitor node context =
|
||||
-- Do what you want with the name
|
||||
( [], context )
|
||||
|
||||
-}
|
||||
withNameVisitor :
|
||||
(Node ( ModuleName, String ) -> context -> ( List (Error {}), context ))
|
||||
-> Rule.ModuleRuleSchema state context
|
||||
-> Rule.ModuleRuleSchema { state | hasAtLeastOneVisitor : () } context
|
||||
withNameVisitor nameVisitor rule =
|
||||
let
|
||||
visitor =
|
||||
NameVisitor nameVisitor
|
||||
in
|
||||
rule
|
||||
|> Rule.withDeclarationListVisitor (declarationListVisitor visitor)
|
||||
|> Rule.withExpressionEnterVisitor (expressionVisitor visitor)
|
||||
|
||||
|
||||
{-| This will apply the `valueVisitor` to every value in the module, and ignore any types.
|
||||
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoInconsistentAliases" initialContext
|
||||
|> NameVisitor.withValueVisitor valueVisitor
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
valueVisitor : Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
valueVisitor node context =
|
||||
-- Do what you want with the value
|
||||
( [], context )
|
||||
|
||||
-}
|
||||
withValueVisitor :
|
||||
(Node ( ModuleName, String ) -> context -> ( List (Error {}), context ))
|
||||
-> Rule.ModuleRuleSchema state context
|
||||
-> Rule.ModuleRuleSchema { state | hasAtLeastOneVisitor : () } context
|
||||
withValueVisitor valueVisitor rule =
|
||||
let
|
||||
visitor =
|
||||
ValueVisitor valueVisitor
|
||||
in
|
||||
rule
|
||||
|> Rule.withDeclarationListVisitor (declarationListVisitor valueVisitor)
|
||||
|> Rule.withExpressionVisitor (expressionVisitor valueVisitor)
|
||||
|> Rule.withDeclarationListVisitor (declarationListVisitor visitor)
|
||||
|> Rule.withExpressionEnterVisitor (expressionVisitor visitor)
|
||||
|
||||
|
||||
{-| This will apply the `typeVisitor` to every type in the module, and ignore any values.
|
||||
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoInconsistentAliases" initialContext
|
||||
|> NameVisitor.withTypeVisitor typeVisitor
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
typeVisitor : Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
typeVisitor node context =
|
||||
-- Do what you want with the type
|
||||
( [], context )
|
||||
|
||||
-}
|
||||
withTypeVisitor :
|
||||
(Node ( ModuleName, String ) -> context -> ( List (Error {}), context ))
|
||||
-> Rule.ModuleRuleSchema state context
|
||||
-> Rule.ModuleRuleSchema { state | hasAtLeastOneVisitor : () } context
|
||||
withTypeVisitor typeVisitor rule =
|
||||
let
|
||||
visitor =
|
||||
TypeVisitor typeVisitor
|
||||
in
|
||||
rule
|
||||
|> Rule.withDeclarationListVisitor (declarationListVisitor visitor)
|
||||
|> Rule.withExpressionEnterVisitor (expressionVisitor visitor)
|
||||
|
||||
|
||||
{-| This will apply the `valueVisitor` to every value and the `typeVisitor` to every type in the module.
|
||||
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newModuleRuleSchema "NoInconsistentAliases" initialContext
|
||||
|> NameVisitor.withValueAndTypeVisitors
|
||||
{ valueVisitor = valueVisitor
|
||||
, typeVisitor = typeVisitor
|
||||
}
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
valueVisitor : Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
valueVisitor node context =
|
||||
-- Do what you want with the value
|
||||
( [], context )
|
||||
|
||||
typeVisitor : Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
typeVisitor node context =
|
||||
-- Do what you want with the type
|
||||
( [], context )
|
||||
|
||||
-}
|
||||
withValueAndTypeVisitors :
|
||||
{ valueVisitor : Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
, typeVisitor : Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
||||
}
|
||||
-> Rule.ModuleRuleSchema state context
|
||||
-> Rule.ModuleRuleSchema { state | hasAtLeastOneVisitor : () } context
|
||||
withValueAndTypeVisitors { valueVisitor, typeVisitor } rule =
|
||||
let
|
||||
visitor =
|
||||
ValueAndTypeVisitor valueVisitor typeVisitor
|
||||
in
|
||||
rule
|
||||
|> Rule.withDeclarationListVisitor (declarationListVisitor visitor)
|
||||
|> Rule.withExpressionEnterVisitor (expressionVisitor visitor)
|
||||
|
||||
|
||||
|
||||
@ -51,24 +181,17 @@ withValueVisitor valueVisitor rule =
|
||||
|
||||
|
||||
declarationListVisitor :
|
||||
VisitorFunction context
|
||||
Visitor context
|
||||
-> (List (Node Declaration) -> context -> ( List (Error {}), context ))
|
||||
declarationListVisitor visitor list context =
|
||||
visitDeclarationList list
|
||||
|> folder visitor context
|
||||
|
||||
|
||||
expressionVisitor :
|
||||
VisitorFunction context
|
||||
-> (Node Expression -> Rule.Direction -> context -> ( List (Error {}), context ))
|
||||
expressionVisitor visitor node direction context =
|
||||
case direction of
|
||||
Rule.OnEnter ->
|
||||
visitExpression node
|
||||
|> folder visitor context
|
||||
|
||||
Rule.OnExit ->
|
||||
( [], context )
|
||||
expressionVisitor : Visitor context -> (Node Expression -> context -> ( List (Error {}), context ))
|
||||
expressionVisitor visitor node context =
|
||||
visitExpression node
|
||||
|> folder visitor context
|
||||
|
||||
|
||||
|
||||
@ -76,7 +199,7 @@ expressionVisitor visitor node direction context =
|
||||
|
||||
|
||||
folder :
|
||||
VisitorFunction context
|
||||
Visitor context
|
||||
-> context
|
||||
-> List Name
|
||||
-> ( List (Error {}), context )
|
||||
@ -85,7 +208,7 @@ folder visitor context list =
|
||||
|
||||
|
||||
folderHelper :
|
||||
VisitorFunction context
|
||||
Visitor context
|
||||
-> Name
|
||||
-> ( List (Error {}), context )
|
||||
-> ( List (Error {}), context )
|
||||
@ -97,9 +220,51 @@ folderHelper visitor name ( errors, context ) =
|
||||
( newErrors ++ errors, newContext )
|
||||
|
||||
|
||||
applyVisitor : VisitorFunction context -> Name -> context -> ( List (Error {}), context )
|
||||
applyVisitor visitor (Value node) context =
|
||||
visitor node context
|
||||
applyVisitor : Visitor context -> Name -> context -> ( List (Error {}), context )
|
||||
applyVisitor visitor name context =
|
||||
case name of
|
||||
Value node ->
|
||||
applyValueVisitor visitor node context
|
||||
|
||||
Type node ->
|
||||
applyTypeVisitor visitor node context
|
||||
|
||||
|
||||
applyValueVisitor : Visitor context -> VisitorFunction context
|
||||
applyValueVisitor visitor =
|
||||
case visitor of
|
||||
NameVisitor function ->
|
||||
function
|
||||
|
||||
ValueVisitor function ->
|
||||
function
|
||||
|
||||
TypeVisitor _ ->
|
||||
noopVisitor
|
||||
|
||||
ValueAndTypeVisitor function _ ->
|
||||
function
|
||||
|
||||
|
||||
applyTypeVisitor : Visitor context -> VisitorFunction context
|
||||
applyTypeVisitor visitor =
|
||||
case visitor of
|
||||
NameVisitor function ->
|
||||
function
|
||||
|
||||
ValueVisitor _ ->
|
||||
noopVisitor
|
||||
|
||||
TypeVisitor function ->
|
||||
function
|
||||
|
||||
ValueAndTypeVisitor _ function ->
|
||||
function
|
||||
|
||||
|
||||
noopVisitor : VisitorFunction context
|
||||
noopVisitor _ context =
|
||||
( [], context )
|
||||
|
||||
|
||||
|
||||
@ -108,24 +273,101 @@ applyVisitor visitor (Value node) context =
|
||||
|
||||
visitDeclarationList : List (Node Declaration) -> List Name
|
||||
visitDeclarationList nodes =
|
||||
List.concatMap visitDeclaration nodes
|
||||
fastConcatMap visitDeclaration nodes
|
||||
|
||||
|
||||
visitDeclaration : Node Declaration -> List Name
|
||||
visitDeclaration node =
|
||||
case Node.value node of
|
||||
Declaration.FunctionDeclaration { declaration } ->
|
||||
visitFunctionImplementation declaration
|
||||
Declaration.FunctionDeclaration { signature, declaration } ->
|
||||
visitMaybeSignature signature
|
||||
++ visitFunctionImplementation declaration
|
||||
|
||||
Declaration.AliasDeclaration { typeAnnotation } ->
|
||||
visitTypeAnnotation typeAnnotation
|
||||
|
||||
Declaration.CustomTypeDeclaration { constructors } ->
|
||||
visitValueConstructorList constructors
|
||||
|
||||
Declaration.PortDeclaration { typeAnnotation } ->
|
||||
visitTypeAnnotation typeAnnotation
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
||||
|
||||
visitMaybeSignature : Maybe (Node Signature) -> List Name
|
||||
visitMaybeSignature maybeNode =
|
||||
case maybeNode of
|
||||
Just node ->
|
||||
visitSignature node
|
||||
|
||||
Nothing ->
|
||||
[]
|
||||
|
||||
|
||||
visitSignature : Node Signature -> List Name
|
||||
visitSignature node =
|
||||
visitTypeAnnotation (node |> Node.value |> .typeAnnotation)
|
||||
|
||||
|
||||
visitFunctionImplementation : Node Expression.FunctionImplementation -> List Name
|
||||
visitFunctionImplementation node =
|
||||
visitPatternList (node |> Node.value |> .arguments)
|
||||
|
||||
|
||||
visitValueConstructorList : List (Node Type.ValueConstructor) -> List Name
|
||||
visitValueConstructorList list =
|
||||
fastConcatMap visitValueConstructor list
|
||||
|
||||
|
||||
visitValueConstructor : Node Type.ValueConstructor -> List Name
|
||||
visitValueConstructor node =
|
||||
visitTypeAnnotationList (node |> Node.value |> .arguments)
|
||||
|
||||
|
||||
visitTypeAnnotationList : List (Node TypeAnnotation) -> List Name
|
||||
visitTypeAnnotationList list =
|
||||
fastConcatMap visitTypeAnnotation list
|
||||
|
||||
|
||||
visitTypeAnnotation : Node TypeAnnotation -> List Name
|
||||
visitTypeAnnotation node =
|
||||
case Node.value node of
|
||||
TypeAnnotation.GenericType _ ->
|
||||
[]
|
||||
|
||||
TypeAnnotation.Typed call types ->
|
||||
visitType call
|
||||
++ visitTypeAnnotationList types
|
||||
|
||||
TypeAnnotation.Unit ->
|
||||
[]
|
||||
|
||||
TypeAnnotation.Tupled list ->
|
||||
visitTypeAnnotationList list
|
||||
|
||||
TypeAnnotation.Record list ->
|
||||
visitRecordFieldList list
|
||||
|
||||
TypeAnnotation.GenericRecord _ list ->
|
||||
visitRecordFieldList (Node.value list)
|
||||
|
||||
TypeAnnotation.FunctionTypeAnnotation argument return ->
|
||||
visitTypeAnnotation argument
|
||||
++ visitTypeAnnotation return
|
||||
|
||||
|
||||
visitRecordFieldList : List (Node TypeAnnotation.RecordField) -> List Name
|
||||
visitRecordFieldList list =
|
||||
fastConcatMap visitRecordField list
|
||||
|
||||
|
||||
visitRecordField : Node TypeAnnotation.RecordField -> List Name
|
||||
visitRecordField node =
|
||||
visitTypeAnnotation (node |> Node.value |> Tuple.second)
|
||||
|
||||
|
||||
visitExpression : Node Expression -> List Name
|
||||
visitExpression (Node range expression) =
|
||||
case expression of
|
||||
@ -150,14 +392,15 @@ visitExpression (Node range expression) =
|
||||
|
||||
visitLetDeclarationList : List (Node Expression.LetDeclaration) -> List Name
|
||||
visitLetDeclarationList list =
|
||||
List.concatMap visitLetDeclaration list
|
||||
fastConcatMap visitLetDeclaration list
|
||||
|
||||
|
||||
visitLetDeclaration : Node Expression.LetDeclaration -> List Name
|
||||
visitLetDeclaration node =
|
||||
case Node.value node of
|
||||
Expression.LetFunction { declaration } ->
|
||||
visitFunctionImplementation declaration
|
||||
Expression.LetFunction { signature, declaration } ->
|
||||
visitMaybeSignature signature
|
||||
++ visitFunctionImplementation declaration
|
||||
|
||||
Expression.LetDestructuring pattern _ ->
|
||||
visitPattern pattern
|
||||
@ -165,7 +408,7 @@ visitLetDeclaration node =
|
||||
|
||||
visitCaseList : List Expression.Case -> List Name
|
||||
visitCaseList list =
|
||||
List.concatMap visitCase list
|
||||
fastConcatMap visitCase list
|
||||
|
||||
|
||||
visitCase : Expression.Case -> List Name
|
||||
@ -175,7 +418,7 @@ visitCase ( pattern, _ ) =
|
||||
|
||||
visitPatternList : List (Node Pattern) -> List Name
|
||||
visitPatternList list =
|
||||
List.concatMap visitPattern list
|
||||
fastConcatMap visitPattern list
|
||||
|
||||
|
||||
visitPattern : Node Pattern -> List Name
|
||||
@ -216,3 +459,17 @@ visitPattern node =
|
||||
visitValue : Node ( ModuleName, String ) -> List Name
|
||||
visitValue node =
|
||||
[ Value node ]
|
||||
|
||||
|
||||
visitType : Node ( ModuleName, String ) -> List Name
|
||||
visitType node =
|
||||
[ Type node ]
|
||||
|
||||
|
||||
|
||||
--- High Performance List
|
||||
|
||||
|
||||
fastConcatMap : (a -> List b) -> List a -> List b
|
||||
fastConcatMap fn =
|
||||
List.foldr (fn >> (++)) []
|
||||
|
@ -57,8 +57,8 @@ rule =
|
||||
|> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
|
||||
|> Rule.withImportVisitor importVisitor
|
||||
|> Rule.withDeclarationEnterVisitor declarationVisitor
|
||||
|> Rule.withExpressionEnterVisitor expressionVisitorOnEnter
|
||||
|> Rule.withExpressionExitVisitor expressionVisitorOnExit
|
||||
|> Rule.withExpressionEnterVisitor expressionEnterVisitor
|
||||
|> Rule.withExpressionExitVisitor expressionExitVisitor
|
||||
|> Rule.withFinalModuleEvaluation finalEvaluation
|
||||
|> Rule.fromModuleRuleSchema
|
||||
|
||||
@ -338,8 +338,8 @@ moduleAliasRange (Node _ { moduleName }) range =
|
||||
{ range | start = (Node.range moduleName).end }
|
||||
|
||||
|
||||
expressionVisitorOnEnter : Node Expression -> Context -> ( List (Error {}), Context )
|
||||
expressionVisitorOnEnter (Node range value) context =
|
||||
expressionEnterVisitor : Node Expression -> Context -> ( List (Error {}), Context )
|
||||
expressionEnterVisitor (Node range value) context =
|
||||
case value of
|
||||
Expression.FunctionOrValue [] name ->
|
||||
( [], markAsUsed name context )
|
||||
@ -404,9 +404,9 @@ expressionVisitorOnEnter (Node range value) context =
|
||||
( [], context )
|
||||
|
||||
|
||||
expressionVisitorOnExit : Node Expression -> Context -> ( List (Error {}), Context )
|
||||
expressionVisitorOnExit (Node _ value) context =
|
||||
case value of
|
||||
expressionExitVisitor : Node Expression -> Context -> ( List (Error {}), Context )
|
||||
expressionExitVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.RecordUpdateExpression expr _ ->
|
||||
( [], markAsUsed (Node.value expr) context )
|
||||
|
||||
|
@ -27,7 +27,7 @@ module Scope exposing
|
||||
|
||||
{- Copied over from https://github.com/jfmengels/elm-review-scope
|
||||
|
||||
Version: 0.2.2
|
||||
Version: 0.3.0
|
||||
|
||||
Copyright (c) 2020, Jeroen Engels
|
||||
All rights reserved.
|
||||
@ -397,26 +397,49 @@ internalAddModuleVisitors schema =
|
||||
(mapInnerModuleContext importVisitor |> pairWithNoErrors)
|
||||
|> Rule.withDeclarationListVisitor
|
||||
(mapInnerModuleContext declarationListVisitor |> pairWithNoErrors)
|
||||
|> Rule.withDeclarationVisitor
|
||||
(\visitedElement direction outerContext ->
|
||||
|> Rule.withDeclarationEnterVisitor
|
||||
(\visitedElement outerContext ->
|
||||
let
|
||||
innerContext : InnerModuleContext
|
||||
innerContext =
|
||||
outerContext.scope
|
||||
|> unboxModule
|
||||
|> declarationVisitor visitedElement direction
|
||||
|> declarationEnterVisitor visitedElement
|
||||
in
|
||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
||||
)
|
||||
|> Rule.withExpressionVisitor
|
||||
(\visitedElement direction outerContext ->
|
||||
|> Rule.withDeclarationExitVisitor
|
||||
(\visitedElement outerContext ->
|
||||
let
|
||||
innerContext : InnerModuleContext
|
||||
innerContext =
|
||||
outerContext.scope
|
||||
|> unboxModule
|
||||
|> popScope visitedElement direction
|
||||
|> expressionVisitor visitedElement direction
|
||||
|> declarationExitVisitor visitedElement
|
||||
in
|
||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
||||
)
|
||||
|> Rule.withExpressionEnterVisitor
|
||||
(\visitedElement outerContext ->
|
||||
let
|
||||
innerContext : InnerModuleContext
|
||||
innerContext =
|
||||
outerContext.scope
|
||||
|> unboxModule
|
||||
|> popScope visitedElement Rule.OnEnter
|
||||
|> expressionEnterVisitor visitedElement
|
||||
in
|
||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
||||
)
|
||||
|> Rule.withExpressionExitVisitor
|
||||
(\visitedElement outerContext ->
|
||||
let
|
||||
innerContext : InnerModuleContext
|
||||
innerContext =
|
||||
outerContext.scope
|
||||
|> unboxModule
|
||||
|> popScope visitedElement Rule.OnExit
|
||||
|> expressionExitVisitor visitedElement
|
||||
in
|
||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
||||
)
|
||||
@ -1021,10 +1044,10 @@ type VariableType
|
||||
| Port
|
||||
|
||||
|
||||
declarationVisitor : Node Declaration -> Rule.Direction -> InnerModuleContext -> InnerModuleContext
|
||||
declarationVisitor declaration direction context =
|
||||
case ( direction, Node.value declaration ) of
|
||||
( Rule.OnEnter, Declaration.FunctionDeclaration function ) ->
|
||||
declarationEnterVisitor : Node Declaration -> InnerModuleContext -> InnerModuleContext
|
||||
declarationEnterVisitor node context =
|
||||
case Node.value node of
|
||||
Declaration.FunctionDeclaration function ->
|
||||
let
|
||||
newScope : Scope
|
||||
newScope =
|
||||
@ -1034,7 +1057,14 @@ declarationVisitor declaration direction context =
|
||||
|> nonemptyList_cons newScope
|
||||
|> updateScope context
|
||||
|
||||
( Rule.OnExit, Declaration.FunctionDeclaration function ) ->
|
||||
_ ->
|
||||
context
|
||||
|
||||
|
||||
declarationExitVisitor : Node Declaration -> InnerModuleContext -> InnerModuleContext
|
||||
declarationExitVisitor node context =
|
||||
case Node.value node of
|
||||
Declaration.FunctionDeclaration _ ->
|
||||
{ context | scopes = nonemptyList_pop context.scopes }
|
||||
|
||||
_ ->
|
||||
@ -1133,10 +1163,10 @@ popScope node direction context =
|
||||
context
|
||||
|
||||
|
||||
expressionVisitor : Node Expression -> Direction -> InnerModuleContext -> InnerModuleContext
|
||||
expressionVisitor (Node _ value) direction context =
|
||||
case ( direction, value ) of
|
||||
( Rule.OnEnter, Expression.LetExpression { declarations, expression } ) ->
|
||||
expressionEnterVisitor : Node Expression -> InnerModuleContext -> InnerModuleContext
|
||||
expressionEnterVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.LetExpression { declarations, expression } ->
|
||||
List.foldl
|
||||
(\declaration scopes ->
|
||||
case Node.value declaration of
|
||||
@ -1161,10 +1191,7 @@ expressionVisitor (Node _ value) direction context =
|
||||
declarations
|
||||
|> updateScope context
|
||||
|
||||
( Rule.OnExit, Expression.LetExpression _ ) ->
|
||||
{ context | scopes = nonemptyList_pop context.scopes }
|
||||
|
||||
( Rule.OnEnter, Expression.CaseExpression caseBlock ) ->
|
||||
Expression.CaseExpression caseBlock ->
|
||||
let
|
||||
cases : List ( Node Expression, Dict String VariableInfo )
|
||||
cases =
|
||||
@ -1187,7 +1214,17 @@ expressionVisitor (Node _ value) direction context =
|
||||
in
|
||||
{ context | scopes = nonemptyList_mapHead (\scope -> { scope | cases = cases }) context.scopes }
|
||||
|
||||
( Rule.OnExit, Expression.CaseExpression caseBlock ) ->
|
||||
_ ->
|
||||
context
|
||||
|
||||
|
||||
expressionExitVisitor : Node Expression -> InnerModuleContext -> InnerModuleContext
|
||||
expressionExitVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.LetExpression _ ->
|
||||
{ context | scopes = nonemptyList_pop context.scopes }
|
||||
|
||||
Expression.CaseExpression _ ->
|
||||
{ context | scopes = nonemptyList_mapHead (\scope -> { scope | cases = [] }) context.scopes }
|
||||
|
||||
_ ->
|
||||
@ -1220,10 +1257,10 @@ A value can be either a function, a constant, a custom type constructor or a typ
|
||||
|
||||
If the element was defined in the current module, then the result will be `[]`.
|
||||
|
||||
expressionVisitor : Node Expression -> Direction -> Context -> ( List (Error {}), Context )
|
||||
expressionVisitor node direction context =
|
||||
case ( direction, Node.value node ) of
|
||||
( Rule.OnEnter, Expression.FunctionOrValue moduleName "button" ) ->
|
||||
expressionVisitor : Node Expression -> Context -> ( List (Error {}), Context )
|
||||
expressionVisitor node context =
|
||||
case Node.value node of
|
||||
Expression.FunctionOrValue moduleName "button" ->
|
||||
if Scope.moduleNameForValue context.scope "button" moduleName == [ "Html" ] then
|
||||
( [ createError node ], context )
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user