CredoNaming
is a suite of checks to enforce naming best practices in an Elixir project.
Add the :credo_naming
package to your mix.exs
dependencies:
def deps do
[
{:credo_naming, "~> 2.1", only: [:dev, :test], runtime: false}
]
end
You just need to add the checks you want in your .credo.exs
configuration file.
This check will raise an issue if specific terms are found in module names.
{CredoNaming.Check.Warning.AvoidSpecificTermsInModuleNames, terms: ["Manager", ~r/Helpers?/]}
Suppose you have a MyApp.ErrorHelpers
module:
$ mix credo
β Warnings - please take a look
β
β [W] β `Helpers` is included in the list of terms to avoid in module names.
β Consider replacing it with a more accurate one.
β lib/my_app/error_helpers.ex:1:39 #(MyApp.ErrorHelpers)
With this check configuration for example, a module named MyApp.UserManager
or MyApp.FormHelpers
would not be allowed.
This check will raise an issue if the name of a module defined in a file does not match its filename.
{CredoNaming.Check.Consistency.ModuleFilename}
Suppose you have a lib/foo.ex
file that defines a Bar
module:
$ mix credo
β Consistency
β
β [C] β The module defined in `lib/foo.ex` is not named consistently with the
β filename. The file should be named either:
β
β ["lib/bar/bar.ex", "lib/bar.ex"]
β
β lib/foo.ex:1:11 #(Bar)
You can exclude files or paths with the excluded_paths
option:
{CredoNaming.Check.Consistency.ModuleFilename, excluded_paths: ["test/support", "priv", "rel", "mix.exs"]}
You can also exclude files or paths with regex:
{CredoNaming.Check.Consistency.ModuleFilename, excluded_paths: [~r/test\/support/, ~r/priv/, ~r/.exs/]}
The check converts module names to paths using PascalCase
convention, which means that the file lib/myapp_graphql.ex
is expected to define the module:
defmodule MyappGraphql do
end
If you want to define your own acronyms, you can do so using the acronyms
option:
{CredoNaming.Check.Consistency.ModuleFilename, acronyms: [{"MyAppGraphQL", "myapp_graphql"}]}
Using this, the lib/myapp_graphql.ex
file will expect to define the module:
defmodule MyAppGraphQL do
end
By default, the check allows for a specific list of valid filenames when a single module is declared within a file. You can overwrite this behaviour by providing the valid_filename_callback
option and implement yourself if a filename should be considered valid.
The callback receives three arguments:
filename
, the stringified name of the module contained in the file (eg."lib/my_app/foo/bar.ex"
)module_name
, the stringified name of the module contained in the file (eg."MyApp.Foo.Bar"
)opts
, the options list passed to the check (eg.[acronyms: [{"GraphQL", "graphql"}]]
)
And must return a tuple containing a boolean value (if the filename is considered valid) and a list of expected filenames.
In this (very simple) example, a file lib/my_app/wrong.ex
that defines a MyApp.Foo.Bar
module would return a {false, ["lib/my_app/foo/bar.ex"]}
tuple.
def valid_filename?(filename, module_name, _opts) do
root_path = CredoNaming.Check.Consistency.ModuleFilename.root_path(filename)
path = "#{Macro.underscore(module_name)}#{Path.extname(filename)}"
filenames = [
Path.join([root_path, path])
]
{filename in filenames, filenames}
end
{CredoNaming.Check.Consistency.ModuleFilename, valid_filename_callback: &valid_filename/3}
You could also use the callback to ignore specific files and fallback on the default callback for others.
def valid_filename?("lib/my_app/my_specific_file.ex", _module_name, _opts), do: {true, []}
def valid_filename?("lib/my_app/my_other_specific_file.ex", _module_name, _opts), do: {true, []}
def valid_filename?(filename, module_name, opts), do: CredoNaming.Check.Consistency.ModuleFilename.valid_filename?(filename, module_name, opts)
{CredoNaming.Check.Consistency.ModuleFilename, valid_filename_callback: &valid_filename/3}
Instead of implementing your own valid_filename_callback
function, you can use the plugins
option to enforce a specific supported naming convention. This option accepts a list of: one arity function or plugin name (for now, only CredoNaming.Check.Consistency.ModuleFilename.Plugins.Phoenix
is supported as a predefined plugin).
{CredoNaming.Check.Consistency.ModuleFilename, plugins: [CredoNaming.Check.Consistency.ModuleFilename.Plugins.Phoenix, &IO.inspect/1]}
In case you have an umbrella project and have set apps_path
to something other than apps
, you can set the apps_path
option to the correct path.
{CredoNaming.Check.Consistency.ModuleFilename, apps_path: "my_apps_path"}
- RΓ©mi PrΓ©vost (@remiprev)
- TomΓ‘Ε‘ JanouΕ‘ek (@liskin)
- Felipe Duzzi (@duzzifelipe)
- Daniel Willeitner (@D-Town44)
- Daniel Reigada (@DReigada)
- Pavel Tsiukhtsiayeu (@paveltyk)
CredoNaming
is Β© 2019 Mirego and may be freely distributed under the New BSD license. See the LICENSE.md
file.
The tag logo is based on this lovely icon by Vectors Point, from The Noun Project. Used under a Creative Commons BY 3.0 license.
Mirego is a team of passionate people who believe that work is a place where you can innovate and have fun. Weβre a team of talented people who imagine and build beautiful Web and mobile applications. We come together to share ideas and change the world.
We also love open-source software and we try to give back to the community as much as we can.