View Source Module Directives (use, alias, ...)
Directive Organization
Modules directives are sorted into the following order:
@shortdoc@moduledoc(adds@moduledoc false)@behaviouruseimport(sorted alphabetically)alias(sorted alphabetically)require(sorted alphabetically)- everything else (order unchanged)
Before
defmodule Foo do
@behaviour Lawful
alias A.A
require A
use B
def c(x), do: y
import C
@behaviour Chaotic
@doc "d doc"
def d do
alias X.X
alias H.H
alias Z.Z
import Ecto.Query
X.foo()
end
@shortdoc "it's pretty short"
import A
alias C.C
alias D.D
require C
require B
use A
alias C.C
alias A.A
@moduledoc "README.md"
|> File.read!()
|> String.split("<!-- MDOC !-->")
|> Enum.fetch!(1)
endAfter
defmodule Foo do
@shortdoc "it's pretty short"
@moduledoc "README.md"
|> File.read!()
|> String.split("<!-- MDOC !-->")
|> Enum.fetch!(1)
@behaviour Chaotic
@behaviour Lawful
use B
use A.A
import A.A
import C
alias A.A
alias C.C
alias D.D
require A
require B
require C
def c(x), do: y
@doc "d doc"
def d do
import Ecto.Query
alias H.H
alias X.X
alias Z.Z
X.foo()
end
endIf any line previously relied on an alias, the alias is fully expanded when it is moved above the alias:
# Given
alias Foo.Bar
import Bar
# Styled
import Foo.Bar
alias Foo.BarDirective Expansion
Expands Module.{SubmoduleA, SubmoduleB} to their explicit forms for ease of searching.
# Before
import Foo.{Bar, Baz, Bop}
alias Foo.{Bar, Baz.A, Bop}
# After
import Foo.Bar
import Foo.Baz
import Foo.Bop
alias Foo.Bar
alias Foo.Baz.A
alias Foo.BopAlias Lifting
When a module with three parts is referenced two or more times, styler creates a new alias for that module and uses it.
# Given
require A.B.C
A.B.C.foo()
A.B.C.bar()
# Styled
alias A.B.C
require C
C.foo()
C.bar()Styler also notices when you have a module aliased and aren't employing that alias and will do the updates for you.
# Given
alias My.Apps.Widget
x = Repo.get(My.Apps.Widget, id)
# Styled
alias My.Apps.Widget
x = Repo.get(Widget, id)Collisions
Styler won't lift aliases that will collide with existing aliases, and likewise won't lift any module whose name would collide with a standard library name.
You can specify additional modules to exclude from lifting via the :alias_lifting_exclude configuration option. For the example above, the following configuration would keep Styler from creating the alias A.B.C node:
# .formatter.exs
[
plugins: [Styler],
styler: [alias_lifting_exclude: [:C]],
]Alias Application
Styler applies aliases in those cases where a developer wrote out a full module name without realizing that the module is already aliased.
# Given
alias A.B
alias A.B.C
alias A.B.C.D, as: X
A.B.foo()
A.B.C.foo()
A.B.C.D.woo()
C.D.woo()
# Styled
alias A.B
alias A.B.C
alias A.B.C.D, as: X
B.foo()
C.foo()
X.woo()
X.woo()
Adds @moduledoc false
Adds @moduledoc false to modules without a moduledoc.
Styler does this for two reasons:
Its appearance during code review is a reminder to the author and reviewer that they may want to document the module. This can otherwise be easily forgotten.
To normalize the use of
@moduledoc false, because it's preferable to docstrings which convey no actual information.For example:
@moduledoc "The module for functions for interacting with Widgets"in theWidgetmodule is crueler code to have written than just@moduledoc false, because including a string gave the reader hope that the author was going to help them comprehend the module. That false hope causes more harm than just saying "Sorry, you're on your own." (aka@moduledoc false)
In conformance with the precedent set by Credo, this @moduledoc is not added if the module's name ends with any of the following:
TestMixfileMixProjectControllerEndpointRepoRouterSocketViewHTMLJSON