libgir/analysis/
flags.rs

1use log::info;
2
3use super::{function_parameters::TransformationType, imports::Imports, *};
4use crate::{codegen::Visibility, config::gobjects::GObject, env::Env, nameutil::*, traits::*};
5
6#[derive(Debug, Default)]
7pub struct Info {
8    pub full_name: String,
9    pub type_id: library::TypeId,
10    pub name: String,
11    pub functions: Vec<functions::Info>,
12    pub specials: special_functions::Infos,
13    pub visibility: Visibility,
14}
15
16impl Info {
17    pub fn type_<'a>(&self, library: &'a library::Library) -> &'a library::Bitfield {
18        (library
19            .type_(self.type_id)
20            .maybe_ref()
21            .unwrap_or_else(|| panic!("{} is not an flags.", self.full_name))) as _
22    }
23}
24
25pub fn new(env: &Env, obj: &GObject, imports: &mut Imports) -> Option<Info> {
26    info!("Analyzing flags {}", obj.name);
27
28    if obj.status.ignored() {
29        return None;
30    }
31
32    let flags_tid = env.library.find_type(0, &obj.name)?;
33    let type_ = env.type_(flags_tid);
34    let flags: &library::Bitfield = type_.maybe_ref()?;
35
36    let name = split_namespace_name(&obj.name).1;
37
38    if obj.status.need_generate() {
39        // Mark the type as available within the bitfield namespace:
40        imports.add_defined(&format!("crate::{name}"));
41        imports.add("crate::ffi");
42
43        let imports = &mut imports.with_defaults(flags.version, &None);
44        imports.add("glib::translate::*");
45        imports.add("glib::bitflags::bitflags");
46
47        let has_get_type = flags.glib_get_type.is_some();
48        if has_get_type {
49            imports.add("glib::prelude::*");
50        }
51    }
52
53    let mut functions = functions::analyze(
54        env,
55        &flags.functions,
56        Some(flags_tid),
57        false,
58        false,
59        obj,
60        imports,
61        None,
62        None,
63    );
64
65    // Gir does not currently mark the first parameter of associated bitfield
66    // functions - that are identical to its bitfield type - as instance
67    // parameter since most languages do not support this.
68    for f in &mut functions {
69        if f.parameters.c_parameters.is_empty() {
70            continue;
71        }
72
73        let first_param = &mut f.parameters.c_parameters[0];
74
75        if first_param.typ == flags_tid {
76            first_param.instance_parameter = true;
77
78            let t = f
79                .parameters
80                .transformations
81                .iter_mut()
82                .find(|t| t.ind_c == 0)
83                .unwrap();
84
85            if let TransformationType::ToGlibScalar { name, .. } = &mut t.transformation_type {
86                *name = "self".to_owned();
87            } else {
88                panic!(
89                    "Bitfield function instance param must be passed as scalar, not {:?}",
90                    t.transformation_type
91                );
92            }
93        }
94    }
95
96    let specials = special_functions::extract(&mut functions, type_, obj);
97
98    if obj.status.need_generate() {
99        special_functions::analyze_imports(&specials, imports);
100    }
101
102    let info = Info {
103        full_name: obj.name.clone(),
104        type_id: flags_tid,
105        name: name.to_owned(),
106        functions,
107        specials,
108        visibility: obj.visibility,
109    };
110
111    Some(info)
112}