mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-09-20 20:48:09 +03:00
216 lines
6.1 KiB
Elm
216 lines
6.1 KiB
Elm
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:
|
|
|
|
- `Html.Attributes.class` -> `( [ "Html", "Attributes" ], "class" )`
|
|
- `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
|
|
|
|
|
|
## Scope
|
|
|
|
This makes no attempt to resolve module names from imports, it just returns what's written in the code. It would be trivial to connect [elm-review-scope] with the name visitor if you want to do this.
|
|
|
|
[elm-review-scope]: http://github.com/jfmengels/elm-review-scope/
|
|
|
|
-}
|
|
|
|
import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
|
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 Review.Rule as Rule exposing (Error)
|
|
|
|
|
|
type alias VisitorFunction context =
|
|
Node ( ModuleName, String ) -> context -> ( List (Error {}), context )
|
|
|
|
|
|
type Name
|
|
= Value (Node ( ModuleName, String ))
|
|
|
|
|
|
withValueVisitor :
|
|
(Node ( ModuleName, String ) -> context -> ( List (Error {}), context ))
|
|
-> Rule.ModuleRuleSchema { schemaState | canCollectProjectData : () } context
|
|
-> Rule.ModuleRuleSchema { schemaState | canCollectProjectData : (), hasAtLeastOneVisitor : () } context
|
|
withValueVisitor valueVisitor rule =
|
|
rule
|
|
|> Rule.withDeclarationListVisitor (declarationListVisitor valueVisitor)
|
|
|> Rule.withExpressionVisitor (expressionVisitor valueVisitor)
|
|
|
|
|
|
|
|
--- VISITORS
|
|
|
|
|
|
declarationListVisitor :
|
|
VisitorFunction 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 )
|
|
|
|
|
|
|
|
--- FOLDER
|
|
|
|
|
|
folder :
|
|
VisitorFunction context
|
|
-> (context -> List Name -> ( List (Error {}), context ))
|
|
folder visitor context list =
|
|
case list of
|
|
[] ->
|
|
( [], context )
|
|
|
|
head :: rest ->
|
|
let
|
|
( headErrors, headContext ) =
|
|
applyVisitor visitor head context
|
|
|
|
( restErrors, restContext ) =
|
|
folder visitor headContext rest
|
|
in
|
|
( headErrors ++ restErrors, restContext )
|
|
|
|
|
|
applyVisitor : VisitorFunction context -> Name -> context -> ( List (Error {}), context )
|
|
applyVisitor visitor (Value node) context =
|
|
visitor node context
|
|
|
|
|
|
|
|
--- PRIVATE
|
|
|
|
|
|
visitDeclarationList : List (Node Declaration) -> List Name
|
|
visitDeclarationList nodes =
|
|
List.concatMap visitDeclaration nodes
|
|
|
|
|
|
visitDeclaration : Node Declaration -> List Name
|
|
visitDeclaration node =
|
|
case Node.value node of
|
|
Declaration.FunctionDeclaration { declaration } ->
|
|
visitFunctionImplementation declaration
|
|
|
|
_ ->
|
|
[]
|
|
|
|
|
|
visitFunctionImplementation : Node Expression.FunctionImplementation -> List Name
|
|
visitFunctionImplementation node =
|
|
visitPatternList (node |> Node.value |> .arguments)
|
|
|
|
|
|
visitExpression : Node Expression -> List Name
|
|
visitExpression (Node range expression) =
|
|
case expression of
|
|
Expression.FunctionOrValue moduleName function ->
|
|
visitValue (Node range ( moduleName, function ))
|
|
|
|
Expression.LetExpression { declarations } ->
|
|
visitLetDeclarationList declarations
|
|
|
|
Expression.CaseExpression { cases } ->
|
|
visitCaseList cases
|
|
|
|
Expression.LambdaExpression { args } ->
|
|
visitPatternList args
|
|
|
|
Expression.RecordUpdateExpression name _ ->
|
|
visitValue (Node.map (\function -> ( [], function )) name)
|
|
|
|
_ ->
|
|
[]
|
|
|
|
|
|
visitLetDeclarationList : List (Node Expression.LetDeclaration) -> List Name
|
|
visitLetDeclarationList list =
|
|
List.concatMap visitLetDeclaration list
|
|
|
|
|
|
visitLetDeclaration : Node Expression.LetDeclaration -> List Name
|
|
visitLetDeclaration node =
|
|
case Node.value node of
|
|
Expression.LetFunction { declaration } ->
|
|
visitFunctionImplementation declaration
|
|
|
|
Expression.LetDestructuring pattern _ ->
|
|
visitPattern pattern
|
|
|
|
|
|
visitCaseList : List Expression.Case -> List Name
|
|
visitCaseList list =
|
|
List.concatMap visitCase list
|
|
|
|
|
|
visitCase : Expression.Case -> List Name
|
|
visitCase ( pattern, _ ) =
|
|
visitPattern pattern
|
|
|
|
|
|
visitPatternList : List (Node Pattern) -> List Name
|
|
visitPatternList list =
|
|
List.concatMap visitPattern list
|
|
|
|
|
|
visitPattern : Node Pattern -> List Name
|
|
visitPattern node =
|
|
case Node.value node of
|
|
Pattern.TuplePattern patterns ->
|
|
visitPatternList patterns
|
|
|
|
Pattern.UnConsPattern head rest ->
|
|
visitPattern head ++ visitPattern rest
|
|
|
|
Pattern.ListPattern list ->
|
|
visitPatternList list
|
|
|
|
Pattern.NamedPattern { moduleName, name } _ ->
|
|
let
|
|
{ start } =
|
|
Node.range node
|
|
|
|
newEnd =
|
|
{ start | column = start.column + (name :: moduleName |> String.join "." |> String.length) }
|
|
|
|
range =
|
|
{ start = start, end = newEnd }
|
|
in
|
|
visitValue (Node range ( moduleName, name ))
|
|
|
|
Pattern.AsPattern pattern _ ->
|
|
visitPattern pattern
|
|
|
|
Pattern.ParenthesizedPattern pattern ->
|
|
visitPattern pattern
|
|
|
|
_ ->
|
|
[]
|
|
|
|
|
|
visitValue : Node ( ModuleName, String ) -> List Name
|
|
visitValue node =
|
|
[ Value node ]
|