From 27318ddfc24240343e0aec245dfbdad994135e96 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval Date: Fri, 31 May 2024 15:16:37 +0200 Subject: [PATCH] Use final annotation If final="1" is set we skip the heuristic to determine whether a class is final. In post processing we can skip the heuristic when the final type is set in the introscpection data and the config does not set final_type. Fixes: https://github.com/gtk-rs/gir/issues/1204 --- src/library_postprocessing.rs | 26 ++++++++++++++++---------- src/parser.rs | 3 ++- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/library_postprocessing.rs b/src/library_postprocessing.rs index 11747c6f5..332663f26 100644 --- a/src/library_postprocessing.rs +++ b/src/library_postprocessing.rs @@ -427,7 +427,7 @@ impl Library { // for that reason. // FIXME: without class_hierarchy this function O(n2) due inner loop in // `has_subtypes` - let mut final_types: Vec = Vec::new(); + let mut overridden_final_types: Vec<(TypeId, bool)> = Vec::new(); for (ns_id, ns) in self.namespaces.iter().enumerate() { for (id, type_) in ns.types.iter().enumerate() { @@ -442,16 +442,21 @@ impl Library { let full_name = tid.full_name(self); let obj = config.objects.get(&*full_name); - let is_final = if let Some(GObject { + if let Some(GObject { final_type: Some(final_type), .. }) = obj { // The config might also be used to override a type that is wrongly // detected as final type otherwise - *final_type + overridden_final_types.push((tid, *final_type)); + } else if klass.final_type { + continue; } else if klass.type_struct.is_none() { - !self.has_subtypes(tid) + let is_final = !self.has_subtypes(tid); + if is_final { + overridden_final_types.push((tid, true)); + } } else { let has_subtypes = self.has_subtypes(tid); let instance_struct_known = !klass.fields.is_empty(); @@ -468,18 +473,19 @@ impl Library { unreachable!("Can't find class for {}", full_name); }; - !has_subtypes && (!instance_struct_known || !class_struct_known) + let is_final = + !has_subtypes && (!instance_struct_known || !class_struct_known); + if is_final { + overridden_final_types.push((tid, true)); + } }; - if is_final { - final_types.push(tid); - } } } } - for tid in final_types { + for (tid, new_is_final) in overridden_final_types { if let Type::Class(Class { final_type, .. }) = self.type_mut(tid) { - *final_type = true; + *final_type = new_is_final; } else { unreachable!(); } diff --git a/src/parser.rs b/src/parser.rs index cdbcb66f6..dae9c1704 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -173,6 +173,7 @@ impl Library { }; let is_abstract = elem.attr("abstract").map_or(false, |x| x == "1"); + let final_type = elem.attr("final").map_or(false, |x| x == "1"); let mut fns = Vec::new(); let mut signals = Vec::new(); @@ -255,7 +256,7 @@ impl Library { properties, parent, implements: impls, - final_type: false, // this will be set during postprocessing + final_type, doc, doc_deprecated, version,