sigmd 0.1.0

Windows API signature metadata
Documentation
//! Parameter parsing: `ParmDecl` -> [`Parameter`].

use sigmd::model::Parameter;

use super::{BuildContext, Error, clang, sal, ty::build_type};

/// Builds a [`Parameter`] from a `ParmDecl` cursor.
///
/// Returns the parameter plus the raw annotation strings for the SAL
/// analyzer to consume, and whether the parameter declaration is
/// invalid. The validity bit feeds dedup scoring and is not persisted.
pub fn build_parameter(
    cursor: clang::Entity<'_>,
    ctx: &BuildContext,
) -> Result<BuildParameter, Error> {
    let name = cursor.get_name();
    let ty = build_type(cursor.get_type().expect("entity has type"), ctx);

    let mut annotations = Vec::new();
    for child in cursor.get_children() {
        if child.get_kind() == clang::EntityKind::AnnotateAttr
            && let Some(child_name) = child.get_name()
        {
            annotations.push(child_name);
        }
    }

    let flags = sal::flags(&sal::decode(&annotations));

    let parameter = Parameter::builder()
        .maybe_name(name)
        .flags(flags)
        .ty(ty)
        .build();

    Ok(BuildParameter {
        parameter,
        annotations,
        is_invalid: cursor.is_invalid_declaration(),
    })
}

/// Output of `build_parameter`.
pub struct BuildParameter {
    /// Parsed parameter.
    pub parameter: Parameter,

    /// Raw annotation strings from `CXCursor_AnnotateAttr` children.
    pub annotations: Vec<String>,

    /// Whether the declaration was marked invalid by clang.
    pub is_invalid: bool,
}