From c8e0cce4bfc78fb3216a72ead0194419623d30c9 Mon Sep 17 00:00:00 2001 From: Gleb Kozyrev Date: Thu, 26 Nov 2015 17:45:16 +0200 Subject: [PATCH 1/2] Add interfaces support to object analysis --- src/analysis/needed_upcast.rs | 9 ++--- src/analysis/object.rs | 64 ++++++++++++++++++++++++++++++----- src/analysis/parents.rs | 27 +++++++++++++-- src/analysis/rust_type.rs | 4 ++- src/codegen/object.rs | 4 +-- src/codegen/objects.rs | 6 ++-- 6 files changed, 94 insertions(+), 20 deletions(-) diff --git a/src/analysis/needed_upcast.rs b/src/analysis/needed_upcast.rs index 655cce4eeb..9b3ae5ead3 100644 --- a/src/analysis/needed_upcast.rs +++ b/src/analysis/needed_upcast.rs @@ -1,8 +1,9 @@ -use library; +use library::{Library, Type, TypeId}; -pub fn needed_upcast(library: &library::Library, type_id: library::TypeId) -> bool { - match library.type_(type_id) { - &library::Type::Class(ref klass) => !klass.children.is_empty(), +pub fn needed_upcast(library: &Library, type_id: TypeId) -> bool { + match *library.type_(type_id) { + Type::Class(ref klass) => !klass.children.is_empty(), + Type::Interface(..) => true, _ => false, } } diff --git a/src/analysis/object.rs b/src/analysis/object.rs index 616578e5ec..86d20c9993 100644 --- a/src/analysis/object.rs +++ b/src/analysis/object.rs @@ -12,6 +12,8 @@ pub struct Info { pub full_name: String, pub class_tid: library::TypeId, pub name: String, + pub c_type: String, + pub get_type: String, pub parents: Vec, pub implements: Vec, pub has_children: bool, @@ -24,13 +26,6 @@ pub struct Info { } impl Info { - //TODO: add test in tests/ for panic - pub fn type_<'a>(&self, library: &'a library::Library) -> &'a library::Class { - let type_ = library.type_(self.class_tid).maybe_ref() - .unwrap_or_else(|| panic!("{} is not a class.", self.full_name)); - type_ - } - ///TODO: return iterator pub fn constructors(&self) -> Vec<&functions::Info> { self.functions.iter() @@ -72,7 +67,7 @@ pub fn new(env: &Env, obj: &GObject) -> Option { imports.add("glib::translate::*".into(), None); imports.add("ffi".into(), None); - let parents = parents::analyze(env, klass, &mut imports); + let parents = parents::analyze_class(env, klass, &mut imports); let implements = implements::analyze(env, klass, &mut imports); let mut has_children = false; @@ -105,6 +100,8 @@ pub fn new(env: &Env, obj: &GObject) -> Option { full_name: full_name, class_tid: class_tid, name: name, + c_type: klass.c_type.clone(), + get_type: klass.glib_get_type.clone(), parents: parents, implements: implements, has_children: has_children, @@ -123,3 +120,54 @@ pub fn new(env: &Env, obj: &GObject) -> Option { info.has_functions = has_functions; Some(info) } + +pub fn interface(env: &Env, obj: &GObject) -> Option { + let full_name = obj.name.clone(); + + let iface_tid = match env.library.find_type(0, &full_name) { + Some(tid) => tid, + None => return None, + }; + + let type_ = env.type_(iface_tid); + + let name: String = split_namespace_name(&full_name).1.into(); + + let iface: &library::Interface = match type_.maybe_ref() { + Some(iface) => iface, + None => return None, + }; + + let mut imports = Imports::new(); + imports.add("glib::translate::*".into(), None); + imports.add("ffi".into(), None); + imports.add("glib::object::Upcast".into(), None); + + let parents = parents::analyze_interface(env, iface, &mut imports); + + let functions = + functions::analyze(env, &iface.functions, iface_tid, &obj.non_nullable_overrides, + &obj.ignored_functions, &mut imports); + + let version = functions.iter().filter_map(|f| f.version).min(); + + //don't `use` yourself + imports.remove(&name); + + let mut info = Info { + full_name: full_name, + class_tid: iface_tid, + name: name, + c_type: iface.c_type.clone(), + get_type: iface.glib_get_type.clone(), + parents: parents, + has_children: true, + functions: functions, + imports: imports, + version: version, + .. Default::default() + }; + + info.has_methods = !info.methods().is_empty(); + Some(info) +} diff --git a/src/analysis/parents.rs b/src/analysis/parents.rs index 22ee732949..ca27fd4649 100644 --- a/src/analysis/parents.rs +++ b/src/analysis/parents.rs @@ -4,10 +4,10 @@ use analysis::rust_type::used_rust_type; use env::Env; use super::general::StatusedTypeId; use super::imports::Imports; -use library::Class; +use library::{Class, Interface}; use traits::*; -pub fn analyze(env: &Env, type_: &Class, imports: &mut Imports) +pub fn analyze_class(env: &Env, type_: &Class, imports: &mut Imports) -> Vec { let mut parents = Vec::new(); @@ -29,3 +29,26 @@ pub fn analyze(env: &Env, type_: &Class, imports: &mut Imports) parents.reverse(); parents } + +pub fn analyze_interface(env: &Env, type_: &Interface, imports: &mut Imports) + -> Vec { + let mut parents = Vec::new(); + + for &parent_tid in &type_.prereq_parents { + let parent_type = env.type_(parent_tid).to_ref_as::(); + let status = env.type_status(&parent_tid.full_name(&env.library)); + + parents.push(StatusedTypeId{ + type_id: parent_tid, + name: parent_type.name.clone(), + status: status, + }); + + if !status.ignored() { + used_rust_type(env, parent_tid).ok().map(|s| imports.add(s, None)); + } + } + + parents.reverse(); + parents +} diff --git a/src/analysis/rust_type.rs b/src/analysis/rust_type.rs index e1e2fa064a..0893e390c5 100644 --- a/src/analysis/rust_type.rs +++ b/src/analysis/rust_type.rs @@ -138,7 +138,8 @@ pub fn parameter_rust_type(env: &Env, type_id:library::TypeId, } } - Class(..) => { + Class(..) | + Interface (..) => { match direction { _ if env.type_status(&type_id.full_name(&env.library)).ignored() => { Err(format!("/*Ignored*/{}", rust_type.as_str())) @@ -177,6 +178,7 @@ fn use_by_ref(type_: &library::Type, direction: library::ParameterDirection) -> Fundamental(library::Fundamental::Filename) | Record(..) | Class(..) | + Interface(..) | List(..) => direction == library::ParameterDirection::In, _ => false, } diff --git a/src/codegen/object.rs b/src/codegen/object.rs index 43971dc9a2..36d859364e 100644 --- a/src/codegen/object.rs +++ b/src/codegen/object.rs @@ -6,14 +6,12 @@ use env::Env; use super::{function, general}; pub fn generate(w: &mut Write, env: &Env, analysis: &analysis::object::Info) -> Result<()>{ - let type_ = analysis.type_(&env.library); - let implements: Vec<&StatusedTypeId> = analysis.parents.iter() .chain(analysis.implements.iter()) .collect(); try!(general::start_comments(w, &env.config)); try!(general::uses(w, &analysis.imports, &env.config.library_name, env.config.min_cfg_version)); - try!(general::define_object_type(w, &analysis.name, &type_.c_type, &type_.glib_get_type, + try!(general::define_object_type(w, &analysis.name, &analysis.c_type, &analysis.get_type, &implements)); if generate_inherent(analysis) { diff --git a/src/codegen/objects.rs b/src/codegen/objects.rs index 7eee71e4c5..0e27b50c43 100644 --- a/src/codegen/objects.rs +++ b/src/codegen/objects.rs @@ -13,10 +13,12 @@ pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec, traits: & } info!("Analyzing {:?}", obj.name); - let class_analysis = match analysis::object::new(env, obj) { + let info = analysis::object::new(env, obj) + .or_else(|| analysis::object::interface(env, obj)); + let class_analysis = match info { Some(info) => info, None => { - warn!("Class {} not found.", obj.name); + warn!("Class or interface {} not found.", obj.name); continue; } }; From cecda57cf4e6cedaed640ac8d8722e430b577c27 Mon Sep 17 00:00:00 2001 From: Gleb Kozyrev Date: Thu, 26 Nov 2015 18:23:39 +0200 Subject: [PATCH 2/2] Add FontChooser and Orientable --- Gir_Gtk.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Gir_Gtk.toml b/Gir_Gtk.toml index 5a72f5ccac..9731116484 100644 --- a/Gir_Gtk.toml +++ b/Gir_Gtk.toml @@ -45,7 +45,7 @@ status = "manual" [[object]] name = "Gtk.Orientable" -status = "manual" +status = "generate" [[object]] name = "Gtk.Adjustment" @@ -138,6 +138,10 @@ status = "generate" name = "Gtk.FontButton" status = "generate" +[[object]] +name = "Gtk.FontChooser" +status = "generate" + [[object]] name = "Gtk.FontChooserWidget" status = "generate"