relay-knowledge 1.1.16

Graph-database-based knowledge graph project.
Documentation
use super::{
    c_family_typedef_like_function_signature,
    declaration::{
        c_family_decorator_payload_token, c_family_external_type_token, c_family_head_tokens,
        c_family_known_decorator_token, c_identifier_name,
    },
    decorated_function_head_has_recovery_decorator,
    signature::c_family_top_level_parameter_start,
};

pub(super) fn c_family_decorated_type_line(trimmed: &str) -> bool {
    let tokens = trimmed
        .split(|character: char| !(character.is_ascii_alphanumeric() || character == '_'))
        .filter(|token| !token.is_empty())
        .collect::<Vec<_>>();
    tokens.iter().enumerate().any(|(index, token)| {
        matches!(*token, "class" | "struct" | "enum" | "union")
            && (c_family_decorator_before_type(&tokens, index)
                || c_family_decorator_after_type(&tokens, index))
    })
}

fn c_family_decorator_before_type(tokens: &[&str], index: usize) -> bool {
    let mut cursor = index;
    while let Some(previous_index) = cursor.checked_sub(1) {
        let Some(previous) = tokens.get(previous_index) else {
            return false;
        };
        if c_family_known_decorator_token(previous) {
            return true;
        }
        if !c_family_decorator_payload_token(previous) && !c_identifier_name(previous) {
            return false;
        }
        cursor = previous_index;
    }

    false
}

fn c_family_decorator_after_type(tokens: &[&str], index: usize) -> bool {
    tokens
        .get(index + 1)
        .is_some_and(|candidate| c_family_known_decorator_token(candidate))
}

pub(super) fn c_family_macro_name(token: &str) -> bool {
    !token.is_empty()
        && token.chars().all(|character| {
            character == '_' || character.is_ascii_uppercase() || character.is_ascii_digit()
        })
        && token.chars().any(|character| character == '_')
        && token
            .chars()
            .any(|character| character.is_ascii_uppercase())
}

pub(super) fn c_family_recoverable_error_function_signature(trimmed: &str) -> bool {
    if !c_family_typedef_like_function_signature(trimmed) {
        return false;
    }
    let Some(parameter_start) = c_family_top_level_parameter_start(trimmed, false) else {
        return false;
    };
    let head = &trimmed[..parameter_start];
    let tokens = c_family_head_tokens(head);
    decorated_function_head_has_recovery_decorator(trimmed)
        || tokens
            .iter()
            .take(tokens.len().saturating_sub(1))
            .any(|token| c_family_recoverable_error_type_token(token.text))
}

fn c_family_recoverable_error_type_token(token: &str) -> bool {
    c_family_external_type_token(token) || (token.ends_with("_t") && c_identifier_name(token))
}