mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-12-24 18:23:09 +03:00
Call multiple declaration and expression visitors in reverse order on exit
This commit is contained in:
parent
003c38ef5d
commit
97d45987bd
@ -270,12 +270,22 @@ type
|
||||
, moduleDefinitionVisitors : List (Node Module -> context -> ( List Error, context ))
|
||||
, importVisitors : List (Node Import -> context -> ( List Error, context ))
|
||||
, declarationListVisitors : List (List (Node Declaration) -> context -> ( List Error, context ))
|
||||
, declarationVisitors : List (Node Declaration -> Direction -> context -> ( List Error, context ))
|
||||
, expressionVisitors : List (Node Expression -> Direction -> context -> ( List Error, context ))
|
||||
, declarationVisitors : List (DirectedVisitor Declaration context)
|
||||
, expressionVisitors : List (DirectedVisitor Expression context)
|
||||
, finalEvaluationFns : List (context -> List Error)
|
||||
}
|
||||
|
||||
|
||||
type alias DirectedVisitor nodeType context =
|
||||
Node nodeType -> Direction -> context -> ( List Error, context )
|
||||
|
||||
|
||||
type alias InAndOut visitor =
|
||||
{ onEnter : List visitor
|
||||
, onExit : List visitor
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- RULE TYPES
|
||||
|
||||
@ -431,8 +441,6 @@ reverseVisitors (Schema schema) =
|
||||
, moduleDefinitionVisitors = List.reverse schema.moduleDefinitionVisitors
|
||||
, importVisitors = List.reverse schema.importVisitors
|
||||
, declarationListVisitors = List.reverse schema.declarationListVisitors
|
||||
, declarationVisitors = List.reverse schema.declarationVisitors
|
||||
, expressionVisitors = List.reverse schema.expressionVisitors
|
||||
, finalEvaluationFns = List.reverse schema.finalEvaluationFns
|
||||
}
|
||||
|
||||
@ -487,18 +495,33 @@ computeErrors (Schema schema) project =
|
||||
schema.initialContext
|
||||
|> accumulateContext schema.elmJsonVisitors (Review.Project.elmJson project)
|
||||
|> accumulateContext schema.dependenciesVisitors (Review.Project.modules project)
|
||||
|
||||
declarationVisitors : InAndOut (DirectedVisitor Declaration context)
|
||||
declarationVisitors =
|
||||
inAndOut schema.declarationVisitors
|
||||
|
||||
expressionVisitors : InAndOut (DirectedVisitor Expression context)
|
||||
expressionVisitors =
|
||||
inAndOut schema.expressionVisitors
|
||||
in
|
||||
\file ->
|
||||
( [], initialContext )
|
||||
|> accumulateWithListOfVisitors schema.moduleDefinitionVisitors file.ast.moduleDefinition
|
||||
|> accumulateList (visitImport schema.importVisitors) file.ast.imports
|
||||
|> accumulateWithListOfVisitors schema.declarationListVisitors file.ast.declarations
|
||||
|> accumulateList (visitDeclaration schema.declarationVisitors schema.expressionVisitors) file.ast.declarations
|
||||
|> accumulateList (visitDeclaration declarationVisitors expressionVisitors) file.ast.declarations
|
||||
|> makeFinalEvaluation schema.finalEvaluationFns
|
||||
|> List.map (\(Error err) -> Error { err | ruleName = schema.name, filePath = file.path })
|
||||
|> List.reverse
|
||||
|
||||
|
||||
inAndOut : List (DirectedVisitor nodeType context) -> InAndOut (DirectedVisitor nodeType context)
|
||||
inAndOut visitors =
|
||||
{ onEnter = List.reverse visitors
|
||||
, onExit = visitors
|
||||
}
|
||||
|
||||
|
||||
accumulateContext : List (element -> context -> context) -> element -> context -> context
|
||||
accumulateContext visitors element context =
|
||||
List.foldl (\visitor -> visitor element) context visitors
|
||||
@ -540,15 +563,25 @@ newMultiSchema name_ { initialContext, elmJsonVisitors, dependenciesVisitors, fi
|
||||
|
||||
|
||||
visitFileForMulti : Schema ForLookingAtSeveralFiles { hasAtLeastOneVisitor : () } context -> context -> ParsedFile -> ( List Error, context )
|
||||
visitFileForMulti (Schema schema) initialContext file =
|
||||
( []
|
||||
, initialContext
|
||||
|> accumulateContext schema.fileKeyVisitors (FileKey file.path)
|
||||
)
|
||||
|> accumulateWithListOfVisitors schema.moduleDefinitionVisitors file.ast.moduleDefinition
|
||||
|> accumulateList (visitImport schema.importVisitors) file.ast.imports
|
||||
|> accumulateWithListOfVisitors schema.declarationListVisitors file.ast.declarations
|
||||
|> accumulateList (visitDeclaration schema.declarationVisitors schema.expressionVisitors) file.ast.declarations
|
||||
visitFileForMulti (Schema schema) =
|
||||
let
|
||||
declarationVisitors : InAndOut (DirectedVisitor Declaration context)
|
||||
declarationVisitors =
|
||||
inAndOut schema.declarationVisitors
|
||||
|
||||
expressionVisitors : InAndOut (DirectedVisitor Expression context)
|
||||
expressionVisitors =
|
||||
inAndOut schema.expressionVisitors
|
||||
in
|
||||
\initialContext file ->
|
||||
( []
|
||||
, initialContext
|
||||
|> accumulateContext schema.fileKeyVisitors (FileKey file.path)
|
||||
)
|
||||
|> accumulateWithListOfVisitors schema.moduleDefinitionVisitors file.ast.moduleDefinition
|
||||
|> accumulateList (visitImport schema.importVisitors) file.ast.imports
|
||||
|> accumulateWithListOfVisitors schema.declarationListVisitors file.ast.declarations
|
||||
|> accumulateList (visitDeclaration declarationVisitors expressionVisitors) file.ast.declarations
|
||||
|
||||
|
||||
{-| TODO documentation
|
||||
@ -1629,16 +1662,16 @@ visitImport importVisitors node context =
|
||||
|
||||
|
||||
visitDeclaration :
|
||||
List (Node Declaration -> Direction -> context -> ( List Error, context ))
|
||||
-> List (Node Expression -> Direction -> context -> ( List Error, context ))
|
||||
InAndOut (DirectedVisitor Declaration context)
|
||||
-> InAndOut (DirectedVisitor Expression context)
|
||||
-> Node Declaration
|
||||
-> context
|
||||
-> ( List Error, context )
|
||||
visitDeclaration declarationVisitors expressionVisitors node context =
|
||||
( [], context )
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnEnter declarationVisitors node
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnEnter declarationVisitors.onEnter node
|
||||
|> accumulateList (visitExpression expressionVisitors) (expressionsInDeclaration node)
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnExit declarationVisitors node
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnExit declarationVisitors.onExit node
|
||||
|
||||
|
||||
visitNodeWithListOfVisitors :
|
||||
@ -1700,12 +1733,16 @@ expressionsInDeclaration node =
|
||||
[]
|
||||
|
||||
|
||||
visitExpression : List (Node Expression -> Direction -> context -> ( List Error, context )) -> Node Expression -> context -> ( List Error, context )
|
||||
visitExpression :
|
||||
InAndOut (DirectedVisitor Expression context)
|
||||
-> Node Expression
|
||||
-> context
|
||||
-> ( List Error, context )
|
||||
visitExpression visitors node context =
|
||||
( [], context )
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnEnter visitors node
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnEnter visitors.onEnter node
|
||||
|> accumulateList (visitExpression visitors) (expressionChildren node)
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnExit visitors node
|
||||
|> visitNodeWithListOfVisitorsAndDirection OnExit visitors.onExit node
|
||||
|
||||
|
||||
|
||||
|
117
tests/Review/RuleVisitorsOrderTest.elm
Normal file
117
tests/Review/RuleVisitorsOrderTest.elm
Normal file
@ -0,0 +1,117 @@
|
||||
module Review.RuleVisitorsOrderTest exposing (all)
|
||||
|
||||
import Elm.Syntax.Declaration exposing (Declaration)
|
||||
import Elm.Syntax.Expression exposing (Expression)
|
||||
import Elm.Syntax.Node exposing (Node)
|
||||
import Review.Rule as Rule exposing (Rule)
|
||||
import Review.Test exposing (ReviewResult)
|
||||
import Test exposing (Test, test)
|
||||
|
||||
|
||||
type alias Context =
|
||||
String
|
||||
|
||||
|
||||
testRule : Rule -> String -> ReviewResult
|
||||
testRule rule string =
|
||||
"module A exposing (..)\n\n"
|
||||
++ string
|
||||
|> Review.Test.run rule
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
Test.describe "Visitor order"
|
||||
[ test "should call the same type of visitors in order of call on enter, and reverse order on exit (expression)" <|
|
||||
\() ->
|
||||
let
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newSchema "TestRule"
|
||||
|> Rule.withInitialContext ""
|
||||
|> Rule.withExpressionVisitor (declarationVisitor "A")
|
||||
|> Rule.withExpressionVisitor (declarationVisitor "B")
|
||||
|> Rule.withExpressionVisitor (declarationVisitor "C")
|
||||
|> Rule.withFinalEvaluation finalEvaluation
|
||||
|> Rule.fromSchema
|
||||
|
||||
declarationVisitor : String -> Node Expression -> Rule.Direction -> Context -> ( List Rule.Error, Context )
|
||||
declarationVisitor text node direction context =
|
||||
case direction of
|
||||
Rule.OnEnter ->
|
||||
( [], context ++ "\nEnter " ++ text )
|
||||
|
||||
Rule.OnExit ->
|
||||
( [], context ++ "\nExit " ++ text )
|
||||
|
||||
finalEvaluation : Context -> List Rule.Error
|
||||
finalEvaluation context =
|
||||
[ Rule.error { message = context, details = [ "details" ] }
|
||||
{ start = { row = 1, column = 1 }
|
||||
, end = { row = 1, column = 7 }
|
||||
}
|
||||
]
|
||||
in
|
||||
testRule rule """
|
||||
a = 1
|
||||
"""
|
||||
|> Review.Test.expectErrors
|
||||
[ Review.Test.error
|
||||
{ message = """
|
||||
Enter A
|
||||
Enter B
|
||||
Enter C
|
||||
Exit C
|
||||
Exit B
|
||||
Exit A"""
|
||||
, details = [ "details" ]
|
||||
, under = "module"
|
||||
}
|
||||
]
|
||||
, test "should call the same type of visitors in order of call on enter, and reverse order on exit (declaration)" <|
|
||||
\() ->
|
||||
let
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newSchema "TestRule"
|
||||
|> Rule.withInitialContext ""
|
||||
|> Rule.withDeclarationVisitor (declarationVisitor "A")
|
||||
|> Rule.withDeclarationVisitor (declarationVisitor "B")
|
||||
|> Rule.withDeclarationVisitor (declarationVisitor "C")
|
||||
|> Rule.withFinalEvaluation finalEvaluation
|
||||
|> Rule.fromSchema
|
||||
|
||||
declarationVisitor : String -> Node Declaration -> Rule.Direction -> Context -> ( List Rule.Error, Context )
|
||||
declarationVisitor text node direction context =
|
||||
case direction of
|
||||
Rule.OnEnter ->
|
||||
( [], context ++ "\nEnter " ++ text )
|
||||
|
||||
Rule.OnExit ->
|
||||
( [], context ++ "\nExit " ++ text )
|
||||
|
||||
finalEvaluation : Context -> List Rule.Error
|
||||
finalEvaluation context =
|
||||
[ Rule.error { message = context, details = [ "details" ] }
|
||||
{ start = { row = 1, column = 1 }
|
||||
, end = { row = 1, column = 7 }
|
||||
}
|
||||
]
|
||||
in
|
||||
testRule rule """
|
||||
a = 1
|
||||
"""
|
||||
|> Review.Test.expectErrors
|
||||
[ Review.Test.error
|
||||
{ message = """
|
||||
Enter A
|
||||
Enter B
|
||||
Enter C
|
||||
Exit C
|
||||
Exit B
|
||||
Exit A"""
|
||||
, details = [ "details" ]
|
||||
, under = "module"
|
||||
}
|
||||
]
|
||||
]
|
Loading…
Reference in New Issue
Block a user