libgir/codegen/
mod.rs

1use std::{
2    fmt::Display,
3    io::{Result, Write},
4    path::Path,
5};
6
7use general::{cfg_condition, version_condition};
8
9use crate::{
10    config::{gobjects::GObject, WorkMode},
11    env::Env,
12    file_saver::*,
13    library::Member,
14    version::Version,
15};
16
17mod alias;
18mod bound;
19mod child_properties;
20mod constants;
21mod doc;
22mod enums;
23mod flags;
24pub mod function;
25mod function_body_chunk;
26mod functions;
27mod general;
28mod object;
29mod objects;
30mod parameter;
31mod properties;
32mod property_body;
33mod record;
34mod records;
35mod ref_mode;
36mod return_value;
37mod signal;
38mod signal_body;
39mod special_functions;
40mod sys;
41mod trait_impls;
42mod trampoline;
43mod trampoline_from_glib;
44mod visibility;
45pub use visibility::Visibility;
46mod trampoline_to_glib;
47pub mod translate_from_glib;
48pub mod translate_to_glib;
49
50pub fn generate(env: &Env) {
51    match env.config.work_mode {
52        WorkMode::Normal => normal_generate(env),
53        WorkMode::Sys => sys::generate(env),
54        WorkMode::Doc => doc::generate(env),
55        WorkMode::DisplayNotBound => {}
56    }
57}
58
59fn normal_generate(env: &Env) {
60    let mut mod_rs: Vec<String> = Vec::new();
61    let mut traits: Vec<String> = Vec::new();
62    let mut builders: Vec<String> = Vec::new();
63    let root_path = env.config.auto_path.as_path();
64
65    generate_single_version_file(env);
66    objects::generate(env, root_path, &mut mod_rs, &mut traits, &mut builders);
67    records::generate(env, root_path, &mut mod_rs);
68    enums::generate(env, root_path, &mut mod_rs);
69    flags::generate(env, root_path, &mut mod_rs);
70    alias::generate(env, root_path, &mut mod_rs);
71    functions::generate(env, root_path, &mut mod_rs);
72    constants::generate(env, root_path, &mut mod_rs);
73
74    generate_mod_rs(env, root_path, &mod_rs, &traits, &builders);
75}
76
77pub fn generate_mod_rs(
78    env: &Env,
79    root_path: &Path,
80    mod_rs: &[String],
81    traits: &[String],
82    builders: &[String],
83) {
84    let path = root_path.join("mod.rs");
85    save_to_file(path, env.config.make_backup, |w| {
86        general::start_comments(w, &env.config)?;
87        general::write_vec(w, mod_rs)?;
88        writeln!(w)?;
89        if !traits.is_empty() {
90            writeln!(w, "pub(crate) mod traits {{")?;
91            general::write_vec(w, traits)?;
92            writeln!(w, "}}")?;
93        }
94
95        if !builders.is_empty() {
96            writeln!(w, "pub(crate) mod builders {{")?;
97            general::write_vec(w, builders)?;
98            writeln!(w, "}}")?;
99        }
100        Ok(())
101    });
102}
103
104pub fn generate_single_version_file(env: &Env) {
105    if let Some(ref path) = env.config.single_version_file {
106        save_to_file(path, env.config.make_backup, |w| {
107            general::single_version_file(w, &env.config, "")
108        });
109    }
110}
111
112pub fn generate_default_impl<
113    'a,
114    D: Display,
115    F: Fn(&'a Member) -> Option<(Option<Version>, Option<&'a String>, D)>,
116>(
117    w: &mut dyn Write,
118    env: &Env,
119    config: &GObject,
120    type_name: &str,
121    type_version: Option<Version>,
122    mut members: impl Iterator<Item = &'a Member>,
123    callback: F,
124) -> Result<()> {
125    if let Some(ref default_value) = config.default_value {
126        let member = match members.find(|m| m.name == *default_value) {
127            Some(m) => m,
128            None => {
129                log::error!(
130                    "type `{}` doesn't have a member named `{}`. Not generating default impl.",
131                    type_name,
132                    default_value,
133                );
134                return Ok(());
135            }
136        };
137        let (version, cfg_cond, member_name) = match callback(member) {
138            Some(n) => n,
139            None => {
140                log::error!(
141                    "member `{}` on type `{}` isn't generated so no default impl.",
142                    default_value,
143                    type_name,
144                );
145                return Ok(());
146            }
147        };
148
149        // First we generate the type cfg.
150        version_condition(w, env, None, type_version, false, 0)?;
151        cfg_condition(w, config.cfg_condition.as_ref(), false, 0)?;
152        // Then we generate the member cfg.
153        version_condition(w, env, None, version, false, 0)?;
154        cfg_condition(w, cfg_cond, false, 0)?;
155        writeln!(
156            w,
157            "\n\
158             impl Default for {type_name} {{\n\
159             \tfn default() -> Self {{\n\
160             \t\tSelf::{member_name}\n\
161             \t}}\n\
162             }}\n",
163        )
164    } else {
165        Ok(())
166    }
167}