Basics
This check is disabled by default.
Learn how to enable it via .credo.exs.
This check has a base priority of high and works with any version of Elixir.
Explanation
Builtin change, validation, preparation, and calculation functions
like set_attribute, present, build, and concat must be
wrapped in their DSL entity (change, validate, prepare,
calculate ...) when you use them inside an action body, a
pipeline body, or a global section (changes, validations,
preparations, calculations).
These builtins are plain functions that Ash imports into the DSL scope. Without the wrapper, the call returns a spec tuple that is silently discarded: the change, validation, or preparation never runs, and no error or warning is raised at compile time or runtime.
# Bad - compiles but silently does nothing
create :register do
accept [:email]
present(:email)
set_attribute(:status, :draft)
end
# Good - wrapped in the matching keyword
create :register do
accept [:email]
validate present(:email)
change set_attribute(:status, :draft)
endThe check examines each builtin family only in the scopes that import
it, so it never flags a bare call the compiler already rejects. The
advice is position-aware for set_context, which exists as both a
change and a preparation builtin: in a pipeline the advice is
change, in a read or generic action it is prepare.
The check reads the builtin names from Ash's *.Builtins modules at
analysis time, so builtins added in newer Ash versions are covered
automatically. Because some builtin names are common words
(present, compare, match, build, load, select), a bare
call to a same-named local helper inside an action body gets flagged
too; silence such a call with # credo:disable-for-next-line.
Check-Specific Parameters
There are no specific parameters for this check.
General Parameters
Like with all checks, general params can be applied.
Parameters can be configured via the .credo.exs config file.