sparksp / elm-review-imports Goto Github PK
View Code? Open in Web Editor NEWelm-review rule to enforce consistent import aliases
Home Page: https://package.elm-lang.org/packages/sparksp/elm-review-imports/latest/
License: MIT License
elm-review rule to enforce consistent import aliases
Home Page: https://package.elm-lang.org/packages/sparksp/elm-review-imports/latest/
License: MIT License
Given two modules
module Main exposing (main)
import Example
import Html
main : Html.Html msg
main =
Html.text <|
case Just Example.Foo of
Just Example.Foo ->
"just foo"
Just Example.Bar ->
"just bar"
Nothing ->
"nothing"
and
module Example exposing (FooBar(..))
type FooBar
= Foo
| Bar
and an elm-review config of
module ReviewConfig exposing (config)
import NoInconsistentAliases
import Review.Rule exposing (Rule)
config : List Rule
config =
[ NoInconsistentAliases.config
[ ( "Example", "E" ) ]
|> NoInconsistentAliases.noMissingAliases
|> NoInconsistentAliases.rule
]
applying the fix converts Main.elm
to
module Main exposing (main)
import Example as E
import Html
main : Html.Html msg
main =
Html.text <|
case Just E.Foo of
Just Example.Foo ->
"foo"
Just Example.Bar ->
"bar"
Nothing ->
"nothing"
Just Example.Foo
to be changed to Just E.Foo
Just Example.Foo
isn't modified
It would be nice if adding ( "List.Extra", "" )
to the config meant that List.Extra
should never be aliased
In the following rule, NoModuleOnExposedName will suggest a fix by replacing convert : Color -> Element.Color
with convert : Color -> Color
which will lead to a compile error. It should instead suggest removing Color from exposing or not suggest any fix in this case.
import Element exposing (Color)
type Color = Red | Green | Blue
convert : Color -> Element.Color
convert color =
...
Edit: I think the correct behavior would be to not show an error at all. Consider this case:
import Subcomponent exposing (Msg(..))
type Msg = A | B
foo : Subcomponent.Msg
foo =
MsgVariantInSubComponent
Subcomponent.Msg
can't be changed to Msg
due to a name collision but exposing (Msg(..))
can't be removed either because of MsgVariantInSubComponent
.
If you've established an alias for a module somewhere in your project and then try to use it bare in another file (without an alias) then we will report the bare import and try to offer a fix.
--- [File 1] Pass: Alias is established
import Html.Attributes as Attr
--- [File 2] Fail: No alias has been used
import Html.Attributes
container children =
Html.div [ Html.Attributes.class "container" ] children
--- [File 3] Pass: Alias is not necessary
import Html.Attributes exposing (class)
view = div [ class "flex" ] []
config : List Rule
config =
[ NoInconsistentAliases.config []
|> NoInconsistentAliases.discoverAliases
|> NoInconsistentAliases.noMissingAliases
|> NoInconsistentAliases.rule
]
At GlobalWebIndex we have our own custom ConsistentImports
rule.
It allows multiple aliases (we need this because of us having a convention import List.Extra as List
, and Html.Attributes.Extra.autocomplete
colliding with Html.Attributes.autocomplete
, which makes us need to import the Extra as Attrs_
instead of Attrs
in the modules that use the autocomplete
value) - described more in the Elm Slack discussion.
We wanted to publish our rule, then found out this package exists, so we'd love to not divide the ecosystem.
Would you consider allowing multiple aliases for a given imported module in elm-review-imports
?
This is on:
jfmengels/elm-review
2.8.1sparksp/elm-review-imports
1.0.1The files below result in a false negative: the import Json.Decode as Json
is not picked upon (should warn and offer a fix to rename the alias to as Decode
):
Note that if the import of Json.Decode.Extra
in Main.elm
is removed, the false negative disappears and the rule suddenly offers to rename the Json.Decode
alias!
Review config:
module ReviewConfig exposing (config)
import NoInconsistentAliases
import Review.Rule exposing (Rule)
config : List Rule
config =
[ NoInconsistentAliases.config
[ ( "Json.Decode", "Decode" )
, ( "Json.Decode.Extra", "Decode" )
]
|> NoInconsistentAliases.noMissingAliases
|> NoInconsistentAliases.rule
]
Main.elm
:
module Main exposing (x)
import Json.Decode as Json
import Json.Decode.Extra as Json
x = 1
I've found a false positive for NoModuleOnExposedNames
:
import Element exposing (width)
foo { width } = Element.width -- false positive
bar = width
If a function or type has been exposed on import do not allow it to be called via the module name/alias. The user should either remove the call from the import's exposes or remove the module name from the call.
Here class
is exposed but is still called by Attr.class
.
import Html.Attributes as Attr exposing (class)
view children =
div [ Attr.class "container" ] children
-import Html.Attributes as Attr exposing (class)
+import Html.Attributes as Attr
view children =
div [ Attr.class "container" ] children
import Html.Attributes as Attr exposing (class)
view children =
- div [ Attr.class "container" ] children
+ div [ class "container" ] children
Here Attribute
has been exposed but is still called by Html.Attribute
.
import Html exposing (Html, Attribute)
container : List (Html.Attribute msg) -> List (Html msg) -> Html msg
container attributes children =
div attributes children
-import Html exposing (Html, Attribute)
+import Html exposing (Html)
container : List (Html.Attribute msg) -> List (Html msg) -> Html msg
container attributes children =
div attributes children
import Html exposing (Html, Attribute)
-container : List (Html.Attribute msg) -> List (Html msg) -> Html msg
+container : List (Attribute msg) -> List (Html msg) -> Html msg
container attributes children =
div attributes children
Currently the consistent alias rule takes a list of module names and the alias they should each use. What if instead the rule took a function with the type signature ModuleName -> Alias
where Alias is
type Alias
= DontCare
| AlwaysNoAlias
| AlwaysAlias String
Edit: To elaborate on why this is useful, in the code we have at work, we have a lot of modules and I'd like to be able to do something like, all elm-ui modules shouldn't be aliased. Or all modules under Shared.* should use the last part of their module name as an alias.
Proposed fix:
-- (fix) NoModuleOnExposedNames: Module used on exposed type `Dict`.
type alias Dict k v =
Internal.Dict k v
^^^^^^^^^^^^^
It is not necessary to use the module here as `Dict` was exposed on import.
You should remove the module from this call, or remove the name from the import
.. exposing list.
Except it is in fact necessary to do that (and exposing the type is done to import the constructors/variants, so can't be avoided)
For things from the prelude (https://package.elm-lang.org/packages/elm/core/latest/), it's not useful to specify things like List.List
, Maybe.Maybe
or String.String
in type annotations.
Based on some discussions with @jfmengels here's an outline of what this rule should achieve:
To ensure consistent use of import aliases throughout the project.
As a project evolves so might your code style, but as you move between files you should not need to keep track of what the "correct" alias is. This gets harder the bigger the project or team. Consider the following three imports. They're all valid, and could have been written by the same author at sometime:
--- [File 1]
import Html.Attributes as Attributes
--- [File 2]
import Html.Attributes as A
--- [File 3]
import Html.Attributes as Attr
Changing an alias across your whole project is menial and time consuming. You will be able to configure the rule with a mapping of modules to aliases to be enforced. We will offer code fixes to apply the correct aliases.
config : List Rule
config =
[ NoInconsistentAliases.config
[ ( "Html.Attributes", "Attr" )
, ( "Json.Encode", "Encode" )
, ( "Json.Decode", "Decode" )
]
|> NoInconsistentAliases.rule
]
What should we do if there's a collision of aliases within a module? Consider the following imports:
--[ src/Somefile.elm ]
import Html.Attributes as A
import Svg.Attributes as Attr
--[ review/src/ReviewConfig.elm ]
NoInconsistentAliases.config
[ ( "Svg.Attributes", "Attr" )
]
|> NoInconsistentAliases.rule
There's nothing to do here, we already meet the config.
--[ review/src/ReviewConfig.elm ]
NoInconsistentAliases.config
[ ( "Html.Attributes", "Attr" )
]
|> NoInconsistentAliases.rule
The rule says that A
is wrong for Html.Attributes
, but our preferred alias Attr
is already taken. We don't have a preference for Svg.Attributes
so we could report Html.Attributes
and mention that the preferred alias is already taken. We would not be able to provide an automated fix for this.
Solution: Report Html.Attributes
with no fix.
--[ review/src/ReviewConfig.elm ]
NoInconsistentAliases.config
[ ( "Html.Attributes", "Attr" )
, ( "Svg.Attributes", "SvgAttr" )
]
|> NoInconsistentAliases.rule
The rule says that both aliases are wrong, however we can't offer a fix for Html.Attributes
because the preferred alias is already taken. We can offer a fix for Svg.Attributes
, which would clear the way to fix Html.Attributes
.
Solution: Report Html.Attributes
with no fix (as Scenario 2), and report Svg.Attributes
with a fix (as normal).
--[ review/src/ReviewConfig.elm ]
NoInconsistentAliases.config
[ ( "Html.Attributes", "Attr" )
, ( "Svg.Attributes", "Attr" )
]
|> NoInconsistentAliases.rule
The rule says that A
is wrong for Html.Attributes
, but our preferred alias Attr
is already taken by another preferred alias. If the user fixes Html.Attributes
then we will have a problem with Svg.Attributes
instead.
Solution: No Report
--[ review/src/ReviewConfig.elm ]
NoInconsistentAliases.config
[ ( "Html.Attributes", "Attributes" )
, ( "Svg.Attributes", "Attributes" )
]
|> NoInconsistentAliases.rule
The rule says that both aliases are wrong. We can report both of them and offer fixes for each - when a fix is applied for either then we'll be in the same situation as Scenario 4.
Solution: Report both aliases as normal.
--[ src/Somefile.elm ]
import Attr
import Html.Attributes as A
--[ review/src/ReviewConfig.elm ]
NoInconsistentAliases.config
[ ( "Html.Attributes", "Attr" )
]
|> NoInconsistentAliases.rule
The rule says that A
is wrong for Html.Attributes
, but our preferred alias Attr
is already taken by a bare module import (no alias). If the user fixes Html.Attributes
then they will have to alias module Attr
instead.
Solution: No Report
--[ src/Somefile.elm ]
import Attributes
import Html.Attributes as A
--[ review/src/ReviewConfig.elm ]
NoInconsistentAliases.config
[ ( "Attributes", "Attr" )
, ( "Html.Attributes", "Attributes" )
]
|> NoInconsistentAliases.rule
This is Scenario 3 again - the only difference is that Attributes
is a bare module. We don't need to do anything different here - when Attributes
is correctly aliased then a fix can be offered for Html.Attributes
.
Solution: Report Attributes
with a fix (as normal), and report Html.Attributes
with no fix (as Scenario 2).
We will check every import alias across the project to ensure they are aliased consistently, and report any that are inconsistent. We will try to report only the errant aliases. For example, if you've imported Html.Attributes
as Attr
fifteen times and as A
once then we'll report just that one.
config : List Rule
config =
[ NoInconsistentAliases.config []
|> NoInconsistentAliases.discoverAliases
|> NoInconsistentAliases.rule
]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.