2020-04-08 01:14:03 +03:00
|
|
|
module NoImportingEverything exposing (rule)
|
2019-06-03 01:30:24 +03:00
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
{-|
|
2019-06-03 01:30:24 +03:00
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
@docs rule
|
2019-07-03 15:19:29 +03:00
|
|
|
|
2019-06-03 01:30:24 +03:00
|
|
|
-}
|
|
|
|
|
|
|
|
import Elm.Syntax.Exposing as Exposing
|
|
|
|
import Elm.Syntax.Import exposing (Import)
|
|
|
|
import Elm.Syntax.Node as Node exposing (Node)
|
2019-09-29 00:47:02 +03:00
|
|
|
import Review.Rule as Rule exposing (Error, Rule)
|
2020-04-08 01:14:03 +03:00
|
|
|
import Set exposing (Set)
|
2019-06-03 01:30:24 +03:00
|
|
|
|
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
{-| Forbids importing everything from a module.
|
2019-06-03 01:30:24 +03:00
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
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).
|
2019-06-03 01:30:24 +03:00
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
config =
|
|
|
|
[ NoImportingEverything.rule []
|
|
|
|
]
|
2019-06-03 01:30:24 +03:00
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
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.
|
2019-07-23 00:38:39 +03:00
|
|
|
|
2019-07-23 00:50:24 +03:00
|
|
|
config =
|
2020-04-08 01:14:03 +03:00
|
|
|
[ NoImportingEverything.rule [ "Html", "Some.Module" ]
|
2019-07-23 00:50:24 +03:00
|
|
|
]
|
|
|
|
|
2019-07-23 00:38:39 +03:00
|
|
|
|
|
|
|
## Fail
|
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
import A exposing (..)
|
|
|
|
import A as B exposing (..)
|
2019-07-23 00:38:39 +03:00
|
|
|
|
|
|
|
|
|
|
|
## Success
|
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
import A as B exposing (B(..), C, d)
|
2019-07-23 00:38:39 +03:00
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
-- If configured with `[ "Html" ]`
|
2019-07-23 00:38:39 +03:00
|
|
|
import Html exposing (..)
|
|
|
|
|
2020-08-09 19:55:15 +03:00
|
|
|
|
|
|
|
## Try it out
|
|
|
|
|
|
|
|
You can try this rule out by running the following command:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
elm-review --template jfmengels/review-common/example --rules NoImportingEverything
|
|
|
|
```
|
|
|
|
|
2019-06-03 01:30:24 +03:00
|
|
|
-}
|
2020-04-08 01:14:03 +03:00
|
|
|
rule : List String -> Rule
|
|
|
|
rule exceptions =
|
2020-06-28 08:49:27 +03:00
|
|
|
Rule.newModuleRuleSchema "NoImportingEverything" ()
|
|
|
|
|> Rule.withSimpleImportVisitor (importVisitor <| exceptionsToSet exceptions)
|
|
|
|
|> Rule.fromModuleRuleSchema
|
2019-06-03 01:30:24 +03:00
|
|
|
|
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
exceptionsToSet : List String -> Set (List String)
|
|
|
|
exceptionsToSet exceptions =
|
|
|
|
exceptions
|
|
|
|
|> List.map (String.split ".")
|
|
|
|
|> Set.fromList
|
2019-06-03 01:30:24 +03:00
|
|
|
|
|
|
|
|
2020-04-08 01:14:03 +03:00
|
|
|
importVisitor : Set (List String) -> Node Import -> List (Error {})
|
|
|
|
importVisitor exceptions node =
|
|
|
|
if Set.member (moduleName node) exceptions then
|
2019-06-16 22:12:37 +03:00
|
|
|
[]
|
2019-06-03 01:30:24 +03:00
|
|
|
|
|
|
|
else
|
2020-04-08 01:14:03 +03:00
|
|
|
case
|
|
|
|
Node.value node
|
|
|
|
|> .exposingList
|
|
|
|
|> Maybe.map Node.value
|
|
|
|
of
|
2019-06-03 01:30:24 +03:00
|
|
|
Just (Exposing.All range) ->
|
2020-04-08 01:14:03 +03:00
|
|
|
[ Rule.error
|
|
|
|
{ message = "Prefer listing what you wish to import and/or using qualified imports"
|
2020-08-09 19:55:15 +03:00
|
|
|
, details = [ "When you import everything from a module it becomes harder to know where a function or a type comes from." ]
|
2020-04-08 01:14:03 +03:00
|
|
|
}
|
|
|
|
{ start = { row = range.start.row, column = range.start.column - 1 }
|
|
|
|
, end = { row = range.end.row, column = range.end.column + 1 }
|
|
|
|
}
|
|
|
|
]
|
2019-06-03 01:30:24 +03:00
|
|
|
|
|
|
|
_ ->
|
2019-06-16 22:12:37 +03:00
|
|
|
[]
|
2020-04-08 01:14:03 +03:00
|
|
|
|
|
|
|
|
|
|
|
moduleName : Node Import -> List String
|
|
|
|
moduleName node =
|
|
|
|
node
|
|
|
|
|> Node.value
|
|
|
|
|> .moduleName
|
|
|
|
|> Node.value
|