Remove previous Rule implementation

This commit is contained in:
Jeroen Engels 2019-06-24 00:41:40 +02:00
parent 9923ec0368
commit f0b1733e8b
3 changed files with 1 additions and 496 deletions

View File

@ -1,8 +1,6 @@
module Lint exposing
( Rule, Severity(..)
, lintSource
, lint, expressionVisitor
, createRule
)
{-| A linter for Elm.
@ -35,15 +33,10 @@ To run the rules on a source code and get a list of errors:
@docs Rule, Severity
# Implementation
# Linting
@docs lintSource
# Rule creation functions
@docs lint, expressionVisitor
-}
import Elm.Parser as Parser
@ -53,8 +46,6 @@ import Elm.Syntax.File exposing (File)
import Elm.Syntax.Node exposing (Node)
import Lint.Direction exposing (Direction)
import Lint.Error as Error exposing (Error)
import Lint.NodeToVisitor exposing (createVisitorsForFile, expressionToVisitors)
import Lint.Rule as Rule exposing (Implementation, Visitor)
import Lint.RuleError as RuleError exposing (RuleError)
@ -120,69 +111,3 @@ parseSource source =
|> Result.mapError (\error -> [ "Parsing error" ])
-- TODO Add all files to have more context https://package.elm-lang.org/packages/stil4m/elm-syntax/7.0.2/Elm-Processing
|> Result.map (process init)
{-| Lints source code using a given rule implementation, and gives back a list of errors that were found.
rule : Rule
rule input =
lint input implementation
implementation : Implementation Context
implementation =
{ typeFn = doNothing
, expressionVisitor = expressionVisitor
, visitEnd = \ctx -> ( [], ctx )
, initialContext = Context
}
-}
lint : Implementation context -> File -> List Error
lint rule file =
createVisitorsForFile file
|> lintWithVisitors rule
{-| Visit an expression using a sub rule implementation. The use of this function is not encouraged, but it can make
part of the implementation of complex rules much easier. It gives back a list of errors and a context.
expressionVisitor : Context -> Direction Expression -> ( List Lint.Error.Error, Context )
expressionVisitor ctx node =
case node of
Enter (Case expr patterns) ->
expressionVisitor subimplementation expr
_ ->
( [], ctx )
subimplementation : Implementation Subcontext
subimplementation =
{ statementFn = doNothing
, typeFn = doNothing
, expressionVisitor = subvisitExpression
, visitEnd = \ctx -> ( [], ctx )
, initialContext = Subcontext
}
-}
expressionVisitor : Implementation context -> Node Expression -> ( List Error, context )
expressionVisitor rule expression =
expressionToVisitors expression
|> List.foldl (visitAndAccumulate rule) ( [], Rule.initialContext rule )
visitAndAccumulate : Implementation context -> Visitor context -> ( List Error, context ) -> ( List Error, context )
visitAndAccumulate rule visitor ( errors, ctx ) =
let
( newErrors, newContext ) =
visitor rule ctx
in
( List.reverse newErrors ++ errors, newContext )
lintWithVisitors : Implementation context -> List (Visitor context) -> List Error
lintWithVisitors rule visitors =
visitors
|> List.foldl (visitAndAccumulate rule) ( [], Rule.initialContext rule )
|> Tuple.first
|> List.reverse

View File

@ -1,207 +0,0 @@
module Lint.NodeToVisitor exposing (createVisitorsForFile, expressionToVisitors)
import Elm.Syntax.Declaration exposing (Declaration(..))
import Elm.Syntax.Expression exposing (Expression(..), Function, FunctionImplementation, LetDeclaration(..))
import Elm.Syntax.File exposing (File)
import Elm.Syntax.Import exposing (Import)
import Elm.Syntax.Infix exposing (InfixDirection(..))
import Elm.Syntax.Module exposing (Module)
import Elm.Syntax.Node exposing (Node, value)
import Elm.Syntax.TypeAnnotation exposing (TypeAnnotation(..))
import Lint.Direction as Direction exposing (Direction)
import Lint.Rule exposing (Visitor, evaluateDeclaration, evaluateExpression, evaluateImport, evaluateModuleDefinition, finalEvaluation)
createExitAndEnterWithChildren : (Direction -> nodeType -> Visitor context) -> nodeType -> List (Visitor context) -> List (Visitor context)
createExitAndEnterWithChildren toVisitor node children =
List.concat
[ [ toVisitor Direction.Enter node ]
, children
, [ toVisitor Direction.Exit node ]
]
moduleVisitor : Visitor context
moduleVisitor rule context =
( finalEvaluation rule context, context )
moduleDefinitionVisitor : Node Module -> Visitor context
moduleDefinitionVisitor node rule context =
evaluateModuleDefinition rule context node
importVisitor : Node Import -> Visitor context
importVisitor node rule context =
evaluateImport rule context node
expressionVisitor : Direction -> Node Expression -> Visitor context
expressionVisitor direction node rule context =
evaluateExpression rule context direction node
declarationVisitor : Direction -> Node Declaration -> Visitor context
declarationVisitor direction node rule context =
evaluateDeclaration rule context direction node
functionToExpression : Function -> Node Expression
functionToExpression { documentation, signature, declaration } =
let
{ name, arguments, expression } =
value declaration
in
expression
expressionToVisitors : Node Expression -> List (Visitor context)
expressionToVisitors node =
let
children : List (Node Expression)
children =
case value node of
Application expressions ->
expressions
Literal _ ->
[]
Integer _ ->
[]
Floatable _ ->
[]
UnitExpr ->
[]
ListExpr elements ->
elements
FunctionOrValue _ _ ->
[]
RecordExpr fields ->
List.map (value >> (\( name, expr ) -> expr)) fields
RecordUpdateExpression name setters ->
List.map (value >> (\( field, expr ) -> expr)) setters
ParenthesizedExpression expr ->
[ expr ]
Operator name ->
[]
OperatorApplication operator direction left right ->
case direction of
Left ->
[ left, right ]
Right ->
[ right, left ]
Non ->
[ left, right ]
IfBlock cond then_ else_ ->
[ cond, then_, else_ ]
LetExpression { expression, declarations } ->
List.map
(\declaration ->
case value declaration of
LetFunction function ->
functionToExpression function
LetDestructuring pattern expr ->
expr
)
declarations
++ [ expression ]
CaseExpression { expression, cases } ->
[ expression ]
++ List.map (\( pattern, caseExpression ) -> caseExpression) cases
LambdaExpression { args, expression } ->
[ expression ]
TupledExpression expressions ->
expressions
PrefixOperator name ->
[]
Hex _ ->
[]
Negation expr ->
[ expr ]
CharLiteral _ ->
[]
RecordAccess expr property ->
[ expr ]
RecordAccessFunction name ->
[]
GLSLExpression expr ->
[]
childrenVisitors =
List.concatMap expressionToVisitors children
in
createExitAndEnterWithChildren expressionVisitor node childrenVisitors
declarationToVisitors : Node Declaration -> List (Visitor context)
declarationToVisitors node =
let
childrenVisitors =
case value node of
FunctionDeclaration function ->
functionToExpression function |> expressionToVisitors
CustomTypeDeclaration _ ->
[]
AliasDeclaration { typeAnnotation } ->
[]
Destructuring pattern expr ->
expressionToVisitors expr
PortDeclaration _ ->
[]
InfixDeclaration _ ->
[]
in
createExitAndEnterWithChildren declarationVisitor node childrenVisitors
declarationsIntoVisitors : List (Node Declaration) -> List (Visitor context)
declarationsIntoVisitors declarations =
List.concatMap declarationToVisitors declarations
importsIntoVisitors : List (Node Import) -> List (Visitor context)
importsIntoVisitors imports =
List.map importVisitor imports
moduleDefinitionIntoVisitor : Node Module -> Visitor context
moduleDefinitionIntoVisitor moduleNode =
moduleDefinitionVisitor moduleNode
createVisitorsForFile : File -> List (Visitor context)
createVisitorsForFile file =
[ moduleDefinitionIntoVisitor file.moduleDefinition ]
++ importsIntoVisitors file.imports
++ declarationsIntoVisitors file.declarations
++ [ moduleVisitor ]

View File

@ -1,213 +0,0 @@
module Lint.Rule exposing
( Implementation
, create, createSimple
, withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation
, withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor
, evaluateDeclaration, evaluateExpression, evaluateImport, evaluateModuleDefinition, finalEvaluation, initialContext
, Visitor
)
{-| This module contains functions that are used for writing rules.
# Definition
@docs Implementation
# Writing rules
@docs create, createSimple
@docs withModuleDefinitionVisitor, withImportVisitor, withExpressionVisitor, withDeclarationVisitor, withFinalEvaluation
@docs withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleExpressionVisitor, withSimpleDeclarationVisitor
# ACCESS
@docs evaluateDeclaration, evaluateExpression, evaluateImport, evaluateModuleDefinition, finalEvaluation, initialContext
# Internal types
@docs Visitor
-}
import Elm.Syntax.Declaration exposing (Declaration)
import Elm.Syntax.Expression exposing (Expression)
import Elm.Syntax.File exposing (File)
import Elm.Syntax.Import exposing (Import)
import Elm.Syntax.Module exposing (Module)
import Elm.Syntax.Node exposing (Node)
import Elm.Syntax.TypeAnnotation exposing (TypeAnnotation)
import Lint.Direction as Direction exposing (Direction)
import Lint.Error exposing (Error)
{-| A Implementation is the implementation of a rule. It is a record that contains:
- initialContext: An initial context
- expression: A LintImplementation for Expression nodes
- visitEnd: A function that takes a context and returns a list of error. Similar to a LintImplementation, but will
be called after visiting the whole AST.
import Lint exposing (Rule)
import Lint.Rule as Rule
type alias Context =
{ numberOfImports : Int
}
rule : Rule
rule input =
lint input implementation
implementation : Rule.Implementation Context
implementation =
Rule.create { numberOfImports = 0 }
|> Rule.withImportVisitor importVisitor
-}
type Implementation context
= Implementation
{ initialContext : context
, moduleDefinitionVisitor : context -> Node Module -> ( List Error, context )
, importVisitor : context -> Node Import -> ( List Error, context )
, expressionVisitor : context -> Direction -> Node Expression -> ( List Error, context )
, declarationVisitor : context -> Direction -> Node Declaration -> ( List Error, context )
, finalEvaluationFn : context -> List Error
}
-- RULE CONSTRUCTOR AND BUILDERS
-- RULES WITH ANALYSES
create : context -> Implementation context
create initialContext_ =
Implementation
{ initialContext = initialContext_
, moduleDefinitionVisitor = \context node -> ( [], context )
, importVisitor = \context node -> ( [], context )
, expressionVisitor = \context direction node -> ( [], context )
, declarationVisitor = \context direction node -> ( [], context )
, finalEvaluationFn = \context -> []
}
withModuleDefinitionVisitor : (context -> Node Module -> ( List Error, context )) -> Implementation context -> Implementation context
withModuleDefinitionVisitor visitor (Implementation impl) =
Implementation { impl | moduleDefinitionVisitor = visitor }
withImportVisitor : (context -> Node Import -> ( List Error, context )) -> Implementation context -> Implementation context
withImportVisitor visitor (Implementation impl) =
Implementation { impl | importVisitor = visitor }
withExpressionVisitor : (context -> Direction -> Node Expression -> ( List Error, context )) -> Implementation context -> Implementation context
withExpressionVisitor visitor (Implementation impl) =
Implementation { impl | expressionVisitor = visitor }
withDeclarationVisitor : (context -> Direction -> Node Declaration -> ( List Error, context )) -> Implementation context -> Implementation context
withDeclarationVisitor visitor (Implementation impl) =
Implementation { impl | declarationVisitor = visitor }
withFinalEvaluation : (context -> List Error) -> Implementation context -> Implementation context
withFinalEvaluation visitor (Implementation impl) =
Implementation { impl | finalEvaluationFn = visitor }
-- RULES WITHOUT ANALYSIS
createSimple : Implementation ()
createSimple =
create ()
withSimpleModuleDefinitionVisitor : (Node Module -> List Error) -> Implementation context -> Implementation context
withSimpleModuleDefinitionVisitor visitor (Implementation impl) =
Implementation { impl | moduleDefinitionVisitor = \context node -> ( visitor node, context ) }
withSimpleImportVisitor : (Node Import -> List Error) -> Implementation context -> Implementation context
withSimpleImportVisitor visitor (Implementation impl) =
Implementation { impl | importVisitor = \context node -> ( visitor node, context ) }
withSimpleExpressionVisitor : (Node Expression -> List Error) -> Implementation context -> Implementation context
withSimpleExpressionVisitor visitor (Implementation impl) =
Implementation
{ impl
| expressionVisitor =
\context direction node ->
case direction of
Direction.Enter ->
( visitor node, context )
Direction.Exit ->
( [], context )
}
withSimpleDeclarationVisitor : (Node Declaration -> List Error) -> Implementation context -> Implementation context
withSimpleDeclarationVisitor visitor (Implementation impl) =
Implementation
{ impl
| declarationVisitor =
\context direction node ->
case direction of
Direction.Enter ->
( visitor node, context )
Direction.Exit ->
( [], context )
}
-- ACCESS
initialContext : Implementation context -> context
initialContext (Implementation impl) =
impl.initialContext
evaluateModuleDefinition : Implementation context -> context -> Node Module -> ( List Error, context )
evaluateModuleDefinition (Implementation impl) =
impl.moduleDefinitionVisitor
evaluateImport : Implementation context -> context -> Node Import -> ( List Error, context )
evaluateImport (Implementation impl) =
impl.importVisitor
evaluateExpression : Implementation context -> context -> Direction -> Node Expression -> ( List Error, context )
evaluateExpression (Implementation impl) =
impl.expressionVisitor
evaluateDeclaration : Implementation context -> context -> Direction -> Node Declaration -> ( List Error, context )
evaluateDeclaration (Implementation impl) =
impl.declarationVisitor
finalEvaluation : Implementation context -> context -> List Error
finalEvaluation (Implementation impl) =
impl.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 Visitor context =
Implementation context -> context -> ( List Error, context )