libgir/analysis/
enums.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::Enumeration {
18        let type_ = library
19            .type_(self.type_id)
20            .maybe_ref()
21            .unwrap_or_else(|| panic!("{} is not an enumeration.", self.full_name));
22        type_
23    }
24}
25
26pub fn new(env: &Env, obj: &GObject, imports: &mut Imports) -> Option<Info> {
27    info!("Analyzing enumeration {}", obj.name);
28
29    if obj.status.ignored() {
30        return None;
31    }
32
33    let enumeration_tid = env.library.find_type(0, &obj.name)?;
34    let type_ = env.type_(enumeration_tid);
35    let enumeration: &library::Enumeration = type_.maybe_ref()?;
36
37    let name = split_namespace_name(&obj.name).1;
38
39    if obj.status.need_generate() {
40        // Mark the type as available within the enum namespace:
41        imports.add_defined(&format!("crate::{name}"));
42        imports.add("crate::ffi");
43
44        let imports = &mut imports.with_defaults(enumeration.version, &None);
45        imports.add("glib::translate::*");
46
47        let has_get_quark = enumeration.error_domain.is_some();
48        if has_get_quark {
49            imports.add("glib::prelude::*");
50        }
51
52        let has_get_type = enumeration.glib_get_type.is_some();
53        if has_get_type {
54            imports.add("glib::prelude::*");
55        }
56    }
57
58    let mut functions = functions::analyze(
59        env,
60        &enumeration.functions,
61        Some(enumeration_tid),
62        false,
63        false,
64        obj,
65        imports,
66        None,
67        None,
68    );
69
70    // Gir does not currently mark the first parameter of associated enum functions
71    // - that are identical to its enum type - as instance parameter since most
72    // languages do not support this.
73    for f in &mut functions {
74        if f.parameters.c_parameters.is_empty() {
75            continue;
76        }
77
78        let first_param = &mut f.parameters.c_parameters[0];
79
80        if first_param.typ == enumeration_tid {
81            first_param.instance_parameter = true;
82
83            let t = f
84                .parameters
85                .transformations
86                .iter_mut()
87                .find(|t| t.ind_c == 0)
88                .unwrap();
89
90            if let TransformationType::ToGlibScalar { name, .. } = &mut t.transformation_type {
91                *name = "self".to_owned();
92            } else {
93                panic!(
94                    "Enumeration function instance param must be passed as scalar, not {:?}",
95                    t.transformation_type
96                );
97            }
98        }
99    }
100
101    let specials = special_functions::extract(&mut functions, type_, obj);
102
103    if obj.status.need_generate() {
104        special_functions::analyze_imports(&specials, imports);
105    }
106
107    let info = Info {
108        full_name: obj.name.clone(),
109        type_id: enumeration_tid,
110        name: name.to_owned(),
111        functions,
112        specials,
113        visibility: obj.visibility,
114    };
115
116    Some(info)
117}