From c1dd42bde9c0feb7d926145785c37d03376b0bc4 Mon Sep 17 00:00:00 2001 From: Jeroen Engels Date: Mon, 24 Jun 2019 00:00:14 +0200 Subject: [PATCH] Add `fromSchema` in new Rule file --- src/Lint/Internal/DeclarationVisitor.elm | 24 ++- src/Lint/Internal/Visit.elm | 32 ---- src/Lint/Rule2.elm | 181 ++++++++++------------- 3 files changed, 88 insertions(+), 149 deletions(-) delete mode 100644 src/Lint/Internal/Visit.elm diff --git a/src/Lint/Internal/DeclarationVisitor.elm b/src/Lint/Internal/DeclarationVisitor.elm index 388b97d1..74d58d23 100644 --- a/src/Lint/Internal/DeclarationVisitor.elm +++ b/src/Lint/Internal/DeclarationVisitor.elm @@ -7,22 +7,18 @@ import Lint.Direction as Direction exposing (Direction) import Lint.Error exposing (Error) import Lint.Internal.Accumulate exposing (accumulate, accumulateList) import Lint.Internal.ExpressionVisitor as ExpressionVisitor -import Lint.Rule2 as Rule exposing (Rule2) -visit : Rule2 context -> Node Declaration -> context -> ( List Error, context ) -visit rule node context = - let - declarationVisitor : Direction -> Node Declaration -> context -> ( List Error, context ) - declarationVisitor = - Rule.evaluateDeclaration rule - - expressionVisitor : Node Expression -> context -> ( List Error, context ) - expressionVisitor = - ExpressionVisitor.visit (Rule.evaluateExpression rule) - in - declarationVisitor Direction.Enter node context - |> accumulateList expressionVisitor (expressionChildren node) +visit : + (Direction -> Node Declaration -> context -> ( List Error, context )) + -> (Direction -> Node Expression -> context -> ( List Error, context )) + -> Node Declaration + -> context + -> ( List Error, context ) +visit declarationVisitor expressionVisitor node context = + context + |> declarationVisitor Direction.Enter node + |> accumulateList (ExpressionVisitor.visit expressionVisitor) (expressionChildren node) |> accumulate (declarationVisitor Direction.Exit node) diff --git a/src/Lint/Internal/Visit.elm b/src/Lint/Internal/Visit.elm deleted file mode 100644 index 31863373..00000000 --- a/src/Lint/Internal/Visit.elm +++ /dev/null @@ -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 diff --git a/src/Lint/Rule2.elm b/src/Lint/Rule2.elm index 9083a959..ecb18d1c 100644 --- a/src/Lint/Rule2.elm +++ b/src/Lint/Rule2.elm @@ -1,10 +1,8 @@ module Lint.Rule2 exposing - ( Rule2 - , newRuleSchema + ( Rule, Schema + , newRuleSchema, fromSchema , withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor - , withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation - , evaluateDeclaration, evaluateExpression, evaluateImport, evaluateModuleDefinition, finalEvaluation, initialContext - , Visitor2 + , withInitialContext, withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation ) {-| This module contains functions that are used for writing rules. @@ -12,24 +10,14 @@ module Lint.Rule2 exposing # Definition -@docs Rule2 +@docs Rule, Schema # Writing rules -@docs newRuleSchema +@docs newRuleSchema, fromSchema @docs withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor -@docs withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation - - -# ACCESS - -@docs evaluateDeclaration, evaluateExpression, evaluateImport, evaluateModuleDefinition, finalEvaluation, initialContext - - -# Internal types - -@docs Visitor +@docs withInitialContext, withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation -} @@ -42,6 +30,17 @@ import Elm.Syntax.Node exposing (Node) import Elm.Syntax.TypeAnnotation exposing (TypeAnnotation) import Lint.Direction as Direction exposing (Direction) 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. @@ -55,8 +54,8 @@ import Lint.Error exposing (Error) |> Rule.fromSchema -} -type Rule2 context - = Rule2 +type Schema context + = Schema { name : String , initialContext : 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`. -} -newRuleSchema : String -> Rule2 () +newRuleSchema : String -> Schema () newRuleSchema name = - Rule2 + Schema { name = name , initialContext = () , moduleDefinitionVisitor = \node context -> ( [], context ) @@ -82,15 +81,36 @@ newRuleSchema name = } - --- TODO --- fromSchema : Rule2 () -> ... +fromSchema : Schema context -> Rule +fromSchema (Schema schema) = + { 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 -withInitialContext initialContext_ (Rule2 rule) = - Rule2 - { name = rule.name +{-| Concatenate the errors of the previous step and of the last step. +-} +makeFinalEvaluation : (context -> List Error) -> ( List Error, context ) -> List Error +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_ , moduleDefinitionVisitor = \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 -withModuleDefinitionVisitor visitor (Rule2 rule) = - Rule2 { rule | moduleDefinitionVisitor = visitor } +withSimpleModuleDefinitionVisitor : (Node Module -> List Error) -> Schema context -> Schema context +withSimpleModuleDefinitionVisitor visitor (Schema schema) = + Schema { schema | moduleDefinitionVisitor = \node context -> ( visitor node, context ) } -withImportVisitor : (Node Import -> context -> ( List Error, context )) -> Rule2 context -> Rule2 context -withImportVisitor visitor (Rule2 rule) = - Rule2 { rule | importVisitor = visitor } +withSimpleImportVisitor : (Node Import -> List Error) -> Schema context -> Schema context +withSimpleImportVisitor visitor (Schema schema) = + Schema { schema | importVisitor = \node context -> ( visitor node, context ) } -withExpressionVisitor : (Direction -> Node Expression -> context -> ( List Error, context )) -> Rule2 context -> Rule2 context -withExpressionVisitor visitor (Rule2 rule) = - Rule2 { rule | expressionVisitor = visitor } - - -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 +withSimpleExpressionVisitor : (Node Expression -> List Error) -> Schema context -> Schema context +withSimpleExpressionVisitor visitor (Schema schema) = + Schema + { schema | expressionVisitor = \direction node context -> case direction of @@ -154,10 +145,10 @@ withSimpleExpressionVisitor visitor (Rule2 rule) = } -withSimpleDeclarationVisitor : (Node Declaration -> List Error) -> Rule2 context -> Rule2 context -withSimpleDeclarationVisitor visitor (Rule2 rule) = - Rule2 - { rule +withSimpleDeclarationVisitor : (Node Declaration -> List Error) -> Schema context -> Schema context +withSimpleDeclarationVisitor visitor (Schema schema) = + Schema + { schema | declarationVisitor = \direction node context -> case direction of @@ -169,42 +160,26 @@ withSimpleDeclarationVisitor visitor (Rule2 rule) = } - --- ACCESS +withModuleDefinitionVisitor : (Node Module -> context -> ( List Error, context )) -> Schema context -> Schema context +withModuleDefinitionVisitor visitor (Schema schema) = + Schema { schema | moduleDefinitionVisitor = visitor } -initialContext : Rule2 context -> context -initialContext (Rule2 rule) = - rule.initialContext +withImportVisitor : (Node Import -> context -> ( List Error, context )) -> Schema context -> Schema context +withImportVisitor visitor (Schema schema) = + Schema { schema | importVisitor = visitor } -evaluateModuleDefinition : Rule2 context -> Node Module -> context -> ( List Error, context ) -evaluateModuleDefinition (Rule2 rule) = - rule.moduleDefinitionVisitor +withExpressionVisitor : (Direction -> Node Expression -> context -> ( List Error, context )) -> Schema context -> Schema context +withExpressionVisitor visitor (Schema schema) = + Schema { schema | expressionVisitor = visitor } -evaluateImport : Rule2 context -> Node Import -> context -> ( List Error, context ) -evaluateImport (Rule2 rule) = - rule.importVisitor +withDeclarationVisitor : (Direction -> Node Declaration -> context -> ( List Error, context )) -> Schema context -> Schema context +withDeclarationVisitor visitor (Schema schema) = + Schema { schema | declarationVisitor = visitor } -evaluateExpression : Rule2 context -> Direction -> Node Expression -> context -> ( List Error, context ) -evaluateExpression (Rule2 rule) = - rule.expressionVisitor - - -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 ) +withFinalEvaluation : (context -> List Error) -> Schema context -> Schema context +withFinalEvaluation visitor (Schema schema) = + Schema { schema | finalEvaluationFn = visitor }