mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-08-16 19:40:22 +03:00
Remove Rule3
This commit is contained in:
parent
d2220e652b
commit
4c43013fb8
@ -1,710 +0,0 @@
|
|||||||
module Review.Rule3 exposing
|
|
||||||
( ModuleRuleSchema
|
|
||||||
, ProjectRuleSchema
|
|
||||||
, fromModuleRuleSchema
|
|
||||||
, fromProjectRuleSchema
|
|
||||||
, newModuleRuleSchema
|
|
||||||
, newProjectRuleSchema
|
|
||||||
, review
|
|
||||||
, withContextFromImportedModules
|
|
||||||
, withDeclarationEnterVisitor
|
|
||||||
, withDeclarationExitVisitor
|
|
||||||
, withDeclarationListVisitor
|
|
||||||
, withDependenciesModuleVisitor
|
|
||||||
, withDependenciesProjectVisitor
|
|
||||||
, withElmJsonModuleVisitor
|
|
||||||
, withElmJsonProjectVisitor
|
|
||||||
, withExpressionEnterVisitor
|
|
||||||
, withExpressionExitVisitor
|
|
||||||
, withExpressionVisitor
|
|
||||||
, withFinalModuleEvaluation
|
|
||||||
, withFinalProjectEvaluation
|
|
||||||
, withImportVisitor
|
|
||||||
, withModuleContext
|
|
||||||
, withModuleDefinitionVisitor
|
|
||||||
, withModuleVisitor
|
|
||||||
, withReadmeModuleVisitor
|
|
||||||
, withReadmeProjectVisitor
|
|
||||||
, withSimpleCommentsVisitor
|
|
||||||
, withSimpleDeclarationVisitor
|
|
||||||
, withSimpleExpressionVisitor
|
|
||||||
, withSimpleImportVisitor
|
|
||||||
, withSimpleModuleDefinitionVisitor
|
|
||||||
)
|
|
||||||
|
|
||||||
import Dict exposing (Dict)
|
|
||||||
import Elm.Project
|
|
||||||
import Elm.Syntax.Declaration exposing (Declaration)
|
|
||||||
import Elm.Syntax.Expression exposing (Expression)
|
|
||||||
import Elm.Syntax.Import exposing (Import)
|
|
||||||
import Elm.Syntax.Module exposing (Module)
|
|
||||||
import Elm.Syntax.ModuleName exposing (ModuleName)
|
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
|
||||||
import Elm.Syntax.Range as Range
|
|
||||||
import Review.Context as Context exposing (Context)
|
|
||||||
import Review.Error exposing (ReviewError)
|
|
||||||
import Review.Exceptions as Exceptions
|
|
||||||
import Review.Metadata as Metadata
|
|
||||||
import Review.Project exposing (Project)
|
|
||||||
import Review.Project.Dependency
|
|
||||||
import Review.Project.Internal
|
|
||||||
import Review.Rule
|
|
||||||
exposing
|
|
||||||
( Direction(..)
|
|
||||||
, ElmJsonKey(..)
|
|
||||||
, Error(..)
|
|
||||||
, Forbidden
|
|
||||||
, ModuleKey(..)
|
|
||||||
, ReadmeKey(..)
|
|
||||||
, Required
|
|
||||||
, Rule(..)
|
|
||||||
, TraversalType(..)
|
|
||||||
, duplicateModuleNames
|
|
||||||
, errorToReviewError
|
|
||||||
, parsingError
|
|
||||||
, removeErrorPhantomType
|
|
||||||
)
|
|
||||||
import Review.Visitor exposing (Folder, Visitor)
|
|
||||||
import Vendor.Graph as Graph
|
|
||||||
|
|
||||||
|
|
||||||
type ProjectRuleSchema schemaState projectContext moduleContext
|
|
||||||
= ProjectRuleSchema
|
|
||||||
{ name : String
|
|
||||||
, initialProjectContext : projectContext
|
|
||||||
, elmJsonVisitors : List (Maybe { elmJsonKey : ElmJsonKey, project : Elm.Project.Project } -> projectContext -> ( List (Error {}), projectContext ))
|
|
||||||
, readmeVisitors : List (Maybe { readmeKey : ReadmeKey, content : String } -> projectContext -> ( List (Error {}), projectContext ))
|
|
||||||
, dependenciesVisitors : List (Dict String Review.Project.Dependency.Dependency -> projectContext -> ( List (Error {}), projectContext ))
|
|
||||||
, moduleVisitors : List (ModuleRuleSchema {} moduleContext -> ModuleRuleSchema { hasAtLeastOneVisitor : () } moduleContext)
|
|
||||||
, moduleContextCreator : Maybe (Context projectContext moduleContext)
|
|
||||||
, folder : Maybe (Folder projectContext moduleContext)
|
|
||||||
|
|
||||||
-- TODO Jeroen Only allow to set it if there is a folder, but not several times
|
|
||||||
, traversalType : TraversalType
|
|
||||||
|
|
||||||
-- TODO Jeroen Only allow to set it if there is a folder and module visitors?
|
|
||||||
, finalEvaluationFns : List (projectContext -> List (Error {}))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
newProjectRuleSchema : String -> projectContext -> ProjectRuleSchema { canAddModuleVisitor : (), withModuleContext : Forbidden } projectContext moduleContext
|
|
||||||
newProjectRuleSchema name initialProjectContext =
|
|
||||||
ProjectRuleSchema
|
|
||||||
{ name = name
|
|
||||||
, initialProjectContext = initialProjectContext
|
|
||||||
, elmJsonVisitors = []
|
|
||||||
, readmeVisitors = []
|
|
||||||
, dependenciesVisitors = []
|
|
||||||
, moduleVisitors = []
|
|
||||||
, moduleContextCreator = Nothing
|
|
||||||
, folder = Nothing
|
|
||||||
, traversalType = AllModulesInParallel
|
|
||||||
, finalEvaluationFns = []
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
type ModuleRuleSchema schemaState moduleContext
|
|
||||||
= ModuleRuleSchema
|
|
||||||
{ name : String
|
|
||||||
, initialModuleContext : Maybe moduleContext
|
|
||||||
, moduleContextCreator : Context () moduleContext
|
|
||||||
, moduleDefinitionVisitors : List (Visitor Module moduleContext)
|
|
||||||
, commentsVisitors : List (List (Node String) -> moduleContext -> ( List (Error {}), moduleContext ))
|
|
||||||
, importVisitors : List (Visitor Import moduleContext)
|
|
||||||
, declarationListVisitors : List (List (Node Declaration) -> moduleContext -> ( List (Error {}), moduleContext ))
|
|
||||||
, declarationVisitorsOnEnter : List (Visitor Declaration moduleContext)
|
|
||||||
, declarationVisitorsOnExit : List (Visitor Declaration moduleContext)
|
|
||||||
, expressionVisitorsOnEnter : List (Visitor Expression moduleContext)
|
|
||||||
, expressionVisitorsOnExit : List (Visitor Expression moduleContext)
|
|
||||||
, finalEvaluationFns : List (moduleContext -> List (Error {}))
|
|
||||||
|
|
||||||
-- Project visitors
|
|
||||||
, elmJsonVisitors : List (Maybe Elm.Project.Project -> moduleContext -> moduleContext)
|
|
||||||
, readmeVisitors : List (Maybe String -> moduleContext -> moduleContext)
|
|
||||||
, dependenciesVisitors : List (Dict String Review.Project.Dependency.Dependency -> moduleContext -> moduleContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
withModuleVisitor :
|
|
||||||
(ModuleRuleSchema {} moduleContext -> ModuleRuleSchema { hasAtLeastOneVisitor : () } moduleContext)
|
|
||||||
-> ProjectRuleSchema { projectSchemaState | canAddModuleVisitor : () } projectContext moduleContext
|
|
||||||
-- TODO BREAKING Change: add hasAtLeastOneVisitor : ()
|
|
||||||
-> ProjectRuleSchema { projectSchemaState | canAddModuleVisitor : (), withModuleContext : Required } projectContext moduleContext
|
|
||||||
withModuleVisitor visitor (ProjectRuleSchema schema) =
|
|
||||||
ProjectRuleSchema { schema | moduleVisitors = visitor :: schema.moduleVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
newModuleRuleSchema : String -> moduleContext -> ModuleRuleSchema { canCollectProjectData : () } moduleContext
|
|
||||||
newModuleRuleSchema name initialModuleContext =
|
|
||||||
ModuleRuleSchema
|
|
||||||
{ name = name
|
|
||||||
, initialModuleContext = Just initialModuleContext
|
|
||||||
, moduleContextCreator = Context.init (always initialModuleContext)
|
|
||||||
, moduleDefinitionVisitors = []
|
|
||||||
, commentsVisitors = []
|
|
||||||
, importVisitors = []
|
|
||||||
, declarationListVisitors = []
|
|
||||||
, declarationVisitorsOnEnter = []
|
|
||||||
, declarationVisitorsOnExit = []
|
|
||||||
, expressionVisitorsOnEnter = []
|
|
||||||
, expressionVisitorsOnExit = []
|
|
||||||
, finalEvaluationFns = []
|
|
||||||
, elmJsonVisitors = []
|
|
||||||
, readmeVisitors = []
|
|
||||||
, dependenciesVisitors = []
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
withModuleContext :
|
|
||||||
{ fromProjectToModule : ModuleKey -> Node ModuleName -> projectContext -> moduleContext
|
|
||||||
, fromModuleToProject : ModuleKey -> Node ModuleName -> moduleContext -> projectContext
|
|
||||||
, foldProjectContexts : projectContext -> projectContext -> projectContext
|
|
||||||
}
|
|
||||||
-> ProjectRuleSchema { schemaState | canAddModuleVisitor : (), withModuleContext : Required } projectContext moduleContext
|
|
||||||
-> ProjectRuleSchema { schemaState | hasAtLeastOneVisitor : (), withModuleContext : Forbidden } projectContext moduleContext
|
|
||||||
withModuleContext functions (ProjectRuleSchema schema) =
|
|
||||||
let
|
|
||||||
moduleContextCreator : Context projectContext moduleContext
|
|
||||||
moduleContextCreator =
|
|
||||||
Context.init
|
|
||||||
(\moduleKey metadata projectContext ->
|
|
||||||
functions.fromProjectToModule
|
|
||||||
moduleKey
|
|
||||||
(Metadata.moduleNameNode metadata)
|
|
||||||
projectContext
|
|
||||||
)
|
|
||||||
|> Context.withModuleKey
|
|
||||||
|> Context.withMetadata
|
|
||||||
in
|
|
||||||
ProjectRuleSchema
|
|
||||||
{ schema
|
|
||||||
| moduleContextCreator = Just moduleContextCreator
|
|
||||||
, folder =
|
|
||||||
Just
|
|
||||||
{ fromModuleToProject =
|
|
||||||
Context.init (\moduleKey metadata moduleContext -> functions.fromModuleToProject moduleKey (Metadata.moduleNameNode metadata) moduleContext)
|
|
||||||
|> Context.withModuleKey
|
|
||||||
|> Context.withMetadata
|
|
||||||
, foldProjectContexts = functions.foldProjectContexts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
withContextFromImportedModules : ProjectRuleSchema schemaState projectContext moduleContext -> ProjectRuleSchema schemaState projectContext moduleContext
|
|
||||||
withContextFromImportedModules (ProjectRuleSchema schema) =
|
|
||||||
ProjectRuleSchema { schema | traversalType = ImportedModulesFirst }
|
|
||||||
|
|
||||||
|
|
||||||
{-| Create a [`Rule`](#Rule) from a configured [`ModuleRuleSchema`](#ModuleRuleSchema).
|
|
||||||
-}
|
|
||||||
fromModuleRuleSchema : ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext -> Rule
|
|
||||||
fromModuleRuleSchema ((ModuleRuleSchema schema) as moduleVisitor) =
|
|
||||||
-- TODO BREAKING CHANGE Add canCollectData as a pre-requisite to using fromModuleRuleSchema
|
|
||||||
ProjectRuleSchema
|
|
||||||
{ name = schema.name
|
|
||||||
, initialProjectContext = getInitialContextFromModuleRule moduleVisitor
|
|
||||||
, elmJsonVisitors = compactProjectDataVisitors (Maybe.map .project) schema.elmJsonVisitors
|
|
||||||
, readmeVisitors = compactProjectDataVisitors (Maybe.map .content) schema.readmeVisitors
|
|
||||||
, dependenciesVisitors = compactProjectDataVisitors identity schema.dependenciesVisitors
|
|
||||||
, moduleVisitors = [ removeExtensibleRecordTypeVariable (always moduleVisitor) ]
|
|
||||||
, moduleContextCreator = Just (Context.init identity)
|
|
||||||
, folder = Nothing
|
|
||||||
, traversalType = AllModulesInParallel
|
|
||||||
, finalEvaluationFns = []
|
|
||||||
}
|
|
||||||
|> fromProjectRuleSchema
|
|
||||||
|
|
||||||
|
|
||||||
getInitialContextFromModuleRule : ModuleRuleSchema schemaState moduleContext -> moduleContext
|
|
||||||
getInitialContextFromModuleRule ((ModuleRuleSchema schema) as moduleVisitor) =
|
|
||||||
case schema.initialModuleContext of
|
|
||||||
Just initialModuleContext ->
|
|
||||||
initialModuleContext
|
|
||||||
|
|
||||||
Nothing ->
|
|
||||||
-- Hack: For module rules, we know we will always have a module context
|
|
||||||
-- I am adding a `|>` to prevent TCO from kicking in, so that people get a runtime crash and an report it
|
|
||||||
-- rather than a mysterious.
|
|
||||||
-- Note: People can call this rule on a module rule built in `withModuleVisitor`, which we will prevent
|
|
||||||
-- in the next major version
|
|
||||||
moduleVisitor |> getInitialContextFromModuleRule
|
|
||||||
|
|
||||||
|
|
||||||
compactProjectDataVisitors : (rawData -> data) -> List (data -> moduleContext -> moduleContext) -> List (rawData -> moduleContext -> ( List nothing, moduleContext ))
|
|
||||||
compactProjectDataVisitors getData visitors =
|
|
||||||
if List.isEmpty visitors then
|
|
||||||
[]
|
|
||||||
|
|
||||||
else
|
|
||||||
[ \rawData moduleContext ->
|
|
||||||
let
|
|
||||||
data : data
|
|
||||||
data =
|
|
||||||
getData rawData
|
|
||||||
in
|
|
||||||
( []
|
|
||||||
, List.foldl
|
|
||||||
(\visitor moduleContext_ -> visitor data moduleContext_)
|
|
||||||
moduleContext
|
|
||||||
(List.reverse visitors)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
{-| This function that is supplied by the user will be stored in the `ProjectRuleSchema`,
|
|
||||||
but it contains an extensible record. This means that `ProjectRuleSchema` will
|
|
||||||
need an additional type variable for no useful value. Because we have full control
|
|
||||||
over the `ModuleRuleSchema` in this module, we can change the phantom type to be
|
|
||||||
whatever we want it to be, and we'll change it something that makes sense but
|
|
||||||
without the extensible record type variable.
|
|
||||||
-}
|
|
||||||
removeExtensibleRecordTypeVariable :
|
|
||||||
(ModuleRuleSchema {} moduleContext -> ModuleRuleSchema { a | hasAtLeastOneVisitor : () } moduleContext)
|
|
||||||
-> (ModuleRuleSchema {} moduleContext -> ModuleRuleSchema { hasAtLeastOneVisitor : () } moduleContext)
|
|
||||||
removeExtensibleRecordTypeVariable function =
|
|
||||||
function >> (\(ModuleRuleSchema param) -> ModuleRuleSchema param)
|
|
||||||
|
|
||||||
|
|
||||||
{-| Add a visitor to the [`ModuleRuleSchema`](#ModuleRuleSchema) which will visit the project's
|
|
||||||
[`elm.json`](https://package.elm-lang.org/packages/elm/project-metadata-utils/latest/Elm-Project) file.
|
|
||||||
|
|
||||||
The following example forbids exposing a module in an "Internal" directory in your `elm.json` file.
|
|
||||||
|
|
||||||
import Elm.Module
|
|
||||||
import Elm.Project
|
|
||||||
import Elm.Syntax.Module as Module exposing (Module)
|
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
|
||||||
|
|
||||||
type alias Context =
|
|
||||||
Maybe Elm.Project.Project
|
|
||||||
|
|
||||||
rule : Rule
|
|
||||||
rule =
|
|
||||||
Rule.newModuleRuleSchema "DoNoExposeInternalModules" Nothing
|
|
||||||
|> Rule.withElmJsonModuleVisitor elmJsonVisitor
|
|
||||||
|> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
|
|
||||||
|> Rule.fromModuleRuleSchema
|
|
||||||
|
|
||||||
elmJsonVisitor : Maybe Elm.Project.Project -> Context -> Context
|
|
||||||
elmJsonVisitor elmJson context =
|
|
||||||
elmJson
|
|
||||||
|
|
||||||
moduleDefinitionVisitor : Node Module -> Context -> ( List (Error {}), Context )
|
|
||||||
moduleDefinitionVisitor node context =
|
|
||||||
let
|
|
||||||
moduleName : List String
|
|
||||||
moduleName =
|
|
||||||
Node.value node |> Module.moduleName
|
|
||||||
in
|
|
||||||
if List.member "Internal" moduleName then
|
|
||||||
case context of
|
|
||||||
Just (Elm.Project.Package { exposed }) ->
|
|
||||||
let
|
|
||||||
exposedModules : List String
|
|
||||||
exposedModules =
|
|
||||||
case exposed of
|
|
||||||
Elm.Project.ExposedList names ->
|
|
||||||
names
|
|
||||||
|> List.map Elm.Module.toString
|
|
||||||
|
|
||||||
Elm.Project.ExposedDict fakeDict ->
|
|
||||||
fakeDict
|
|
||||||
|> List.concatMap Tuple.second
|
|
||||||
|> List.map Elm.Module.toString
|
|
||||||
in
|
|
||||||
if List.member (String.join "." moduleName) exposedModules then
|
|
||||||
( [ Rule.error "Do not expose modules in `Internal` as part of the public API" (Node.range node) ], context )
|
|
||||||
|
|
||||||
else
|
|
||||||
( [], context )
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
( [], context )
|
|
||||||
|
|
||||||
else
|
|
||||||
( [], context )
|
|
||||||
|
|
||||||
-}
|
|
||||||
withElmJsonModuleVisitor :
|
|
||||||
(Maybe Elm.Project.Project -> moduleContext -> moduleContext)
|
|
||||||
-> ModuleRuleSchema { schemaState | canCollectProjectData : () } moduleContext
|
|
||||||
-> ModuleRuleSchema { schemaState | canCollectProjectData : () } moduleContext
|
|
||||||
withElmJsonModuleVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | elmJsonVisitors = visitor :: schema.elmJsonVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
{-| Add a visitor to the [`ModuleRuleSchema`](#ModuleRuleSchema) which will visit
|
|
||||||
the project's `README.md` file.
|
|
||||||
-}
|
|
||||||
withReadmeModuleVisitor :
|
|
||||||
(Maybe String -> moduleContext -> moduleContext)
|
|
||||||
-> ModuleRuleSchema { schemaState | canCollectProjectData : () } moduleContext
|
|
||||||
-> ModuleRuleSchema { schemaState | canCollectProjectData : () } moduleContext
|
|
||||||
withReadmeModuleVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | readmeVisitors = visitor :: schema.readmeVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
{-| Add a visitor to the [`ProjectRuleSchema`](#ProjectRuleSchema) which will visit the project's
|
|
||||||
[dependencies](./Review-Project-Dependency).
|
|
||||||
|
|
||||||
You can use this look at the modules contained in dependencies, which can make the rule very precise when it targets
|
|
||||||
specific functions.
|
|
||||||
|
|
||||||
-}
|
|
||||||
withDependenciesModuleVisitor :
|
|
||||||
(Dict String Review.Project.Dependency.Dependency -> moduleContext -> moduleContext)
|
|
||||||
-> ModuleRuleSchema { schemaState | canCollectProjectData : () } moduleContext
|
|
||||||
-> ModuleRuleSchema { schemaState | canCollectProjectData : () } moduleContext
|
|
||||||
withDependenciesModuleVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | dependenciesVisitors = visitor :: schema.dependenciesVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withElmJsonProjectVisitor :
|
|
||||||
(Maybe { elmJsonKey : ElmJsonKey, project : Elm.Project.Project } -> projectContext -> ( List (Error {}), projectContext ))
|
|
||||||
-> ProjectRuleSchema schemaState projectContext moduleContext
|
|
||||||
-> ProjectRuleSchema { schemaState | hasAtLeastOneVisitor : () } projectContext moduleContext
|
|
||||||
withElmJsonProjectVisitor visitor (ProjectRuleSchema projectRuleSchema) =
|
|
||||||
-- TODO BREAKING CHANGE, make elm.json mandatory
|
|
||||||
-- TODO BREAKING CHANGE, Rename to withElmJsonVisitor
|
|
||||||
ProjectRuleSchema { projectRuleSchema | elmJsonVisitors = visitor :: projectRuleSchema.elmJsonVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withReadmeProjectVisitor :
|
|
||||||
(Maybe { readmeKey : ReadmeKey, content : String } -> projectContext -> ( List (Error {}), projectContext ))
|
|
||||||
-> ProjectRuleSchema schemaState projectContext moduleContext
|
|
||||||
-> ProjectRuleSchema { schemaState | hasAtLeastOneVisitor : () } projectContext moduleContext
|
|
||||||
withReadmeProjectVisitor visitor (ProjectRuleSchema projectRuleSchema) =
|
|
||||||
-- TODO BREAKING CHANGE, Rename to withReadmeVisitor
|
|
||||||
ProjectRuleSchema { projectRuleSchema | readmeVisitors = visitor :: projectRuleSchema.readmeVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withDependenciesProjectVisitor :
|
|
||||||
(Dict String Review.Project.Dependency.Dependency -> projectContext -> ( List (Error {}), projectContext ))
|
|
||||||
-> ProjectRuleSchema schemaState projectContext moduleContext
|
|
||||||
-> ProjectRuleSchema { schemaState | hasAtLeastOneVisitor : () } projectContext moduleContext
|
|
||||||
withDependenciesProjectVisitor visitor (ProjectRuleSchema projectRuleSchema) =
|
|
||||||
-- TODO BREAKING CHANGE, Rename to withDependenciesVisitor
|
|
||||||
ProjectRuleSchema { projectRuleSchema | dependenciesVisitors = visitor :: projectRuleSchema.dependenciesVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withFinalProjectEvaluation :
|
|
||||||
(projectContext -> List (Error { useErrorForModule : () }))
|
|
||||||
-> ProjectRuleSchema schemaState projectContext moduleContext
|
|
||||||
-> ProjectRuleSchema { schemaState | hasAtLeastOneVisitor : () } projectContext moduleContext
|
|
||||||
withFinalProjectEvaluation visitor (ProjectRuleSchema projectRuleSchema) =
|
|
||||||
let
|
|
||||||
removeErrorPhantomTypeFromEvaluation : (projectContext -> List (Error b)) -> (projectContext -> List (Error {}))
|
|
||||||
removeErrorPhantomTypeFromEvaluation function projectContext =
|
|
||||||
function projectContext
|
|
||||||
|> List.map removeErrorPhantomType
|
|
||||||
in
|
|
||||||
ProjectRuleSchema { projectRuleSchema | finalEvaluationFns = removeErrorPhantomTypeFromEvaluation visitor :: projectRuleSchema.finalEvaluationFns }
|
|
||||||
|
|
||||||
|
|
||||||
fromProjectRuleSchema : ProjectRuleSchema { schemaState | hasAtLeastOneVisitor : () } projectContext moduleContext -> Rule
|
|
||||||
fromProjectRuleSchema ((ProjectRuleSchema schema) as projectRuleSchema) =
|
|
||||||
Rule
|
|
||||||
{ exceptions = Exceptions.init
|
|
||||||
, ruleImplementation = Review.Visitor.run schema.name (fromProjectRuleSchemaToRunnableProjectVisitor projectRuleSchema) Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fromProjectRuleSchemaToRunnableProjectVisitor : ProjectRuleSchema schemaState projectContext moduleContext -> Review.Visitor.RunnableProjectVisitor projectContext moduleContext
|
|
||||||
fromProjectRuleSchemaToRunnableProjectVisitor (ProjectRuleSchema schema) =
|
|
||||||
{ initialProjectContext = schema.initialProjectContext
|
|
||||||
, elmJsonVisitors = List.reverse schema.elmJsonVisitors
|
|
||||||
, readmeVisitors = List.reverse schema.readmeVisitors
|
|
||||||
, dependenciesVisitors = List.reverse schema.dependenciesVisitors
|
|
||||||
, moduleVisitor = mergeModuleVisitors schema.initialProjectContext schema.moduleContextCreator schema.moduleVisitors
|
|
||||||
, traversalAndFolder =
|
|
||||||
case ( schema.traversalType, schema.folder ) of
|
|
||||||
( AllModulesInParallel, _ ) ->
|
|
||||||
Review.Visitor.TraverseAllModulesInParallel schema.folder
|
|
||||||
|
|
||||||
( ImportedModulesFirst, Just folder ) ->
|
|
||||||
Review.Visitor.TraverseImportedModulesFirst folder
|
|
||||||
|
|
||||||
( ImportedModulesFirst, Nothing ) ->
|
|
||||||
Review.Visitor.TraverseAllModulesInParallel Nothing
|
|
||||||
, finalEvaluationFns = List.reverse schema.finalEvaluationFns
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mergeModuleVisitors :
|
|
||||||
projectContext
|
|
||||||
-> Maybe (Context projectContext moduleContext)
|
|
||||||
-> List (ModuleRuleSchema schemaState1 moduleContext -> ModuleRuleSchema schemaState2 moduleContext)
|
|
||||||
-> Maybe ( Review.Visitor.RunnableModuleVisitor moduleContext, Context projectContext moduleContext )
|
|
||||||
mergeModuleVisitors initialProjectContext maybeModuleContextCreator visitors =
|
|
||||||
case ( maybeModuleContextCreator, List.isEmpty visitors ) of
|
|
||||||
( Nothing, _ ) ->
|
|
||||||
Nothing
|
|
||||||
|
|
||||||
( _, True ) ->
|
|
||||||
Nothing
|
|
||||||
|
|
||||||
( Just moduleContextCreator, False ) ->
|
|
||||||
let
|
|
||||||
dummyAvailableData : Context.AvailableData
|
|
||||||
dummyAvailableData =
|
|
||||||
{ metadata = Metadata.createMetadata { moduleNameNode = Node.Node Range.emptyRange [] }
|
|
||||||
, moduleKey = ModuleKey "dummy"
|
|
||||||
}
|
|
||||||
|
|
||||||
initialModuleContext : moduleContext
|
|
||||||
initialModuleContext =
|
|
||||||
Context.apply dummyAvailableData moduleContextCreator initialProjectContext
|
|
||||||
|
|
||||||
emptyModuleVisitor : ModuleRuleSchema schemaState moduleContext
|
|
||||||
emptyModuleVisitor =
|
|
||||||
ModuleRuleSchema
|
|
||||||
{ name = ""
|
|
||||||
, initialModuleContext = Just initialModuleContext
|
|
||||||
, moduleContextCreator = Context.init (always initialModuleContext)
|
|
||||||
, moduleDefinitionVisitors = []
|
|
||||||
, commentsVisitors = []
|
|
||||||
, importVisitors = []
|
|
||||||
, declarationListVisitors = []
|
|
||||||
, declarationVisitorsOnEnter = []
|
|
||||||
, declarationVisitorsOnExit = []
|
|
||||||
, expressionVisitorsOnEnter = []
|
|
||||||
, expressionVisitorsOnExit = []
|
|
||||||
, finalEvaluationFns = []
|
|
||||||
, elmJsonVisitors = []
|
|
||||||
, readmeVisitors = []
|
|
||||||
, dependenciesVisitors = []
|
|
||||||
}
|
|
||||||
in
|
|
||||||
Just
|
|
||||||
( List.foldl
|
|
||||||
(\addVisitors (ModuleRuleSchema moduleVisitorSchema) ->
|
|
||||||
addVisitors (ModuleRuleSchema moduleVisitorSchema)
|
|
||||||
)
|
|
||||||
emptyModuleVisitor
|
|
||||||
visitors
|
|
||||||
|> fromModuleRuleSchemaToRunnableModuleVisitor
|
|
||||||
, moduleContextCreator
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
fromModuleRuleSchemaToRunnableModuleVisitor : ModuleRuleSchema schemaState moduleContext -> Review.Visitor.RunnableModuleVisitor moduleContext
|
|
||||||
fromModuleRuleSchemaToRunnableModuleVisitor (ModuleRuleSchema schema) =
|
|
||||||
{ moduleDefinitionVisitors = List.reverse schema.moduleDefinitionVisitors
|
|
||||||
, commentsVisitors = List.reverse schema.commentsVisitors
|
|
||||||
, importVisitors = List.reverse schema.importVisitors
|
|
||||||
, declarationListVisitors = List.reverse schema.declarationListVisitors
|
|
||||||
, declarationVisitorsOnEnter = List.reverse schema.declarationVisitorsOnEnter
|
|
||||||
, declarationVisitorsOnExit = schema.declarationVisitorsOnExit
|
|
||||||
, expressionVisitorsOnEnter = List.reverse schema.expressionVisitorsOnEnter
|
|
||||||
, expressionVisitorsOnExit = schema.expressionVisitorsOnExit
|
|
||||||
, finalEvaluationFns = List.reverse schema.finalEvaluationFns
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
withSimpleModuleDefinitionVisitor : (Node Module -> List (Error {})) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withSimpleModuleDefinitionVisitor visitor schema =
|
|
||||||
withModuleDefinitionVisitor (\node moduleContext -> ( visitor node, moduleContext )) schema
|
|
||||||
|
|
||||||
|
|
||||||
withModuleDefinitionVisitor : (Node Module -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withModuleDefinitionVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | moduleDefinitionVisitors = visitor :: schema.moduleDefinitionVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withSimpleCommentsVisitor : (List (Node String) -> List (Error {})) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withSimpleCommentsVisitor visitor schema =
|
|
||||||
withCommentsVisitor (\node moduleContext -> ( visitor node, moduleContext )) schema
|
|
||||||
|
|
||||||
|
|
||||||
withCommentsVisitor : (List (Node String) -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withCommentsVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | commentsVisitors = visitor :: schema.commentsVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withSimpleImportVisitor : (Node Import -> List (Error {})) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withSimpleImportVisitor visitor schema =
|
|
||||||
withImportVisitor (\node moduleContext -> ( visitor node, moduleContext )) schema
|
|
||||||
|
|
||||||
|
|
||||||
withImportVisitor : (Node Import -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withImportVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | importVisitors = visitor :: schema.importVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withSimpleDeclarationVisitor : (Node Declaration -> List (Error {})) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withSimpleDeclarationVisitor visitor schema =
|
|
||||||
withDeclarationEnterVisitor
|
|
||||||
(\node moduleContext -> ( visitor node, moduleContext ))
|
|
||||||
schema
|
|
||||||
|
|
||||||
|
|
||||||
withDeclarationEnterVisitor : (Node Declaration -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withDeclarationEnterVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | declarationVisitorsOnEnter = visitor :: schema.declarationVisitorsOnEnter }
|
|
||||||
|
|
||||||
|
|
||||||
withDeclarationExitVisitor : (Node Declaration -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withDeclarationExitVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | declarationVisitorsOnExit = visitor :: schema.declarationVisitorsOnExit }
|
|
||||||
|
|
||||||
|
|
||||||
withDeclarationListVisitor : (List (Node Declaration) -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withDeclarationListVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | declarationListVisitors = visitor :: schema.declarationListVisitors }
|
|
||||||
|
|
||||||
|
|
||||||
withSimpleExpressionVisitor : (Node Expression -> List (Error {})) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withSimpleExpressionVisitor visitor schema =
|
|
||||||
withExpressionEnterVisitor
|
|
||||||
(\node moduleContext -> ( visitor node, moduleContext ))
|
|
||||||
schema
|
|
||||||
|
|
||||||
|
|
||||||
withExpressionVisitor : (Node Expression -> Direction -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withExpressionVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema
|
|
||||||
{ schema
|
|
||||||
| expressionVisitorsOnEnter = (\node ctx -> visitor node OnEnter ctx) :: schema.expressionVisitorsOnEnter
|
|
||||||
, expressionVisitorsOnExit = (\node ctx -> visitor node OnExit ctx) :: schema.expressionVisitorsOnExit
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
withExpressionEnterVisitor : (Node Expression -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withExpressionEnterVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | expressionVisitorsOnEnter = visitor :: schema.expressionVisitorsOnEnter }
|
|
||||||
|
|
||||||
|
|
||||||
withExpressionExitVisitor : (Node Expression -> moduleContext -> ( List (Error {}), moduleContext )) -> ModuleRuleSchema schemaState moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withExpressionExitVisitor visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | expressionVisitorsOnExit = visitor :: schema.expressionVisitorsOnExit }
|
|
||||||
|
|
||||||
|
|
||||||
withFinalModuleEvaluation : (moduleContext -> List (Error {})) -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext -> ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } moduleContext
|
|
||||||
withFinalModuleEvaluation visitor (ModuleRuleSchema schema) =
|
|
||||||
ModuleRuleSchema { schema | finalEvaluationFns = visitor :: schema.finalEvaluationFns }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- REVIEWING
|
|
||||||
|
|
||||||
|
|
||||||
{-| Review a project and gives back the errors raised by the given rules.
|
|
||||||
|
|
||||||
Note that you won't need to use this function when writing a rule. You should
|
|
||||||
only need it if you try to make `elm-review` run in a new environment.
|
|
||||||
|
|
||||||
import Review.Project as Project exposing (Project, ProjectModule)
|
|
||||||
import Review.Rule as Rule exposing (Rule)
|
|
||||||
|
|
||||||
config : List Rule
|
|
||||||
config =
|
|
||||||
[ Some.Rule.rule
|
|
||||||
, Some.Other.Rule.rule
|
|
||||||
]
|
|
||||||
|
|
||||||
project : Project
|
|
||||||
project =
|
|
||||||
Project.new
|
|
||||||
|> Project.addModule { path = "src/A.elm", source = "module A exposing (a)\na = 1" }
|
|
||||||
|> Project.addModule { path = "src/B.elm", source = "module B exposing (b)\nb = 1" }
|
|
||||||
|
|
||||||
doReview =
|
|
||||||
let
|
|
||||||
( errors, rulesWithCachedValues ) =
|
|
||||||
Rule.review rules project
|
|
||||||
in
|
|
||||||
doSomethingWithTheseValues
|
|
||||||
|
|
||||||
The resulting `List Rule` is the same list of rules given as input, but with an
|
|
||||||
updated internal cache to make it faster to re-run the rules on the same project.
|
|
||||||
If you plan on re-reviewing with the same rules and project, for instance to
|
|
||||||
review the project after a file has changed, you may want to store the rules in
|
|
||||||
your `Model`.
|
|
||||||
|
|
||||||
The rules are functions, so doing so will make your model unable to be
|
|
||||||
exported/imported with `elm/browser`'s debugger, and may cause a crash if you try
|
|
||||||
to compare them or the model that holds them.
|
|
||||||
|
|
||||||
-}
|
|
||||||
review : List Rule -> Project -> ( List ReviewError, List Rule )
|
|
||||||
review rules project =
|
|
||||||
case Review.Project.modulesThatFailedToParse project of
|
|
||||||
[] ->
|
|
||||||
case Review.Project.modules project |> duplicateModuleNames Dict.empty of
|
|
||||||
Just duplicate ->
|
|
||||||
let
|
|
||||||
paths : String
|
|
||||||
paths =
|
|
||||||
duplicate.paths
|
|
||||||
|> List.sort
|
|
||||||
|> List.map (\s -> "\n - " ++ s)
|
|
||||||
|> String.join ""
|
|
||||||
|
|
||||||
moduleNames : String
|
|
||||||
moduleNames =
|
|
||||||
String.join "." duplicate.moduleName
|
|
||||||
in
|
|
||||||
( [ Review.Error.ReviewError
|
|
||||||
{ filePath = "GLOBAL ERROR"
|
|
||||||
, ruleName = "Incorrect project"
|
|
||||||
, message = "Found several modules named `" ++ moduleNames ++ "`"
|
|
||||||
, details =
|
|
||||||
[ "I found several modules with the name `" ++ moduleNames ++ "`. Depending on how I choose to resolve this, I might give you different reports. Since this is a compiler error anyway, I require this problem to be solved. Please fix this then try running `elm-review` again."
|
|
||||||
, "Here are the paths to some of the files that share a module name:" ++ paths
|
|
||||||
, "It is possible that you requested me to look at several projects, and that modules from each project share the same name. I don't recommend reviewing several projects at the same time, as I can only handle one `elm.json`. I instead suggest running `elm-review` twice, once for each project."
|
|
||||||
]
|
|
||||||
, range = { start = { row = 0, column = 0 }, end = { row = 0, column = 0 } }
|
|
||||||
, fixes = Nothing
|
|
||||||
, target = Review.Error.Global
|
|
||||||
}
|
|
||||||
]
|
|
||||||
, rules
|
|
||||||
)
|
|
||||||
|
|
||||||
Nothing ->
|
|
||||||
let
|
|
||||||
sortedModules : Result (Graph.Edge ()) (List (Graph.NodeContext ModuleName ()))
|
|
||||||
sortedModules =
|
|
||||||
project
|
|
||||||
|> Review.Project.Internal.moduleGraph
|
|
||||||
|> Graph.checkAcyclic
|
|
||||||
|> Result.map Graph.topologicalSort
|
|
||||||
in
|
|
||||||
case sortedModules of
|
|
||||||
Err _ ->
|
|
||||||
( [ Review.Error.ReviewError
|
|
||||||
{ filePath = "GLOBAL ERROR"
|
|
||||||
, ruleName = "Incorrect project"
|
|
||||||
, message = "Import cycle discovered"
|
|
||||||
, details =
|
|
||||||
[ "I detected an import cycle in your project. This prevents me from working correctly, and results in a error for the Elm compiler anyway. Please resolve it using the compiler's suggestions, then try running `elm-review` again."
|
|
||||||
]
|
|
||||||
, range = { start = { row = 0, column = 0 }, end = { row = 0, column = 0 } }
|
|
||||||
, fixes = Nothing
|
|
||||||
, target = Review.Error.Global
|
|
||||||
}
|
|
||||||
]
|
|
||||||
, rules
|
|
||||||
)
|
|
||||||
|
|
||||||
Ok nodeContexts ->
|
|
||||||
runRules rules project nodeContexts
|
|
||||||
|> Tuple.mapFirst (List.map errorToReviewError)
|
|
||||||
|
|
||||||
modulesThatFailedToParse ->
|
|
||||||
( List.map parsingError modulesThatFailedToParse, rules )
|
|
||||||
|
|
||||||
|
|
||||||
runRules : List Rule -> Project -> List (Graph.NodeContext ModuleName ()) -> ( List (Error {}), List Rule )
|
|
||||||
runRules rules project nodeContexts =
|
|
||||||
List.foldl
|
|
||||||
(\(Rule { exceptions, ruleImplementation }) ( errors, previousRules ) ->
|
|
||||||
let
|
|
||||||
( ruleErrors, ruleWithCache ) =
|
|
||||||
ruleImplementation exceptions project nodeContexts
|
|
||||||
in
|
|
||||||
( List.concat [ List.map removeErrorPhantomType ruleErrors, errors ], ruleWithCache :: previousRules )
|
|
||||||
)
|
|
||||||
( [], [] )
|
|
||||||
rules
|
|
@ -13,7 +13,6 @@ import Elm.Version
|
|||||||
import Regex exposing (Regex)
|
import Regex exposing (Regex)
|
||||||
import Review.Fix as Fix
|
import Review.Fix as Fix
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports links in the `README.md` that point to this project's package documentation on <https://package.elm-lang.org/>,
|
{-| Reports links in the `README.md` that point to this project's package documentation on <https://package.elm-lang.org/>,
|
||||||
|
@ -5,7 +5,6 @@ import Elm.Syntax.Node as Node exposing (Node)
|
|||||||
import Elm.Syntax.Pattern as Pattern
|
import Elm.Syntax.Pattern as Pattern
|
||||||
import Elm.Syntax.Range exposing (Range)
|
import Elm.Syntax.Range exposing (Range)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
rule : Rule
|
rule : Rule
|
||||||
|
@ -16,7 +16,6 @@ import Elm.Syntax.Expression exposing (Expression(..))
|
|||||||
import Elm.Syntax.Module as Module exposing (Module(..))
|
import Elm.Syntax.Module as Module exposing (Module(..))
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import Elm.Package
|
|||||||
import Elm.Project
|
import Elm.Project
|
||||||
import Elm.Syntax.Range exposing (Range)
|
import Elm.Syntax.Range exposing (Range)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
rule : Rule
|
rule : Rule
|
||||||
|
@ -10,7 +10,6 @@ import Elm.Syntax.Expression as Expression exposing (Expression)
|
|||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Elm.Syntax.Pattern as Pattern exposing (Pattern)
|
import Elm.Syntax.Pattern as Pattern exposing (Pattern)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports when pattern matching is used for a boolean value.
|
{-| Reports when pattern matching is used for a boolean value.
|
||||||
|
@ -11,7 +11,6 @@ import Elm.Syntax.Expression as Expression exposing (Expression)
|
|||||||
import Elm.Syntax.Import exposing (Import)
|
import Elm.Syntax.Import exposing (Import)
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Forbid the use of [`Debug.log`](https://package.elm-lang.org/packages/elm/core/latest/Debug) before it goes into production or fails in the CI.
|
{-| Forbid the use of [`Debug.log`](https://package.elm-lang.org/packages/elm/core/latest/Debug) before it goes into production or fails in the CI.
|
||||||
|
@ -11,7 +11,6 @@ import Elm.Syntax.Expression as Expression exposing (Expression)
|
|||||||
import Elm.Syntax.Import exposing (Import)
|
import Elm.Syntax.Import exposing (Import)
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Forbid the use of [`Debug.todo`] and [`Debug.toString`].
|
{-| Forbid the use of [`Debug.todo`] and [`Debug.toString`].
|
||||||
|
@ -10,7 +10,6 @@ import Elm.Syntax.Exposing as Exposing
|
|||||||
import Elm.Syntax.Module as Module exposing (Module)
|
import Elm.Syntax.Module as Module exposing (Module)
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Forbids exporting everything from a module.
|
{-| Forbids exporting everything from a module.
|
||||||
|
@ -12,7 +12,6 @@ module NoExtraBooleanComparison exposing (rule)
|
|||||||
import Elm.Syntax.Expression as Expression exposing (Expression(..))
|
import Elm.Syntax.Expression as Expression exposing (Expression(..))
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Forbid the use of boolean comparisons that can be simplified.
|
{-| Forbid the use of boolean comparisons that can be simplified.
|
||||||
@ -63,8 +62,8 @@ You should not use this rule if you
|
|||||||
-}
|
-}
|
||||||
rule : Rule
|
rule : Rule
|
||||||
rule =
|
rule =
|
||||||
Rule3.newModuleRuleSchema "NoExtraBooleanComparison" ()
|
Rule.newModuleRuleSchema "NoExtraBooleanComparison" ()
|
||||||
|> Rule3.withSimpleExpressionVisitor expressionVisitor
|
|> Rule.withSimpleExpressionVisitor expressionVisitor
|
||||||
|> Rule.fromModuleRuleSchema
|
|> Rule.fromModuleRuleSchema
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import Elm.Syntax.Expression as Expression exposing (Expression)
|
|||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Elm.Syntax.Range exposing (Range)
|
import Elm.Syntax.Range exposing (Range)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports when an operator is used as a prefix operator and all the operands are already given.
|
{-| Reports when an operator is used as a prefix operator and all the operands are already given.
|
||||||
@ -40,8 +39,8 @@ import Review.Rule3 as Rule3
|
|||||||
-}
|
-}
|
||||||
rule : Rule
|
rule : Rule
|
||||||
rule =
|
rule =
|
||||||
Rule3.newModuleRuleSchema "NoFullyAppliedPrefixOperator" ()
|
Rule.newModuleRuleSchema "NoFullyAppliedPrefixOperator" ()
|
||||||
|> Rule3.withSimpleExpressionVisitor expressionVisitor
|
|> Rule.withSimpleExpressionVisitor expressionVisitor
|
||||||
|> Rule.fromModuleRuleSchema
|
|> Rule.fromModuleRuleSchema
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import Elm.Syntax.Exposing as Exposing
|
|||||||
import Elm.Syntax.Import exposing (Import)
|
import Elm.Syntax.Import exposing (Import)
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ import Elm.Syntax.Node as Node exposing (Node)
|
|||||||
import NoLeftPizzaUtil
|
import NoLeftPizzaUtil
|
||||||
import Review.Fix as Fix
|
import Review.Fix as Fix
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Specify how strict the rule should be.
|
{-| Specify how strict the rule should be.
|
||||||
|
@ -10,7 +10,6 @@ import Elm.Syntax.Expression as Expression exposing (Expression)
|
|||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Elm.Syntax.Range exposing (Range)
|
import Elm.Syntax.Range exposing (Range)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports when an operation on lists could be simplified to a single literal list.
|
{-| Reports when an operation on lists could be simplified to a single literal list.
|
||||||
|
@ -9,7 +9,6 @@ module NoMissingTypeAnnotation exposing (rule)
|
|||||||
import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports top-level declarations that do not have a type annotation.
|
{-| Reports top-level declarations that do not have a type annotation.
|
||||||
|
@ -9,7 +9,6 @@ module NoMissingTypeAnnotationInLetIn exposing (rule)
|
|||||||
import Elm.Syntax.Expression as Expression exposing (Expression)
|
import Elm.Syntax.Expression as Expression exposing (Expression)
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports `let in` declarations that do not have a type annotation.
|
{-| Reports `let in` declarations that do not have a type annotation.
|
||||||
|
@ -10,7 +10,6 @@ import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
|||||||
import Elm.Syntax.Expression as Expression exposing (Expression)
|
import Elm.Syntax.Expression as Expression exposing (Expression)
|
||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports when the `update` function calls itself.
|
{-| Reports when the `update` function calls itself.
|
||||||
|
@ -21,7 +21,6 @@ import Elm.Syntax.Node as Node exposing (Node)
|
|||||||
import Elm.Syntax.Signature exposing (Signature)
|
import Elm.Syntax.Signature exposing (Signature)
|
||||||
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Scope
|
import Scope
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ import Elm.Writer as Writer
|
|||||||
import NoUnused.Patterns.NameVisitor as NameVisitor
|
import NoUnused.Patterns.NameVisitor as NameVisitor
|
||||||
import Review.Fix as Fix
|
import Review.Fix as Fix
|
||||||
import Review.Rule as Rule exposing (Rule)
|
import Review.Rule as Rule exposing (Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ rule =
|
|||||||
|> Rule.withDeclarationExitVisitor declarationExitVisitor
|
|> Rule.withDeclarationExitVisitor declarationExitVisitor
|
||||||
|> Rule.withExpressionEnterVisitor expressionEnterVisitor
|
|> Rule.withExpressionEnterVisitor expressionEnterVisitor
|
||||||
|> Rule.withExpressionExitVisitor expressionExitVisitor
|
|> Rule.withExpressionExitVisitor expressionExitVisitor
|
||||||
|> NameVisitor.withValueVisitor_New valueVisitor
|
|> NameVisitor.withValueVisitor valueVisitor
|
||||||
|> Rule.fromModuleRuleSchema
|
|> Rule.fromModuleRuleSchema
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ import Elm.Writer as Writer
|
|||||||
import NoUnused.Patterns.NameVisitor as NameVisitor
|
import NoUnused.Patterns.NameVisitor as NameVisitor
|
||||||
import Review.Fix as Fix
|
import Review.Fix as Fix
|
||||||
import Review.Rule as Rule exposing (Rule)
|
import Review.Rule as Rule exposing (Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ rule =
|
|||||||
Rule.newModuleRuleSchema "NoUnused.Patterns" initialContext
|
Rule.newModuleRuleSchema "NoUnused.Patterns" initialContext
|
||||||
|> Rule.withExpressionEnterVisitor expressionEnterVisitor
|
|> Rule.withExpressionEnterVisitor expressionEnterVisitor
|
||||||
|> Rule.withExpressionExitVisitor expressionExitVisitor
|
|> Rule.withExpressionExitVisitor expressionExitVisitor
|
||||||
|> NameVisitor.withValueVisitor_New valueVisitor
|
|> NameVisitor.withValueVisitor valueVisitor
|
||||||
|> Rule.fromModuleRuleSchema
|
|> Rule.fromModuleRuleSchema
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
module NoUnused.Patterns.NameVisitor exposing
|
module NoUnused.Patterns.NameVisitor exposing (withValueVisitor)
|
||||||
( withValueVisitor
|
|
||||||
, withValueVisitor_New
|
|
||||||
)
|
|
||||||
|
|
||||||
{-| Visit each name in the module.
|
{-| Visit each name in the module.
|
||||||
|
|
||||||
@ -39,7 +36,6 @@ import Elm.Syntax.Signature exposing (Signature)
|
|||||||
import Elm.Syntax.Type as Type
|
import Elm.Syntax.Type as Type
|
||||||
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
||||||
import Review.Rule as Rule exposing (Error)
|
import Review.Rule as Rule exposing (Error)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
type Visitor context
|
type Visitor context
|
||||||
@ -180,20 +176,6 @@ withValueAndTypeVisitors { valueVisitor, typeVisitor } rule =
|
|||||||
|> Rule.withExpressionEnterVisitor (expressionVisitor visitor)
|
|> Rule.withExpressionEnterVisitor (expressionVisitor visitor)
|
||||||
|
|
||||||
|
|
||||||
withValueVisitor_New :
|
|
||||||
(Node ( ModuleName, String ) -> context -> ( List (Error {}), context ))
|
|
||||||
-> Rule.ModuleRuleSchema state context
|
|
||||||
-> Rule.ModuleRuleSchema { state | hasAtLeastOneVisitor : () } context
|
|
||||||
withValueVisitor_New valueVisitor rule =
|
|
||||||
let
|
|
||||||
visitor =
|
|
||||||
ValueVisitor valueVisitor
|
|
||||||
in
|
|
||||||
rule
|
|
||||||
|> Rule.withDeclarationListVisitor (declarationListVisitor visitor)
|
|
||||||
|> Rule.withExpressionEnterVisitor (expressionVisitor visitor)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- VISITORS
|
--- VISITORS
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
|||||||
import NoUnused.NonemptyList as NonemptyList exposing (Nonempty)
|
import NoUnused.NonemptyList as NonemptyList exposing (Nonempty)
|
||||||
import Review.Fix as Fix exposing (Fix)
|
import Review.Fix as Fix exposing (Fix)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
|||||||
import Elm.Syntax.Expression as Expression
|
import Elm.Syntax.Expression as Expression
|
||||||
import Elm.Syntax.Node as Node exposing (Node(..))
|
import Elm.Syntax.Node as Node exposing (Node(..))
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
|
|
||||||
|
|
||||||
{-| Reports `subscriptions` functions that never return a subscription.
|
{-| Reports `subscriptions` functions that never return a subscription.
|
||||||
@ -45,8 +44,8 @@ that turn out to be unnecessary later.
|
|||||||
-}
|
-}
|
||||||
rule : Rule
|
rule : Rule
|
||||||
rule =
|
rule =
|
||||||
Rule3.newModuleRuleSchema "NoUselessSubscriptions" ()
|
Rule.newModuleRuleSchema "NoUselessSubscriptions" ()
|
||||||
|> Rule3.withSimpleDeclarationVisitor declarationVisitor
|
|> Rule.withSimpleDeclarationVisitor declarationVisitor
|
||||||
|> Rule.fromModuleRuleSchema
|
|> Rule.fromModuleRuleSchema
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import Elm.Syntax.Declaration exposing (Declaration)
|
|||||||
import Elm.Syntax.Expression exposing (Expression)
|
import Elm.Syntax.Expression exposing (Expression)
|
||||||
import Elm.Syntax.Node exposing (Node)
|
import Elm.Syntax.Node exposing (Node)
|
||||||
import Review.Rule as Rule exposing (Error, Rule)
|
import Review.Rule as Rule exposing (Error, Rule)
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Review.Test
|
import Review.Test
|
||||||
import Test exposing (Test, test)
|
import Test exposing (Test, test)
|
||||||
|
|
||||||
|
@ -76,7 +76,6 @@ import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
|
|||||||
import Elm.Type
|
import Elm.Type
|
||||||
import Review.Project.Dependency as Dependency exposing (Dependency)
|
import Review.Project.Dependency as Dependency exposing (Dependency)
|
||||||
import Review.Rule as Rule
|
import Review.Rule as Rule
|
||||||
import Review.Rule3 as Rule3
|
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
|
||||||
|
|
||||||
@ -351,13 +350,13 @@ addProjectVisitors schema =
|
|||||||
|
|
||||||
|
|
||||||
addProjectVisitors_New :
|
addProjectVisitors_New :
|
||||||
Rule3.ProjectRuleSchema { schemaState | canAddModuleVisitor : () } { projectContext | scope : ProjectContext } { moduleContext | scope : ModuleContext }
|
Rule.ProjectRuleSchema { schemaState | canAddModuleVisitor : () } { projectContext | scope : ProjectContext } { moduleContext | scope : ModuleContext }
|
||||||
-> Rule3.ProjectRuleSchema { schemaState | canAddModuleVisitor : (), hasAtLeastOneVisitor : (), withModuleContext : Rule.Required } { projectContext | scope : ProjectContext } { moduleContext | scope : ModuleContext }
|
-> Rule.ProjectRuleSchema { schemaState | canAddModuleVisitor : (), hasAtLeastOneVisitor : (), withModuleContext : Rule.Required } { projectContext | scope : ProjectContext } { moduleContext | scope : ModuleContext }
|
||||||
addProjectVisitors_New schema =
|
addProjectVisitors_New schema =
|
||||||
schema
|
schema
|
||||||
|> Rule3.withContextFromImportedModules
|
|> Rule.withContextFromImportedModules
|
||||||
|> Rule3.withDependenciesProjectVisitor (mapInnerProjectContext dependenciesProjectVisitor)
|
|> Rule.withDependenciesProjectVisitor (mapInnerProjectContext dependenciesProjectVisitor)
|
||||||
|> Rule3.withModuleVisitor internalAddModuleVisitors_New
|
|> Rule.withModuleVisitor internalAddModuleVisitors
|
||||||
|
|
||||||
|
|
||||||
{-| Adds the scope visitors to your module rule.
|
{-| Adds the scope visitors to your module rule.
|
||||||
@ -457,63 +456,6 @@ internalAddModuleVisitors schema =
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
internalAddModuleVisitors_New : Rule3.ModuleRuleSchema schemaState { moduleContext | scope : ModuleContext } -> Rule3.ModuleRuleSchema { schemaState | hasAtLeastOneVisitor : () } { moduleContext | scope : ModuleContext }
|
|
||||||
internalAddModuleVisitors_New schema =
|
|
||||||
schema
|
|
||||||
|> Rule3.withModuleDefinitionVisitor
|
|
||||||
(mapInnerModuleContext moduleDefinitionVisitor |> pairWithNoErrors)
|
|
||||||
|> Rule3.withImportVisitor
|
|
||||||
(mapInnerModuleContext importVisitor |> pairWithNoErrors)
|
|
||||||
|> Rule3.withDeclarationListVisitor
|
|
||||||
(mapInnerModuleContext declarationListVisitor |> pairWithNoErrors)
|
|
||||||
|> Rule3.withDeclarationEnterVisitor
|
|
||||||
(\visitedElement outerContext ->
|
|
||||||
let
|
|
||||||
innerContext : InnerModuleContext
|
|
||||||
innerContext =
|
|
||||||
outerContext.scope
|
|
||||||
|> unboxModule
|
|
||||||
|> declarationEnterVisitor visitedElement
|
|
||||||
in
|
|
||||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
|
||||||
)
|
|
||||||
|> Rule3.withDeclarationExitVisitor
|
|
||||||
(\visitedElement outerContext ->
|
|
||||||
let
|
|
||||||
innerContext : InnerModuleContext
|
|
||||||
innerContext =
|
|
||||||
outerContext.scope
|
|
||||||
|> unboxModule
|
|
||||||
|> declarationExitVisitor visitedElement
|
|
||||||
in
|
|
||||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
|
||||||
)
|
|
||||||
|> Rule3.withExpressionEnterVisitor
|
|
||||||
(\visitedElement outerContext ->
|
|
||||||
let
|
|
||||||
innerContext : InnerModuleContext
|
|
||||||
innerContext =
|
|
||||||
outerContext.scope
|
|
||||||
|> unboxModule
|
|
||||||
|> popScopeEnter visitedElement
|
|
||||||
|> expressionEnterVisitor visitedElement
|
|
||||||
in
|
|
||||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
|
||||||
)
|
|
||||||
|> Rule3.withExpressionExitVisitor
|
|
||||||
(\visitedElement outerContext ->
|
|
||||||
let
|
|
||||||
innerContext : InnerModuleContext
|
|
||||||
innerContext =
|
|
||||||
outerContext.scope
|
|
||||||
|> unboxModule
|
|
||||||
|> popScopeExit visitedElement
|
|
||||||
|> expressionExitVisitor visitedElement
|
|
||||||
in
|
|
||||||
( [], { outerContext | scope = ModuleContext innerContext } )
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
mapInnerProjectContext : (visitedElement -> InnerProjectContext -> InnerProjectContext) -> visitedElement -> { projectContext | scope : ProjectContext } -> ( List nothing, { projectContext | scope : ProjectContext } )
|
mapInnerProjectContext : (visitedElement -> InnerProjectContext -> InnerProjectContext) -> visitedElement -> { projectContext | scope : ProjectContext } -> ( List nothing, { projectContext | scope : ProjectContext } )
|
||||||
mapInnerProjectContext visitor visitedElement outerContext =
|
mapInnerProjectContext visitor visitedElement outerContext =
|
||||||
let
|
let
|
||||||
|
Loading…
Reference in New Issue
Block a user