scythe-codegen 0.19.0

Polyglot code generation backends for scythe
Documentation
//! Spec rendering shared by the Elixir backends.
//!
//! Elixir writes a parameter's type twice, in two positions that do not mean
//! the same thing. In a `@type`/`defstruct` field position a bare module
//! alias is a reference to that module, so an enum column's `UserStatus`
//! renders correctly as `UserStatus.t()`. In a `@spec` *argument* position
//! the same bare alias is a **literal atom** type -- `:"Elixir.UserStatus"`
//! -- which no caller can ever satisfy, because what actually crosses the
//! call boundary is the runtime string the database stores (`"active"`).
//!
//! Only `elixir-ecto` handled that distinction; the other five backends put
//! `full_type` straight into the `@spec` and produced a signature Dialyzer
//! rejects for every correct call. Keeping the rule here rather than in one
//! backend that the others reach across into means there is one derivation
//! of it, which is the property the whole `*_common.rs` family exists for.

use crate::backend_trait::ResolvedParam;

/// Render a bound query parameter's `@spec` argument type.
///
/// An enum parameter is spelled `String.t()` -- the type of the value a
/// caller actually passes -- rather than its module alias, which in argument
/// position would be a literal-atom type nothing can satisfy. Every other
/// parameter keeps the `full_type` the manifest resolved for it (#202).
pub(crate) fn elixir_param_spec_type(param: &ResolvedParam) -> String {
    if param.neutral_type.starts_with("enum::") {
        "String.t()".to_string()
    } else {
        param.full_type.clone()
    }
}