alef 0.109.6

Opinionated polyglot binding generator for Rust libraries
Documentation
//! Kotlin assertion rendering helpers.
//!
//! ~keep This file is already over the repo's 1,000-line file-modularization cap. The
//! `not_error_may_assert_presence` unification (routing `not_error` through
//! `not_error_presence::may_assert_presence`) added one parameter to `render_assertion`,
//! required at every call site — the small net growth here is that mechanical churn plus the
//! `not_error` arm's updated doc comment, not new unrelated functionality.

use crate::e2e::field_access::FieldResolver;
use crate::e2e::fixture::Assertion;

/// Non-(out, assertion) inputs to [`render_assertion`], grouped to keep the function under
/// poly's `too-many-parameters` limit. Field order matches the parameter order it replaces -- no
/// behavior change.
#[cfg(test)]
pub(super) struct RenderAssertionContext<'a> {
    pub(super) result_var: &'a str,
    pub(super) class_name: &'a str,
    pub(super) field_resolver: &'a FieldResolver,
    pub(super) result_is_simple: bool,
    pub(super) result_is_option: bool,
    pub(super) enum_fields: &'a std::collections::HashSet<String>,
    pub(super) json_scalar_fields: &'a std::collections::HashSet<String>,
    pub(super) fields_c_types: &'a std::collections::HashMap<String, String>,
    pub(super) is_streaming: bool,
    pub(super) kotlin_android_style: bool,
    pub(super) not_error_may_assert_presence: bool,
}

/// [`render_assertion_with_streaming_context`] with no stream item type, so a `stream.has_*_event`
/// predicate renders as a counted skip marker rather than a variant check. Every non-streaming
/// call site (and every unit test below) keeps its existing signature through this.
///
/// `#[cfg(test)]`: every production caller resolves a streaming item type and goes through
/// [`render_assertion_with_streaming_context`] directly, so this exists only to keep the unit
/// tests' existing call shape. ~keep
#[cfg(test)]
pub(super) fn render_assertion(out: &mut String, assertion: &Assertion, context: RenderAssertionContext) {
    let RenderAssertionContext {
        result_var,
        class_name,
        field_resolver,
        result_is_simple,
        result_is_option,
        enum_fields,
        json_scalar_fields,
        fields_c_types,
        is_streaming,
        kotlin_android_style,
        not_error_may_assert_presence,
    } = context;
    render_assertion_with_streaming_context(
        out,
        assertion,
        RenderAssertionStreamingContext {
            result_var,
            class_name,
            field_resolver,
            result_is_simple,
            result_is_option,
            enum_fields,
            json_scalar_fields,
            fields_c_types,
            is_streaming,
            streaming_item_type: None,
            kotlin_android_style,
            not_error_may_assert_presence,
        },
    );
}

/// Non-(out, assertion) inputs to [`render_assertion_with_streaming_context`], grouped to keep
/// the function under poly's `too-many-parameters` limit. Field order matches the parameter
/// order it replaces -- no behavior change.
pub(super) struct RenderAssertionStreamingContext<'a> {
    pub(super) result_var: &'a str,
    pub(super) class_name: &'a str,
    pub(super) field_resolver: &'a FieldResolver,
    pub(super) result_is_simple: bool,
    pub(super) result_is_option: bool,
    pub(super) enum_fields: &'a std::collections::HashSet<String>,
    pub(super) json_scalar_fields: &'a std::collections::HashSet<String>,
    pub(super) fields_c_types: &'a std::collections::HashMap<String, String>,
    pub(super) is_streaming: bool,
    pub(super) streaming_item_type: Option<&'a str>,
    pub(super) kotlin_android_style: bool,
    pub(super) not_error_may_assert_presence: bool,
}

/// `streaming_item_type` is the unqualified name of the streaming event union (e.g. `CrawlEvent`),
/// resolved by the caller from the call recipe or the matching streaming adapter. It is what lets
/// `stream.has_page_event` and friends render a real `chunks.any { it is CrawlEvent.Page }` check
/// instead of being skipped for want of a type name. ~keep
pub(super) fn render_assertion_with_streaming_context(
    out: &mut String,
    assertion: &Assertion,
    context: RenderAssertionStreamingContext,
) {
    let RenderAssertionStreamingContext {
        result_var,
        class_name: _class_name,
        field_resolver,
        result_is_simple,
        result_is_option,
        enum_fields,
        json_scalar_fields,
        fields_c_types,
        is_streaming,
        streaming_item_type,
        kotlin_android_style,
        not_error_may_assert_presence,
    } = context;
    // `mock.*` request-count virtual fields (alef issue #443): resolve against the mock
    // server's own request log via the once-per-suite helper, never a struct field --
    // intercept before EVERY other branch below, including every field-shape gate
    // `assertion_field_gates` runs (starting with `try_skip_field_not_available_on_result_type`),
    // which would otherwise misclassify a `mock.*` field as absent from the result type. ~keep
    if super::assertion_mock_capture::try_render_mock_capture_assertion(out, assertion, kotlin_android_style) {
        return;
    }

    if super::assertion_field_gates::try_render_field_shape_gates(
        out,
        assertion,
        super::assertion_field_gates::FieldShapeGatesContext {
            field_resolver,
            result_var,
            result_is_simple,
            is_streaming,
            streaming_item_type,
            kotlin_android_style,
            fields_c_types,
        },
    ) {
        return;
    }

    super::assertion_scalar_dispatch::render_scalar_pipeline(
        out,
        assertion,
        super::assertion_scalar_dispatch::ScalarPipelineContext {
            field_resolver,
            result_var,
            result_is_simple,
            result_is_option,
            enum_fields,
            json_scalar_fields,
            fields_c_types,
            kotlin_android_style,
            is_streaming,
            not_error_may_assert_presence,
        },
    );
}

#[cfg(test)]
mod tests;