elm-review/tests/NoImportingEverything.elm
2020-06-28 08:01:44 +02:00

93 lines
2.4 KiB
Elm

module NoImportingEverything exposing (rule)
{-|
@docs rule
-}
import Elm.Syntax.Exposing as Exposing
import Elm.Syntax.Import exposing (Import)
import Elm.Syntax.Node as Node exposing (Node)
import Review.Rule as Rule exposing (Error, Rule)
import Set exposing (Set)
{-| Forbids importing everything from a module.
When you import everything from a module, it becomes harder to know where a function
or a type comes from. The official guide even
[recommends against importing everything](https://guide.elm-lang.org/webapps/modules.html#using-modules).
config =
[ NoImportingEverything.rule []
]
Teams often have an agreement on the list of imports from which it is okay to expose everything, so
you can configure a list of exceptions.
config =
[ NoImportingEverything.rule [ "Html", "Some.Module" ]
]
## Fail
import A exposing (..)
import A as B exposing (..)
## Success
import A as B exposing (B(..), C, d)
-- If configured with `[ "Html" ]`
import Html exposing (..)
-}
rule : List String -> Rule
rule exceptions =
Rule.newModuleRuleSchema "NoImportingEverything" ()
|> Rule.withSimpleImportVisitor (importVisitor <| exceptionsToSet exceptions)
|> Rule.fromModuleRuleSchema
exceptionsToSet : List String -> Set (List String)
exceptionsToSet exceptions =
exceptions
|> List.map (String.split ".")
|> Set.fromList
importVisitor : Set (List String) -> Node Import -> List (Error {})
importVisitor exceptions node =
if Set.member (moduleName node) exceptions then
[]
else
case
Node.value node
|> .exposingList
|> Maybe.map Node.value
of
Just (Exposing.All range) ->
[ Rule.error
{ message = "Prefer listing what you wish to import and/or using qualified imports"
, details = [ "When you import everything from a module, it becomes harder to know where a function or a type comes from" ]
}
{ start = { row = range.start.row, column = range.start.column - 1 }
, end = { row = range.end.row, column = range.end.column + 1 }
}
]
_ ->
[]
moduleName : Node Import -> List String
moduleName node =
node
|> Node.value
|> .moduleName
|> Node.value