Separate visitors into Enter and Exit types

This commit is contained in:
Jeroen Engels 2017-01-08 15:31:17 +01:00
parent 9ebb4ac7d4
commit 5e25a994cb
5 changed files with 75 additions and 51 deletions

103
Lint.elm
View File

@ -1,7 +1,14 @@
module Lint exposing (lint, LintRule, Error, doNothing)
module Lint
exposing
( lint
, LintRule
, Error
, doNothing
)
import Ast.Expression exposing (..)
import Ast.Statement exposing (..)
import Node exposing (..)
type alias Error =
@ -9,7 +16,7 @@ type alias Error =
type alias LintImplementation nodeType context =
context -> nodeType -> ( List Error, context )
context -> Direction nodeType -> ( List Error, context )
type alias LintRule context =
@ -29,17 +36,21 @@ doNothing ctx _ =
( [], ctx )
expressionVisitor : Expression -> Visitor context
createExitAndEnterWithChildren : (Direction nodeType -> Visitor context) -> nodeType -> List (Visitor context) -> List (Visitor context)
createExitAndEnterWithChildren toVisitor node children =
List.concat
[ [ toVisitor (Enter node) ]
, children
, [ toVisitor (Exit node) ]
]
expressionVisitor : Direction Expression -> Visitor context
expressionVisitor node rule context =
rule.expressionFn context node
typeVisitor : Type -> Visitor context
typeVisitor node rule context =
rule.typeFn context node
statementVisitor : Statement -> Visitor context
statementVisitor : Direction Statement -> Visitor context
statementVisitor node rule context =
rule.statementFn context node
@ -47,24 +58,24 @@ statementVisitor node rule context =
expressionToVisitors : Expression -> List (Visitor context)
expressionToVisitors node =
let
visitAndTransformChildren children =
List.concat
[ [ expressionVisitor node ]
, List.concatMap expressionToVisitors children
]
children =
case node of
Application expression1 expression2 ->
[ expression1, expression2 ]
Access expression names ->
[ expression ]
Variable _ ->
[]
_ ->
[]
childrenVisitors =
List.concatMap expressionToVisitors children
in
case node of
Application expression1 expression2 ->
visitAndTransformChildren [ expression1, expression2 ]
Access expression names ->
visitAndTransformChildren [ expression ]
Variable _ ->
[ expressionVisitor node ]
_ ->
[]
createExitAndEnterWithChildren expressionVisitor node childrenVisitors
typeToVisitors : Type -> List (Visitor context)
@ -72,28 +83,32 @@ typeToVisitors node =
[]
statementChildrenToVisitors : List Expression -> List Type -> List (Visitor context)
statementChildrenToVisitors expressions types =
List.concat
[ List.concatMap expressionToVisitors expressions
, List.concatMap typeToVisitors types
]
statementToVisitors : Statement -> List (Visitor context)
statementToVisitors node =
let
visitAndTransformChildren expressions types =
List.concat
[ [ statementVisitor node ]
, List.concatMap expressionToVisitors expressions
, List.concatMap typeToVisitors types
]
childrenVisitors =
case node of
FunctionTypeDeclaration name application ->
statementChildrenToVisitors [] [ application ]
FunctionDeclaration name params body ->
statementChildrenToVisitors [ body ] []
ModuleDeclaration name exportSet ->
statementChildrenToVisitors [] []
_ ->
[]
in
case node of
FunctionTypeDeclaration name application ->
visitAndTransformChildren [] [ application ]
FunctionDeclaration name params body ->
visitAndTransformChildren [ body ] []
ModuleDeclaration name exportSet ->
visitAndTransformChildren [] []
_ ->
[]
createExitAndEnterWithChildren statementVisitor node childrenVisitors
visitAndAccumulate : LintRule context -> Visitor context -> ( List Error, context ) -> ( List Error, context )

6
Node.elm Normal file
View File

@ -0,0 +1,6 @@
module Node exposing (..)
type Direction node
= Enter node
| Exit node

View File

@ -1,6 +1,7 @@
module FindNoAnnotatedFunction exposing (rule)
import Lint exposing (LintRule, Error, doNothing)
import Node exposing (..)
import Ast.Statement exposing (..)
@ -18,13 +19,13 @@ rule =
}
statementFn : Context -> Statement -> ( List Error, Context )
statementFn : Context -> Direction Statement -> ( List Error, Context )
statementFn ctx node =
case node of
FunctionTypeDeclaration name application ->
Enter (FunctionTypeDeclaration name application) ->
( [], { ctx | annotatedFunctions = name :: ctx.annotatedFunctions } )
FunctionDeclaration name params body ->
Enter (FunctionDeclaration name params body) ->
if List.member name ctx.annotatedFunctions then
( [], ctx )
else

View File

@ -1,6 +1,7 @@
module NoDebug exposing (rule)
import Lint exposing (LintRule, Error, doNothing)
import Node exposing (..)
import Ast.Expression exposing (..)
@ -17,10 +18,10 @@ rule =
}
expressionFn : Context -> Expression -> ( List Error, Context )
expressionFn : Context -> Direction Expression -> ( List Error, Context )
expressionFn ctx node =
case node of
Variable vars ->
Enter (Variable vars) ->
if List.member "Debug" vars then
( [ "Forbidden use of Debug" ], ctx )
else

View File

@ -1,6 +1,7 @@
module NoExposingEverything exposing (rule)
import Lint exposing (LintRule, Error, doNothing)
import Node exposing (..)
import Ast.Statement exposing (..)
@ -17,10 +18,10 @@ rule =
}
statementFn : Context -> Statement -> ( List Error, Context )
statementFn : Context -> Direction Statement -> ( List Error, Context )
statementFn ctx node =
case node of
ModuleDeclaration names AllExport ->
Enter (ModuleDeclaration names AllExport) ->
case names of
[ name ] ->
( [ "Do not expose everything from module " ++ name ++ " using (..)" ], ctx )