libgir/analysis/
signals.rs

1use super::{imports::Imports, trampolines};
2use crate::{
3    analysis::trampolines::Trampoline,
4    config::{self, gobjects::GObject},
5    env::Env,
6    library, nameutil,
7    traits::*,
8    version::Version,
9};
10
11#[derive(Debug)]
12pub struct Info {
13    pub connect_name: String,
14    pub signal_name: String,
15    pub action_emit_name: Option<String>,
16    pub trampoline: Result<Trampoline, Vec<String>>,
17    pub version: Option<Version>,
18    pub deprecated_version: Option<Version>,
19    pub doc_hidden: bool,
20    pub is_detailed: bool,
21    pub generate_doc: bool,
22    pub cfg_condition: Option<String>,
23}
24
25pub fn analyze(
26    env: &Env,
27    signals: &[library::Signal],
28    type_tid: library::TypeId,
29    in_trait: bool,
30    is_fundamental: bool,
31    obj: &GObject,
32    imports: &mut Imports,
33) -> Vec<Info> {
34    let mut sns = Vec::new();
35
36    for signal in signals {
37        let configured_signals = obj.signals.matched(&signal.name);
38        if !configured_signals.iter().all(|f| f.status.need_generate()) {
39            continue;
40        }
41        if env.is_totally_deprecated(Some(type_tid.ns_id), signal.deprecated_version) {
42            continue;
43        }
44
45        let info = analyze_signal(
46            env,
47            signal,
48            type_tid,
49            in_trait,
50            is_fundamental,
51            &configured_signals,
52            obj,
53            imports,
54        );
55        sns.push(info);
56    }
57
58    sns
59}
60
61fn analyze_signal(
62    env: &Env,
63    signal: &library::Signal,
64    type_tid: library::TypeId,
65    in_trait: bool,
66    is_fundamental: bool,
67    configured_signals: &[&config::signals::Signal],
68    obj: &GObject,
69    imports: &mut Imports,
70) -> Info {
71    let mut used_types: Vec<String> = Vec::with_capacity(4);
72    let version = configured_signals
73        .iter()
74        .filter_map(|f| f.version)
75        .min()
76        .or(signal.version);
77    let cfg_condition = configured_signals
78        .iter()
79        .find_map(|s| s.cfg_condition.clone());
80    let deprecated_version = signal.deprecated_version;
81    let doc_hidden = configured_signals.iter().any(|f| f.doc_hidden);
82
83    let imports = &mut imports.with_defaults(version, &None);
84    imports.add("glib::translate::*");
85
86    let connect_name = format!("connect_{}", nameutil::signal_to_snake(&signal.name));
87    let trampoline = trampolines::analyze(
88        env,
89        signal,
90        type_tid,
91        in_trait,
92        is_fundamental,
93        configured_signals,
94        obj,
95        &mut used_types,
96        version,
97    );
98
99    let action_emit_name = if signal.is_action {
100        imports.add("glib::prelude::*");
101        Some(format!("emit_{}", nameutil::signal_to_snake(&signal.name)))
102    } else {
103        None
104    };
105
106    if trampoline.is_ok() {
107        imports.add_used_types(&used_types);
108        imports.add("glib::prelude::*");
109        imports.add("glib::object::ObjectType as _");
110        imports.add("glib::signal::{connect_raw, SignalHandlerId}");
111        imports.add("std::boxed::Box as Box_");
112    }
113    let generate_doc = configured_signals.iter().all(|f| f.generate_doc);
114
115    Info {
116        connect_name,
117        signal_name: signal.name.clone(),
118        trampoline,
119        action_emit_name,
120        version,
121        deprecated_version,
122        doc_hidden,
123        is_detailed: signal.is_detailed,
124        generate_doc,
125        cfg_condition,
126    }
127}