SiriusStarr/elm-review-no-unsorted/1.1.1

NOTE: the latest version is 1.1.8

NoUnsortedTopLevelDeclarations

Review Rule

rule : RuleConfig r -> Rule

Reports top-level declarations that are not in the "proper" order.

🔧 Running with --fix will automatically sort the declarations.

The proper order of declarations is specified in the rule configuration. See the Configuration section below for more information.

config =
    [ NoUnsortedTopLevelDeclarations.rule
        (NoUnsortedTopLevelDeclarations.sortTopLevelDeclarations
            |> NoUnsortedTopLevelDeclarations.portsFirst
            |> NoUnsortedTopLevelDeclarations.exposedOrderWithPrivateLast
            |> NoUnsortedTopLevelDeclarations.alphabetically
        )
    ]

Fail

module A exposing
    ( A, a
    , Z
    )


{-|


@docs A, a
@docs Z


-}


type A
    = A


z =
    zed


type alias Z =
    A


a =
    foo


b =
    bar

Success

module A exposing
    ( A, a
    , Z
    )


{-|


@docs A, a
@docs Z


-}


type A
    = A


a =
    foo


type alias Z =
    A


b =
    bar


z =
    zed

When (not) to enable this rule

This rule is useful when you want to ensure that your top-level declarations are in a consistent, predictable order.

This rule is not useful when you want to be able to write top-level declarations in varying orders throughout your codebase, e.g. if you want to emphasize what is most important on a case-by-case basis.

Try it out

You can try this rule out by running the following command:

elm-review --template SiriusStarr/elm-review-no-unsorted/example --rules NoUnsortedTopLevelDeclarations

Configuration

type RuleConfig r

Configuration for this rule. Create a new one with sortTopLevelDeclarations and use orderings to create a hierarchy of sorting.

{ noAlphabetical : ()
, noDependency : ()
, noExposed : ()
, noHelper : ()
, noType : ()
, noPort : ()
}

Create a new RuleConfig. Use the various orderings to then specify primary and fallback orderings.

Orderings

alphabetically : RuleConfig { r | noAlphabetical : () } -> RuleConfig r

Sort declarations alphabetically. Note that this decapitalizes the first letter before performing the comparison so as to treat types and functions the same. For example, the following is sorted alphabetically:

type A
    = A


a =
    foo


b =
    bar


z =
    zed


type alias Z =
    A
exposedOrderWithPrivateLast : RuleConfig { r | noExposed : () } -> RuleConfig r

Sort TLDs in the order they are exposed by the module, with private TLDs coming after all those that are exposed. For example, the following is sorted by this and then alphabetically:

module A exposing
    ( A, a
    , Z
    )


{-|


@docs A, a
@docs Z


-}


type A
    = A


a =
    foo


type alias Z =
    A


b =
    bar


z =
    zed
exposedOrderWithPrivateFirst : RuleConfig { r | noExposed : () } -> RuleConfig r

Sort TLDs in the order they are exposed by the module, with private TLDs coming before all those that are exposed. For example, the following is sorted by this and then alphabetically:

module A exposing
    ( A, a
    , Z
    )


{-|


@docs A, a
@docs Z


-}


b =
    bar


z =
    zed


type A
    = A


a =
    foo


type alias Z =
    A
typesFirst : RuleConfig { r | noType : () } -> RuleConfig r

Sort TLDs so that types and type aliases always come before functions (and ports, if they haven't been sorted already). For example, the following is sorted by this order and then alphabetically:

type A
    = A


type alias Z =
    A


a =
    foo


b =
    bar


z =
    zed
typesLast : RuleConfig { r | noType : () } -> RuleConfig r

Sort TLDs so that types and type aliases always come after functions (and ports, if they haven't been sorted already). For example, the following is sorted by this order and then alphabetically:

a =
    foo


b =
    bar


z =
    zed


type A
    = A


type alias Z =
    A
portsFirst : RuleConfig { r | noPort : () } -> RuleConfig r

Sort TLDs so that ports always come before functions (and types, if they haven't been sorted already). For example, the following is sorted by this order and then alphabetically:

port sendMessage : String -> Cmd msg


type A
    = A


a =
    foo


b =
    bar


type alias Z =
    A


z =
    zed
portsLast : RuleConfig { r | noPort : () } -> RuleConfig r

Sort TLDs so that ports always come after functions (and types, if they haven't been sorted already). For example, the following is sorted by this order and then alphabetically:

type A
    = A


a =
    foo


b =
    bar


type alias Z =
    A


z =
    zed


port sendMessage : String -> Cmd msg

Glues

Glues provide a way to "stick" one declaration to another, i.e. to always sort one declaration alongside another. Note that glues will chain, i.e. if a is glued before b and b is glued after c, then the result will be c -> a -> b (sorted wherever c is sorted to). Glues behave in the following ways:

  • If multiple glues are specified, the first specified will be used.
  • If multiple declarations are glued at the same place, they will be ordered by the orderings specified.
  • If glues are not acyclic (i.e. two declarations are glued to each other, possibly via intermediates), then all of the involved declarations will not be glued and will be sorted normally.
glueHelpersBefore : RuleConfig { r | noHelper : () } -> RuleConfig r

Helpers are unexposed functions that are used in exactly one other function. This glue attaches them immediately before the function they are used in.

For example:

foldrHelper : (a -> b -> b) -> b -> Int -> List a -> b
foldrHelper fn acc ctr ls =
    case ls of
        [] ->
            acc


        a :: r1 ->
            ...


{-| Reduce a list from the right.
-}
foldr : (a -> b -> b) -> b -> List a -> b
foldr fn acc ls =
    foldrHelper fn acc 0 ls
glueHelpersAfter : RuleConfig { r | noHelper : () } -> RuleConfig r

Helpers are unexposed functions that are used in exactly one other function. This glue attaches them immediately after the function they are used in.

For example:

{-| Reduce a list from the right.
-}
foldr : (a -> b -> b) -> b -> List a -> b
foldr fn acc ls =
    foldrHelper fn acc 0 ls


foldrHelper : (a -> b -> b) -> b -> Int -> List a -> b
foldrHelper fn acc ctr ls =
    case ls of
        [] ->
            acc


        a :: r1 ->
            ...

Dependencies are unexposed functions that are used in multiple other functions. This glue attaches them immediately before the first function they are used in.

For example:

unwrap =
    some func


a x =
    unwrap x


b x =
    unwrap x


c x =
    unwrap x

Dependencies are unexposed functions that are used in multiple other functions. This glue attaches them immediately after the first function they are used in.

For example:

a x =
    unwrap x


unwrap =
    some func


b x =
    unwrap x


c x =
    unwrap x

Dependencies are unexposed functions that are used in multiple other functions. This glue attaches them immediately after the last function they are used in.

For example:

a x =
    unwrap x


b x =
    unwrap x


c x =
    unwrap x


unwrap =
    some func

Dependencies are unexposed functions that are used in multiple other functions. This glue attaches them immediately before the last function they are used in.

For example:

a x =
    unwrap x


b x =
    unwrap x


unwrap =
    some func


c x =
    unwrap x