mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-11-23 23:05:35 +03:00
Make NoUnused.Modules not report test modules or modules with a main function
This commit is contained in:
parent
4ff2c2db00
commit
9cc72c659f
@ -12,6 +12,7 @@ module NoUnusedModules exposing (rule)
|
||||
import Dict exposing (Dict)
|
||||
import Elm.Module
|
||||
import Elm.Project exposing (Project)
|
||||
import Elm.Syntax.Declaration as Declaration exposing (Declaration)
|
||||
import Elm.Syntax.Import exposing (Import)
|
||||
import Elm.Syntax.Module as Module exposing (Module)
|
||||
import Elm.Syntax.ModuleName exposing (ModuleName)
|
||||
@ -23,13 +24,10 @@ import Set exposing (Set)
|
||||
|
||||
{-| Forbid the use of modules that are never used in your project.
|
||||
|
||||
For an application, a module is considered unused if it does not contain a
|
||||
`main` function (be it exposed or not), does not import `Test` module, and is
|
||||
never imported in other modules.
|
||||
|
||||
For a package, a module is considered unused if it is not exposed in the
|
||||
`elm.json`'s `exposed-modules`, does not import `Test` module, and is never
|
||||
imported in other modules.
|
||||
A module is considered unused if it does not contain a `main` function
|
||||
(be it exposed or not), does not import `Test` module, and is never imported in
|
||||
other modules. For packages, modules listed in the `elm.json`'s
|
||||
`exposed-modules` are considered used.
|
||||
|
||||
A module will be considered as used if it gets imported, even if none of its
|
||||
functions or types are used. Other rules from this package will help detect and
|
||||
@ -43,12 +41,12 @@ remove code so that the import statement is removed.
|
||||
# When (not) to use this rule
|
||||
|
||||
You may not want to enable this rule if you are not concerned about having
|
||||
unused modules in your application of package.
|
||||
unused modules in your application or package.
|
||||
|
||||
-}
|
||||
rule : Rule
|
||||
rule =
|
||||
Rule.newMultiSchema "NoUnusedModules"
|
||||
Rule.newMultiSchema "NoUnused.Modules"
|
||||
{ elmJsonVisitors = [ elmJsonVisitor ]
|
||||
, dependenciesVisitors = []
|
||||
, moduleVisitorSchema = moduleVisitorSchema
|
||||
@ -79,19 +77,21 @@ type alias GlobalContext =
|
||||
|
||||
type alias ModuleContext =
|
||||
{ importedModules : Set ModuleName
|
||||
, containsMainFunction : Bool
|
||||
}
|
||||
|
||||
|
||||
initGlobalContext : GlobalContext
|
||||
initGlobalContext =
|
||||
{ modules = Dict.empty
|
||||
, usedModules = Set.empty
|
||||
, usedModules = Set.singleton [ "ReviewConfig" ]
|
||||
}
|
||||
|
||||
|
||||
initModuleContext : Rule.FileKey -> Node ModuleName -> GlobalContext -> ModuleContext
|
||||
initModuleContext _ _ _ =
|
||||
{ importedModules = Set.empty
|
||||
, containsMainFunction = False
|
||||
}
|
||||
|
||||
|
||||
@ -101,7 +101,12 @@ toGlobalContext fileKey moduleName moduleContext =
|
||||
Dict.singleton
|
||||
(Node.value moduleName)
|
||||
{ fileKey = fileKey, moduleNameLocation = Node.range moduleName }
|
||||
, usedModules = moduleContext.importedModules
|
||||
, usedModules =
|
||||
if Set.member [ "Test" ] moduleContext.importedModules || moduleContext.containsMainFunction then
|
||||
Set.insert (Node.value moduleName) moduleContext.importedModules
|
||||
|
||||
else
|
||||
moduleContext.importedModules
|
||||
}
|
||||
|
||||
|
||||
@ -113,24 +118,7 @@ fold contextA contextB =
|
||||
|
||||
|
||||
|
||||
-- VISITORS
|
||||
|
||||
|
||||
moduleVisitorSchema :
|
||||
Rule.Schema Rule.ForLookingAtSeveralFiles { hasNoVisitor : () } ModuleContext
|
||||
-> Rule.Schema Rule.ForLookingAtSeveralFiles { hasAtLeastOneVisitor : () } ModuleContext
|
||||
moduleVisitorSchema schema =
|
||||
schema
|
||||
|> Rule.withImportVisitor importVisitor
|
||||
|
||||
|
||||
error : ( ModuleName, { fileKey : Rule.FileKey, moduleNameLocation : Range } ) -> Error
|
||||
error ( moduleName, { fileKey, moduleNameLocation } ) =
|
||||
Rule.errorForFile fileKey
|
||||
{ message = "Module `" ++ String.join "." moduleName ++ "` is never used."
|
||||
, details = [ "This module is never used. You may want to remove it to keep your project clean, and maybe detect some unused code in your project." ]
|
||||
}
|
||||
moduleNameLocation
|
||||
-- GLOBAL VISITORS
|
||||
|
||||
|
||||
elmJsonVisitor : Maybe Project -> GlobalContext -> GlobalContext
|
||||
@ -155,9 +143,44 @@ elmJsonVisitor maybeProject context =
|
||||
exposedModules
|
||||
|> List.map (Elm.Module.toString >> String.split ".")
|
||||
|> Set.fromList
|
||||
|> Set.union context.usedModules
|
||||
}
|
||||
|
||||
|
||||
finalEvaluationForProject : GlobalContext -> List Error
|
||||
finalEvaluationForProject { modules, usedModules } =
|
||||
modules
|
||||
|> Dict.filter (\moduleName _ -> not <| Set.member moduleName usedModules)
|
||||
|> Dict.toList
|
||||
|> List.map error
|
||||
|
||||
|
||||
|
||||
-- MODULE VISITORS
|
||||
|
||||
|
||||
moduleVisitorSchema :
|
||||
Rule.Schema Rule.ForLookingAtSeveralFiles { hasNoVisitor : () } ModuleContext
|
||||
-> Rule.Schema Rule.ForLookingAtSeveralFiles { hasAtLeastOneVisitor : () } ModuleContext
|
||||
moduleVisitorSchema schema =
|
||||
schema
|
||||
|> Rule.withImportVisitor importVisitor
|
||||
|> Rule.withDeclarationListVisitor declarationListVisitor
|
||||
|
||||
|
||||
error : ( ModuleName, { fileKey : Rule.FileKey, moduleNameLocation : Range } ) -> Error
|
||||
error ( moduleName, { fileKey, moduleNameLocation } ) =
|
||||
Rule.errorForFile fileKey
|
||||
{ message = "Module `" ++ String.join "." moduleName ++ "` is never used."
|
||||
, details = [ "This module is never used. You may want to remove it to keep your project clean, and maybe detect some unused code in your project." ]
|
||||
}
|
||||
moduleNameLocation
|
||||
|
||||
|
||||
|
||||
-- IMPORT VISITOR
|
||||
|
||||
|
||||
importVisitor : Node Import -> ModuleContext -> ( List Error, ModuleContext )
|
||||
importVisitor node context =
|
||||
( []
|
||||
@ -173,9 +196,26 @@ moduleNameForImport node =
|
||||
|> Node.value
|
||||
|
||||
|
||||
finalEvaluationForProject : GlobalContext -> List Error
|
||||
finalEvaluationForProject { modules, usedModules } =
|
||||
modules
|
||||
|> Dict.filter (\moduleName _ -> not <| Set.member moduleName usedModules)
|
||||
|> Dict.toList
|
||||
|> List.map error
|
||||
|
||||
-- DECLARATION LIST VISITOR
|
||||
|
||||
|
||||
declarationListVisitor : List (Node Declaration) -> ModuleContext -> ( List Error, ModuleContext )
|
||||
declarationListVisitor list context =
|
||||
let
|
||||
containsMainFunction : Bool
|
||||
containsMainFunction =
|
||||
List.any
|
||||
(\decl ->
|
||||
case Node.value decl of
|
||||
Declaration.FunctionDeclaration function ->
|
||||
(function.declaration |> Node.value |> .name |> Node.value) == "main"
|
||||
|
||||
_ ->
|
||||
False
|
||||
)
|
||||
list
|
||||
in
|
||||
( []
|
||||
, { context | containsMainFunction = containsMainFunction }
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user