# `AshGrant.Transformers.AddCanPerformCalculations`
[🔗](https://github.com/jhlee111/ash_grant/blob/v0.14.1/lib/ash_grant/transformers/add_can_perform_calculations.ex#L1)

Spark DSL transformer that generates CanPerform calculations from DSL entities.

This transformer reads `can_perform` entities and the `can_perform_actions`
option from the `ash_grant` section and adds corresponding boolean calculations
using `Ash.Resource.Builder.add_new_calculation/5`.

## Usage Rules

- **`can_perform_actions`** (batch) and **`can_perform`** (individual entity) can coexist.
  Both are merged into a single list before generating calculations.
- **Naming**: `can_perform_actions [:update]` generates `:can_update?`.
  `can_perform :update` also generates `:can_update?` by default.
  Use the `name:` option on `can_perform` for a custom name (e.g., `name: :editable?`).
- **Duplicate handling**: Uses `add_new_calculation` (not `add_calculation`), so if
  the same calculation name already exists (from an explicit `calculations` block or
  a duplicate DSL entry), it is silently skipped. The first definition wins.
- **Coexistence with explicit module**: DSL-generated calculations and manually declared
  `{AshGrant.Calculation.CanPerform, ...}` calculations coexist safely.
- **Resource auto-detection**: The transformer injects the resource module automatically
  via `Transformer.get_persisted(dsl_state, :module)`, so users do not need to pass
  `resource: __MODULE__` when using the DSL.
- **Public by default**: All DSL-generated calculations are `public?: true` by default.
  The `can_perform` entity supports `public?: false` for private calculations.
- **Action validation**: At compile time, the transformer verifies that each referenced
  action name exists on the resource. A typo like `can_perform_actions [:foobar]` raises
  a `Spark.Error.DslError` with the list of available actions.

# `after_compile?`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
