Add fromSchema in new Rule file

This commit is contained in:
Jeroen Engels 2019-06-24 00:00:14 +02:00
parent 8bcb7c64c5
commit c1dd42bde9
3 changed files with 88 additions and 149 deletions

View File

@ -7,22 +7,18 @@ import Lint.Direction as Direction exposing (Direction)
import Lint.Error exposing (Error) import Lint.Error exposing (Error)
import Lint.Internal.Accumulate exposing (accumulate, accumulateList) import Lint.Internal.Accumulate exposing (accumulate, accumulateList)
import Lint.Internal.ExpressionVisitor as ExpressionVisitor import Lint.Internal.ExpressionVisitor as ExpressionVisitor
import Lint.Rule2 as Rule exposing (Rule2)
visit : Rule2 context -> Node Declaration -> context -> ( List Error, context ) visit :
visit rule node context = (Direction -> Node Declaration -> context -> ( List Error, context ))
let -> (Direction -> Node Expression -> context -> ( List Error, context ))
declarationVisitor : Direction -> Node Declaration -> context -> ( List Error, context ) -> Node Declaration
declarationVisitor = -> context
Rule.evaluateDeclaration rule -> ( List Error, context )
visit declarationVisitor expressionVisitor node context =
expressionVisitor : Node Expression -> context -> ( List Error, context ) context
expressionVisitor = |> declarationVisitor Direction.Enter node
ExpressionVisitor.visit (Rule.evaluateExpression rule) |> accumulateList (ExpressionVisitor.visit expressionVisitor) (expressionChildren node)
in
declarationVisitor Direction.Enter node context
|> accumulateList expressionVisitor (expressionChildren node)
|> accumulate (declarationVisitor Direction.Exit node) |> accumulate (declarationVisitor Direction.Exit node)

View File

@ -1,32 +0,0 @@
module Lint.Internal.Visit exposing (applyRule)
import Elm.Syntax.Declaration exposing (Declaration)
import Elm.Syntax.File exposing (File)
import Elm.Syntax.Import exposing (Import)
import Elm.Syntax.Module exposing (Module)
import Elm.Syntax.Node exposing (Node, value)
import Lint.Direction as Direction exposing (Direction)
import Lint.Error exposing (Error)
import Lint.Internal.Accumulate exposing (accumulateList)
import Lint.Internal.DeclarationVisitor as DeclarationVisitor
import Lint.Rule2 as Rule exposing (Rule2)
{-| Applies a `Rule` on a file, and returns the list of errors that it found.
-}
applyRule : Rule2 context -> File -> List Error
applyRule rule file =
Rule.initialContext rule
|> Rule.evaluateModuleDefinition rule file.moduleDefinition
|> accumulateList (Rule.evaluateImport rule) file.imports
|> accumulateList (DeclarationVisitor.visit rule) file.declarations
|> makeFinalEvaluation rule
|> List.reverse
{-| Concatenate the errors of the previous step and of the last step.
-}
makeFinalEvaluation : Rule2 context -> ( List Error, context ) -> List Error
makeFinalEvaluation rule ( previousErrors, previousContext ) =
Rule.finalEvaluation rule previousContext
++ previousErrors

View File

@ -1,10 +1,8 @@
module Lint.Rule2 exposing module Lint.Rule2 exposing
( Rule2 ( Rule, Schema
, newRuleSchema , newRuleSchema, fromSchema
, withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor , withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor
, withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation , withInitialContext, withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation
, evaluateDeclaration, evaluateExpression, evaluateImport, evaluateModuleDefinition, finalEvaluation, initialContext
, Visitor2
) )
{-| This module contains functions that are used for writing rules. {-| This module contains functions that are used for writing rules.
@ -12,24 +10,14 @@ module Lint.Rule2 exposing
# Definition # Definition
@docs Rule2 @docs Rule, Schema
# Writing rules # Writing rules
@docs newRuleSchema @docs newRuleSchema, fromSchema
@docs withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor @docs withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor
@docs withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation @docs withInitialContext, withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation
# ACCESS
@docs evaluateDeclaration, evaluateExpression, evaluateImport, evaluateModuleDefinition, finalEvaluation, initialContext
# Internal types
@docs Visitor
-} -}
@ -42,6 +30,17 @@ import Elm.Syntax.Node exposing (Node)
import Elm.Syntax.TypeAnnotation exposing (TypeAnnotation) import Elm.Syntax.TypeAnnotation exposing (TypeAnnotation)
import Lint.Direction as Direction exposing (Direction) import Lint.Direction as Direction exposing (Direction)
import Lint.Error exposing (Error) import Lint.Error exposing (Error)
import Lint.Internal.Accumulate exposing (accumulate, accumulateList)
import Lint.Internal.DeclarationVisitor as DeclarationVisitor
import Lint.Internal.ExpressionVisitor as ExpressionVisitor
{-| Shortcut to a lint rule
-}
type alias Rule =
{ name : String
, analyze : File -> List Error
}
{-| Represents a `rule` that will be enforced. {-| Represents a `rule` that will be enforced.
@ -55,8 +54,8 @@ import Lint.Error exposing (Error)
|> Rule.fromSchema |> Rule.fromSchema
-} -}
type Rule2 context type Schema context
= Rule2 = Schema
{ name : String { name : String
, initialContext : context , initialContext : context
, moduleDefinitionVisitor : Node Module -> context -> ( List Error, context ) , moduleDefinitionVisitor : Node Module -> context -> ( List Error, context )
@ -69,9 +68,9 @@ type Rule2 context
{-| Creates a new schema for a rule. Will require calling `fromSchema` to create a usable `Rule`. {-| Creates a new schema for a rule. Will require calling `fromSchema` to create a usable `Rule`.
-} -}
newRuleSchema : String -> Rule2 () newRuleSchema : String -> Schema ()
newRuleSchema name = newRuleSchema name =
Rule2 Schema
{ name = name { name = name
, initialContext = () , initialContext = ()
, moduleDefinitionVisitor = \node context -> ( [], context ) , moduleDefinitionVisitor = \node context -> ( [], context )
@ -82,15 +81,36 @@ newRuleSchema name =
} }
fromSchema : Schema context -> Rule
-- TODO fromSchema (Schema schema) =
-- fromSchema : Rule2 () -> ... { name = schema.name
, analyze =
\file ->
schema.initialContext
|> schema.moduleDefinitionVisitor file.moduleDefinition
|> accumulateList schema.importVisitor file.imports
|> accumulateList (DeclarationVisitor.visit schema.declarationVisitor schema.expressionVisitor) file.declarations
|> makeFinalEvaluation schema.finalEvaluationFn
|> List.reverse
}
withInitialContext : context -> Rule2 () -> Rule2 context {-| Concatenate the errors of the previous step and of the last step.
withInitialContext initialContext_ (Rule2 rule) = -}
Rule2 makeFinalEvaluation : (context -> List Error) -> ( List Error, context ) -> List Error
{ name = rule.name makeFinalEvaluation finalEvaluationFn ( previousErrors, previousContext ) =
finalEvaluationFn previousContext
++ previousErrors
-- RULES WITH ANALYSIS
withInitialContext : context -> Schema () -> Schema context
withInitialContext initialContext_ (Schema schema) =
Schema
{ name = schema.name
, initialContext = initialContext_ , initialContext = initialContext_
, moduleDefinitionVisitor = \node context -> ( [], context ) , moduleDefinitionVisitor = \node context -> ( [], context )
, importVisitor = \node context -> ( [], context ) , importVisitor = \node context -> ( [], context )
@ -100,49 +120,20 @@ withInitialContext initialContext_ (Rule2 rule) =
} }
withModuleDefinitionVisitor : (Node Module -> context -> ( List Error, context )) -> Rule2 context -> Rule2 context withSimpleModuleDefinitionVisitor : (Node Module -> List Error) -> Schema context -> Schema context
withModuleDefinitionVisitor visitor (Rule2 rule) = withSimpleModuleDefinitionVisitor visitor (Schema schema) =
Rule2 { rule | moduleDefinitionVisitor = visitor } Schema { schema | moduleDefinitionVisitor = \node context -> ( visitor node, context ) }
withImportVisitor : (Node Import -> context -> ( List Error, context )) -> Rule2 context -> Rule2 context withSimpleImportVisitor : (Node Import -> List Error) -> Schema context -> Schema context
withImportVisitor visitor (Rule2 rule) = withSimpleImportVisitor visitor (Schema schema) =
Rule2 { rule | importVisitor = visitor } Schema { schema | importVisitor = \node context -> ( visitor node, context ) }
withExpressionVisitor : (Direction -> Node Expression -> context -> ( List Error, context )) -> Rule2 context -> Rule2 context withSimpleExpressionVisitor : (Node Expression -> List Error) -> Schema context -> Schema context
withExpressionVisitor visitor (Rule2 rule) = withSimpleExpressionVisitor visitor (Schema schema) =
Rule2 { rule | expressionVisitor = visitor } Schema
{ schema
withDeclarationVisitor : (Direction -> Node Declaration -> context -> ( List Error, context )) -> Rule2 context -> Rule2 context
withDeclarationVisitor visitor (Rule2 rule) =
Rule2 { rule | declarationVisitor = visitor }
withFinalEvaluation : (context -> List Error) -> Rule2 context -> Rule2 context
withFinalEvaluation visitor (Rule2 rule) =
Rule2 { rule | finalEvaluationFn = visitor }
-- RULES WITHOUT ANALYSIS
withSimpleModuleDefinitionVisitor : (Node Module -> List Error) -> Rule2 context -> Rule2 context
withSimpleModuleDefinitionVisitor visitor (Rule2 rule) =
Rule2 { rule | moduleDefinitionVisitor = \node context -> ( visitor node, context ) }
withSimpleImportVisitor : (Node Import -> List Error) -> Rule2 context -> Rule2 context
withSimpleImportVisitor visitor (Rule2 rule) =
Rule2 { rule | importVisitor = \node context -> ( visitor node, context ) }
withSimpleExpressionVisitor : (Node Expression -> List Error) -> Rule2 context -> Rule2 context
withSimpleExpressionVisitor visitor (Rule2 rule) =
Rule2
{ rule
| expressionVisitor = | expressionVisitor =
\direction node context -> \direction node context ->
case direction of case direction of
@ -154,10 +145,10 @@ withSimpleExpressionVisitor visitor (Rule2 rule) =
} }
withSimpleDeclarationVisitor : (Node Declaration -> List Error) -> Rule2 context -> Rule2 context withSimpleDeclarationVisitor : (Node Declaration -> List Error) -> Schema context -> Schema context
withSimpleDeclarationVisitor visitor (Rule2 rule) = withSimpleDeclarationVisitor visitor (Schema schema) =
Rule2 Schema
{ rule { schema
| declarationVisitor = | declarationVisitor =
\direction node context -> \direction node context ->
case direction of case direction of
@ -169,42 +160,26 @@ withSimpleDeclarationVisitor visitor (Rule2 rule) =
} }
withModuleDefinitionVisitor : (Node Module -> context -> ( List Error, context )) -> Schema context -> Schema context
-- ACCESS withModuleDefinitionVisitor visitor (Schema schema) =
Schema { schema | moduleDefinitionVisitor = visitor }
initialContext : Rule2 context -> context withImportVisitor : (Node Import -> context -> ( List Error, context )) -> Schema context -> Schema context
initialContext (Rule2 rule) = withImportVisitor visitor (Schema schema) =
rule.initialContext Schema { schema | importVisitor = visitor }
evaluateModuleDefinition : Rule2 context -> Node Module -> context -> ( List Error, context ) withExpressionVisitor : (Direction -> Node Expression -> context -> ( List Error, context )) -> Schema context -> Schema context
evaluateModuleDefinition (Rule2 rule) = withExpressionVisitor visitor (Schema schema) =
rule.moduleDefinitionVisitor Schema { schema | expressionVisitor = visitor }
evaluateImport : Rule2 context -> Node Import -> context -> ( List Error, context ) withDeclarationVisitor : (Direction -> Node Declaration -> context -> ( List Error, context )) -> Schema context -> Schema context
evaluateImport (Rule2 rule) = withDeclarationVisitor visitor (Schema schema) =
rule.importVisitor Schema { schema | declarationVisitor = visitor }
evaluateExpression : Rule2 context -> Direction -> Node Expression -> context -> ( List Error, context ) withFinalEvaluation : (context -> List Error) -> Schema context -> Schema context
evaluateExpression (Rule2 rule) = withFinalEvaluation visitor (Schema schema) =
rule.expressionVisitor Schema { schema | finalEvaluationFn = visitor }
evaluateDeclaration : Rule2 context -> Direction -> Node Declaration -> context -> ( List Error, context )
evaluateDeclaration (Rule2 rule) =
rule.declarationVisitor
finalEvaluation : Rule2 context -> context -> List Error
finalEvaluation (Rule2 rule) =
rule.finalEvaluationFn
{-| Shorthand for a function that takes a rule's implementation, a context and returns ( List Lint.Error.Error, context ).
A Visitor represents a node and calls the appropriate function for the given node type.
-}
type alias Visitor2 context =
Rule2 context -> context -> ( List Error, context )