-
-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Review.Rule.with...Pattern...Visitor
s
#121
Comments
Having a specific visitor for pattern would I think only be useful to detect usages of a type (to find unused ones or to forbid some). Apart from that, I have a hard time finding good use-cases for a generic visitor, because I feel like often the reason why I'm visiting is contextual, and contextual to the expression, or declaration I'm looking at. For instance, I may not visit patterns the same way when destructuring arguments of a function and when I'm looking at the patterns of a case expression. Therefore, I think it could make sense for us to provide something like a visitPattern : (Node Pattern -> a) -> List (Node Pattern) -> a -> a
visitPattern fn nodes acc =
case nodes of
[] -> acc
pattern :: restOfPatterns ->
-- Using your implementation of `patternChildren`
visitPattern fn (patternChildren children ++ restOfPatterns) (fn pattern) and then you can call this function in all the relevant places, depending on the context that you're in (looking at arguments, pattern matches, etc.) I think we could provide something similar for type annotations as well, instead of the proposal in #122. I'd be curious to see whether in practice this fits with what I've done in some of my rules. Because I feel like in some cases the way I visited was different than this proposal or not. I think that would be worth checking when implementing this feature. Then comes the question: And then comes the question: should we provide similar functions for expressions and declarations for consistency? What do you think of this? |
Very neat proposal, might even fit into Doesn't this apply (or doesn't apply) for expressions as well?
hell yes, I've written (or copied) similar functions lots of times For expressions import Elm.Syntax.Expression as Expression exposing (Expression)
import Elm.Syntax.Node as Node exposing (Node(..))
{-| Get all immediate child expressions of an expression.
-}
expressionsInner : Expression -> List (Node Expression)
expressionsInner expression =
case expression of
Expression.UnitExpr ->
[]
Expression.Integer _ ->
[]
Expression.Hex _ ->
[]
Expression.Floatable _ ->
[]
Expression.Literal _ ->
[]
Expression.CharLiteral _ ->
[]
Expression.GLSLExpression _ ->
[]
Expression.RecordAccessFunction _ ->
[]
Expression.FunctionOrValue _ _ ->
[]
Expression.Operator _ ->
[]
Expression.PrefixOperator _ ->
[]
Expression.LambdaExpression lambda ->
[ lambda.expression ]
Expression.RecordAccess record _ ->
[ record ]
Expression.ParenthesizedExpression expression_ ->
[ expression_ ]
Expression.Negation expression_ ->
[ expression_ ]
Expression.OperatorApplication _ _ leftExpression rightExpression ->
[ leftExpression, rightExpression ]
Expression.IfBlock predExpr thenExpr elseExpr ->
[ predExpr, thenExpr, elseExpr ]
Expression.ListExpr expressions ->
expressions
Expression.TupledExpression expressions ->
expressions
Expression.Application expressions ->
expressions
Expression.RecordExpr fields ->
fields |> List.map (\(Node _ ( _, value )) -> value)
Expression.RecordUpdateExpression record updaters ->
(record |> Node.map (FunctionOrValue []))
:: (updaters |> List.map (\(Node _ ( _, newValue )) -> newValue))
Expression.CaseExpression caseBlock ->
caseBlock.expression
:: (caseBlock.cases |> List.map (\( _, expression_ ) -> expression_))
Expression.LetExpression letBlock ->
letBlock.declarations
|> List.map
(\(Node _ letDeclaration) ->
case letDeclaration of
LetFunction { declaration } ->
declaration |> Node.value |> .expression
LetDestructuring _ expression_ ->
expression_
)
|> (::) letBlock.expression |
Potentially yes. It's not something it usually provides though.
I'm really curious why you have felt the need to do that. In my experience, there's very rarely the need to reimplement your own expression visitor. Could you provide some examples for this?
It doesn't need to have special treatment, but there a few reasons among which:
|
Including
Pattern
visitors would be useful to for example forbid tuple patterns, specific named patterns, ...:Review.Rule.withSimplePatternVisitor
Review.Rule.withPatternEnterVisitor
Review.Rule.withPatternExitVisitor
It is currently quite a lot of code and therefore error-prone.
Maybe the code I wrote can help with the implementation just a little 🤷:
The text was updated successfully, but these errors were encountered: