Skip to content

Commit

Permalink
Auto merge of gtk-rs#167 - gkoz:interfaces, r=gkoz
Browse files Browse the repository at this point in the history
Add interfaces support to object analysis

None
  • Loading branch information
homu committed Nov 26, 2015
2 parents c6a4ae6 + cecda57 commit 8f9fc07
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 21 deletions.
6 changes: 5 additions & 1 deletion Gir_Gtk.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ status = "manual"

[[object]]
name = "Gtk.Orientable"
status = "manual"
status = "generate"

[[object]]
name = "Gtk.Adjustment"
Expand Down Expand Up @@ -138,6 +138,10 @@ status = "generate"
name = "Gtk.FontButton"
status = "generate"

[[object]]
name = "Gtk.FontChooser"
status = "generate"

[[object]]
name = "Gtk.FontChooserWidget"
status = "generate"
Expand Down
9 changes: 5 additions & 4 deletions src/analysis/needed_upcast.rs
Original file line number Diff line number Diff line change
@@ -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,
}
}
64 changes: 56 additions & 8 deletions src/analysis/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<general::StatusedTypeId>,
pub implements: Vec<general::StatusedTypeId>,
pub has_children: bool,
Expand All @@ -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()
Expand Down Expand Up @@ -72,7 +67,7 @@ pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
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;
Expand Down Expand Up @@ -105,6 +100,8 @@ pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
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,
Expand All @@ -123,3 +120,54 @@ pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
info.has_functions = has_functions;
Some(info)
}

pub fn interface(env: &Env, obj: &GObject) -> Option<Info> {
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)
}
27 changes: 25 additions & 2 deletions src/analysis/parents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<StatusedTypeId> {
let mut parents = Vec::new();

Expand All @@ -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<StatusedTypeId> {
let mut parents = Vec::new();

for &parent_tid in &type_.prereq_parents {
let parent_type = env.type_(parent_tid).to_ref_as::<Class>();
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
}
4 changes: 3 additions & 1 deletion src/analysis/rust_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand Down Expand Up @@ -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,
}
Expand Down
4 changes: 1 addition & 3 deletions src/codegen/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 4 additions & 2 deletions src/codegen/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>, 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;
}
};
Expand Down

0 comments on commit 8f9fc07

Please sign in to comment.