[DRE-commits] [ruby-gir-ffi] 01/05: Imported Upstream version 0.7.7

Takaki Taniguchi takaki at moszumanska.debian.org
Mon Dec 15 02:34:24 UTC 2014


This is an automated email from the git hooks/post-receive script.

takaki pushed a commit to branch master
in repository ruby-gir-ffi.

commit 4da273e880d97a1ca2b347e77a0a084e3c8f0ef5
Author: TANIGUCHI Takaki <takaki at asis.media-as.org>
Date:   Wed Nov 5 10:51:52 2014 +0900

    Imported Upstream version 0.7.7
---
 Changelog.md                                       |  31 +++-
 README.md                                          |   2 +-
 Rakefile                                           |   8 -
 TODO.md                                            |   4 +
 checksums.yaml.gz                                  | Bin 267 -> 0 bytes
 examples/demo_ffi_inherited_layout.rb              |  21 ---
 examples/demo_ffi_nested_struct.rb                 |  17 --
 examples/demo_ffi_safe_inherited_layout.rb         |  43 -----
 examples/hard_coded.rb                             | 167 -------------------
 examples/leak_test.rb                              |  11 --
 examples/main_loop.rb                              |  12 ++
 examples/print_class.rb                            |  61 -------
 gir_ffi.gemspec                                    |  41 +++++
 lib/ffi-glib.rb                                    |   1 +
 lib/ffi-glib/array.rb                              |  23 ++-
 lib/ffi-glib/array_methods.rb                      |   2 +-
 lib/ffi-glib/list.rb                               |   2 +-
 lib/ffi-glib/list_methods.rb                       |   2 +-
 lib/ffi-glib/main_loop.rb                          |  49 ++++++
 lib/ffi-glib/ptr_array.rb                          |   4 +-
 lib/ffi-glib/s_list.rb                             |   2 +-
 lib/ffi-glib/variant.rb                            |   6 +-
 lib/ffi-gobject.rb                                 |  25 +--
 lib/ffi-gobject/initially_unowned.rb               |   2 +-
 lib/ffi-gobject/object.rb                          |  26 +--
 lib/ffi-gobject/ruby_closure.rb                    |   5 +-
 lib/ffi-gobject/value.rb                           |  28 ++--
 lib/ffi-gobject_introspection/i_base_info.rb       |   6 +-
 lib/ffi-gobject_introspection/i_constant_info.rb   |  26 +--
 lib/ffi-gobject_introspection/i_interface_info.rb  |   2 +-
 lib/ffi-gobject_introspection/i_repository.rb      |   2 +-
 lib/ffi-gobject_introspection/lib.rb               |   2 +-
 lib/gir_ffi-base/glib/strv.rb                      |   4 +-
 lib/gir_ffi.rb                                     |   2 +-
 lib/gir_ffi/arg_helper.rb                          |   4 +-
 lib/gir_ffi/builder.rb                             |   2 +-
 lib/gir_ffi/builders/argument_builder.rb           |  36 +++--
 .../builders/argument_builder_collection.rb        |  67 ++++++--
 lib/gir_ffi/builders/base_argument_builder.rb      |  30 ++--
 lib/gir_ffi/builders/base_type_builder.rb          |  11 +-
 lib/gir_ffi/builders/callback_argument_builder.rb  |  10 +-
 lib/gir_ffi/builders/callback_builder.rb           |   4 -
 .../builders/callback_return_value_builder.rb      |  22 +--
 lib/gir_ffi/builders/constant_builder.rb           |   6 +-
 lib/gir_ffi/builders/enum_builder.rb               |  14 +-
 lib/gir_ffi/builders/error_argument_builder.rb     |  20 ++-
 lib/gir_ffi/builders/field_builder.rb              |  22 +--
 lib/gir_ffi/builders/function_builder.rb           | 122 +++++---------
 lib/gir_ffi/builders/interface_builder.rb          |   9 +-
 lib/gir_ffi/builders/mapping_method_builder.rb     |  75 +++++----
 lib/gir_ffi/builders/marshalling_method_builder.rb |  77 +++++----
 lib/gir_ffi/builders/method_template.rb            |  81 ++++++++++
 lib/gir_ffi/builders/module_builder.rb             |  10 +-
 lib/gir_ffi/builders/null_argument_builder.rb      |  12 --
 lib/gir_ffi/builders/null_builder.rb               |  12 --
 lib/gir_ffi/builders/object_builder.rb             |  69 +++++---
 lib/gir_ffi/builders/property_builder.rb           |   8 +-
 lib/gir_ffi/builders/registered_type_builder.rb    |   6 +-
 lib/gir_ffi/builders/return_value_builder.rb       |  35 ++--
 lib/gir_ffi/builders/signal_closure_builder.rb     |   9 +-
 lib/gir_ffi/builders/type_builder.rb               |   2 +-
 lib/gir_ffi/builders/unintrospectable_builder.rb   |   6 +-
 lib/gir_ffi/builders/user_defined_builder.rb       |  41 +++--
 lib/gir_ffi/builders/vfunc_builder.rb              |   9 +-
 lib/gir_ffi/builders/with_layout.rb                |  10 +-
 lib/gir_ffi/callback_base.rb                       |  15 +-
 lib/gir_ffi/class_base.rb                          |  15 +-
 lib/gir_ffi/enum_base.rb                           |   4 +-
 lib/gir_ffi/g_type.rb                              |  40 ++---
 lib/gir_ffi/in_out_pointer.rb                      |   6 +-
 lib/gir_ffi/in_pointer.rb                          |  17 +-
 lib/gir_ffi/info_ext/i_callable_info.rb            |   2 +-
 lib/gir_ffi/info_ext/i_callback_info.rb            |   2 +-
 lib/gir_ffi/info_ext/i_field_info.rb               |   4 +-
 lib/gir_ffi/info_ext/i_registered_type_info.rb     |   3 +-
 lib/gir_ffi/info_ext/i_signal_info.rb              |   8 +-
 lib/gir_ffi/info_ext/i_type_info.rb                |  12 +-
 lib/gir_ffi/info_ext/i_vfunc_info.rb               |   2 +-
 lib/gir_ffi/method_stubber.rb                      |   2 +-
 lib/gir_ffi/module_base.rb                         |   5 +-
 lib/gir_ffi/object_base.rb                         |   2 +-
 lib/gir_ffi/struct_base.rb                         |   2 +-
 lib/gir_ffi/type_base.rb                           |   4 +-
 lib/gir_ffi/unintrospectable_type_info.rb          |   2 +
 lib/gir_ffi/version.rb                             |   2 +-
 lib/gir_ffi/zero_terminated.rb                     |   2 +-
 metadata.yml                                       | 177 ++-------------------
 tasks/test.rake                                    |   2 +-
 tasks/valgrind.rake                                |   3 -
 tasks/yard.rake                                    |   6 -
 test/ffi-glib/array_test.rb                        |  28 ++++
 test/ffi-glib/byte_array_test.rb                   |   2 +-
 test/ffi-glib/bytes_test.rb                        |   2 +-
 test/ffi-glib/iconv_test.rb                        |   2 +-
 test/ffi-glib/main_loop_test.rb                    |  27 ++++
 test/ffi-gobject/object_test.rb                    |  12 +-
 test/ffi-gobject/value_test.rb                     |  13 +-
 test/ffi-gobject_introspection/i_base_info_test.rb |  14 ++
 .../i_constant_info_test.rb                        |  24 ++-
 .../i_object_info_test.rb                          |  14 +-
 .../i_registered_type_info_test.rb                 |  24 +++
 test/ffi-gobject_introspection/i_type_info_test.rb |  17 ++
 test/gir_ffi/builder_test.rb                       |   5 +-
 test/gir_ffi/builders/argument_builder_test.rb     |   4 +-
 test/gir_ffi/builders/function_builder_test.rb     |  54 +++----
 test/gir_ffi/builders/object_builder_test.rb       |  10 ++
 test/gir_ffi/builders/return_value_builder_test.rb |   6 +-
 .../builders/signal_closure_builder_test.rb        |  12 +-
 test/gir_ffi/class_base_test.rb                    |   8 +-
 test/gir_ffi/in_out_pointer_test.rb                |   2 -
 test/gir_ffi/info_ext/i_type_info_test.rb          |   2 +-
 test/gir_ffi/method_stubber_test.rb                |   8 +-
 test/gir_ffi_test_helper.rb                        |   4 -
 .../generated_gimarshallingtests_test.rb           |   2 +-
 test/integration/generated_regress_test.rb         |   4 +-
 test/lib/autogen.sh                                |   1 +
 test/lib/configure.ac                              |   1 +
 test/minitest/stats_plugin.rb                      |  26 +++
 118 files changed, 1025 insertions(+), 1122 deletions(-)

diff --git a/Changelog.md b/Changelog.md
index 2578de5..d693092 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,34 @@
 # Changelog
 
+## 0.7.7 / 2014-10-21
+
+* Handle introspecting boolean constants
+* Provide config.h for versions of the test libs that need it
+* Include gemspec in the gem
+* Avoid needless casting from string to symbol by making #setup_and_call take a
+  string
+* Avoid argument list unpacking by making #setup_and_call take an array of
+  arguments rather than a variable number of arguments
+* Remove old example files
+* Let rubygems know about required Ruby version
+* Various clean-ups
+
+## 0.7.6 / 2014-08-22
+
+* Work around respond_to? behavior in JRuby 1.6.13
+* Deprecate setup_class in favor of load_class
+* Support GValue containing GArray
+* Provide constant TYPE_BYTE_ARRAY
+* Don't recurse looking for signals and properties
+* Clean up generated code:
+  * Avoid use of an ignored dummy argument
+  * Clean up trailing whitespace
+* Drop support for Ruby 1.9.2
+* Allow data argument for GObject::Object#signal_connect
+* Let Ruby threads run during GLib's main loop
+* Make all dependencies versioned
+* Various refactoring & code cleanup
+
 ## 0.7.5 / 2014-06-22
 
 * Use closures as signal handlers, rather than callbacks
@@ -58,7 +87,7 @@
   * Register defined properties in a subclass
   * Support setting virtual function implementations in a subclass
   * Support adding an interface to a subclass
-  * Support implementing an interface's virtual functions in a subclass 
+  * Support implementing an interface's virtual functions in a subclass
 * Use FFI's DataConvertor system to handle enums and callbacks
 * Stop using deprecated GValueArray to construct argument array for signal_emit
 * Make ITypeInfo#g_type return correct value for c arrays
diff --git a/README.md b/README.md
index 0af36d1..bee656a 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ Ruby bindings for GNOME using the GObject Introspection Repository.
 
 ## Requirements
 
-GirFFI should work on MRI 1.9, 2.0, and 2.1, JRuby in 1.9 mode, and on
+GirFFI should work on MRI 1.9.3, 2.0, and 2.1, JRuby in 1.9 or 2.0 mode, and on
 Rubinius.
 
 You will also need gobject-introspection installed with some
diff --git a/Rakefile b/Rakefile
index 972d9b4..c3c8286 100644
--- a/Rakefile
+++ b/Rakefile
@@ -9,14 +9,6 @@ end
 
 MyGemHelper.install_tasks
 
-begin
-  require 'repl_rake'
-  ReplRake.setup
-rescue LoadError
-end
-
 load 'tasks/test.rake'
-load 'tasks/valgrind.rake'
-load 'tasks/yard.rake'
 
 task :default => 'test:all'
diff --git a/TODO.md b/TODO.md
index cd8400c..f2ff784 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,5 +1,7 @@
 # TODO
 
+MAKE CONSTRUCTOR_WRAP CHECK TYPES?
+
 ## Memory managment
 
 GirFFI does not attempt to free any memory at the moment, or lower the
@@ -8,6 +10,8 @@ reference count of any objects it gets from GObject. This task therefore involve
 - Free non-GObject pointers as needed (at garbage-collection time)
 - Lower reference count of GObjects (at garbage-collection time)
 
+**Use memory_profiler to check memory use (https://github.com/SamSaffron/memory_profiler)**
+
 ## Refactorings
 
 These in the order they occured to me, and may therefore be fixed in any order.
diff --git a/checksums.yaml.gz b/checksums.yaml.gz
deleted file mode 100644
index 8423d9b..0000000
Binary files a/checksums.yaml.gz and /dev/null differ
diff --git a/examples/demo_ffi_inherited_layout.rb b/examples/demo_ffi_inherited_layout.rb
deleted file mode 100644
index 2b1b047..0000000
--- a/examples/demo_ffi_inherited_layout.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# Demonstration program for FFI functionality.
-#
-# Show what happens if we call layout again in a subclass. This works in
-# JRuby, but not in MRI (gives warnings with ffi 0.6.3, is explicitely
-# forbidden later).
-#
-require 'ffi'
-
-class Foo < FFI::Struct
-  layout :a, :int, :b, :int
-end
-
-class Bar < Foo
-  layout :p, Foo, :c, :int
-end
-
-bar = Bar.new
-foo = Foo.new(bar.to_ptr)
-foo[:a] = 20
-puts "bar[:p][:a] = #{bar[:p][:a]}"
-
diff --git a/examples/demo_ffi_nested_struct.rb b/examples/demo_ffi_nested_struct.rb
deleted file mode 100644
index bda9104..0000000
--- a/examples/demo_ffi_nested_struct.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# Demonstration program for FFI functionality.
-#
-# Basic demo of nested struct. Works in MRI, YARV, and JRuby. Does not work
-# in Rubinius.
-#
-require 'ffi'
-
-module LibTest
-  class Foo < FFI::Struct
-    layout :a, :int, :b, :int
-  end
-
-  class Bar < FFI::Struct
-    layout :f, Foo, :g, :int
-  end
-end
-puts LibTest::Bar.members.inspect
diff --git a/examples/demo_ffi_safe_inherited_layout.rb b/examples/demo_ffi_safe_inherited_layout.rb
deleted file mode 100644
index fbe83ab..0000000
--- a/examples/demo_ffi_safe_inherited_layout.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# Demonstrate safe inheritance with layout.
-#
-# Uses nested Struct class to separate inheritance from FFI::Struct from
-# main inheritance structure. Works with MRI and JRuby, without warnings.
-
-require 'ffi'
-require 'forwardable'
-
-class Foo
-  extend Forwardable
-  def_delegators :@struct, :[], :to_ptr
-
-  class Struct < FFI::Struct
-    layout :a, :int, :b, :int
-  end
-
-  def initialize(ptr=nil)
-    @struct = ptr.nil? ?
-      self.ffi_structure.new :
-      self.ffi_structure.new(ptr)
-  end
-
-  def ffi_structure
-    self.class.ffi_structure
-  end
-
-  class << self
-    def ffi_structure
-      self.const_get(:Struct)
-    end
-  end
-end
-
-class Bar < Foo
-  class Struct < FFI::Struct
-    layout :p, Foo.ffi_structure, :c, :int
-  end
-end
-
-bar = Bar.new
-bar[:p][:a] = 20
-foo = Foo.new(bar.to_ptr)
-puts foo[:a]
diff --git a/examples/hard_coded.rb b/examples/hard_coded.rb
deleted file mode 100644
index 9e1f93c..0000000
--- a/examples/hard_coded.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-# Hard-code FFI-based Gtk+ test program. Nothing is generated here.
-require 'ffi'
-module GObject
-
-  module Lib
-    extend FFI::Library
-    CALLBACKS = []
-    ffi_lib "gobject-2.0"
-    callback :GCallback, [], :void
-    enum :GConnectFlags, [:AFTER, (1<<0), :SWAPPED, (1<<1)]
-
-    attach_function :g_signal_connect_data, [:pointer, :string, :GCallback,
-      :pointer, :pointer, :GConnectFlags], :ulong
-  end
-
-  def self.signal_connect_data gobject, signal, prc, data, destroy_data, connect_flags
-    Lib::CALLBACKS << prc
-    Lib.g_signal_connect_data gobject.to_ptr, signal, prc, data, destroy_data, connect_flags
-  end
-end
-
-module Gtk
-  module Lib
-    extend FFI::Library
-
-    ffi_lib "gtk-x11-2.0"
-    attach_function :gtk_init, [:pointer, :pointer], :void
-    attach_function :gtk_main, [], :void
-    attach_function :gtk_main_quit, [], :void
-
-    attach_function :gtk_widget_show, [:pointer], :pointer
-    attach_function :gtk_widget_destroy, [:pointer], :void
-    attach_function :gtk_container_add, [:pointer, :pointer], :void
-
-    enum :GtkWindowType, [:GTK_WINDOW_TOPLEVEL, :GTK_WINDOW_POPUP]
-    attach_function :gtk_window_new, [:GtkWindowType], :pointer
-    attach_function :gtk_button_new, [], :pointer
-    attach_function :gtk_button_new_with_label, [:string], :pointer
-    attach_function :gtk_label_new, [:string], :pointer
-  end
-
-  def self.init size, ary
-    argv = self.string_array_to_inoutptr ary
-    argc = self.int_to_inoutptr(size)
-
-    Lib.gtk_init argc, argv
-
-    outsize = self.outptr_to_int argc
-    outary = self.outptr_to_string_array argv, ary.nil? ? 0 : ary.size
-
-    return outsize, outary
-  end
-
-  def self.int_to_inoutptr val
-    ptr = FFI::MemoryPointer.new(:int)
-    ptr.write_int val
-    return ptr
-  end
-
-  # Note: This implementation would dump core if the garbage collector runs
-  # before the contents of the pointers is used.
-  def self.string_array_to_inoutptr ary
-    ptrs = ary.map {|a| FFI::MemoryPointer.from_string(a)}
-    block = FFI::MemoryPointer.new(:pointer, ptrs.length)
-    block.write_array_of_pointer ptrs
-    argv = FFI::MemoryPointer.new(:pointer)
-    argv.write_pointer block
-    argv
-  end
-
-  def self.outptr_to_int ptr
-    return ptr.read_int
-  end
-
-  def self.outptr_to_string_array ptr, size
-    block = ptr.read_pointer
-    ptrs = block.read_array_of_pointer(size)
-    return ptrs.map {|p| p.null? ? nil : p.read_string}
-  end
-
-  def self.main; Lib.gtk_main; end
-  def self.main_quit; Lib.gtk_main_quit; end
-
-  class Widget
-    def show
-      Lib.gtk_widget_show(@gobj)
-    end
-    def destroy
-      Lib.gtk_widget_destroy(@gobj)
-    end
-    def to_ptr
-      @gobj
-    end
-  end
-
-  class Container < Widget
-    def add widget
-      Lib.gtk_container_add self.to_ptr, widget.to_ptr
-    end
-  end
-
-  class Window < Container
-    def initialize type
-      @gobj = Lib.gtk_window_new(type)
-    end
-  end
-
-  class Button < Container
-    class << self
-      alias :real_new :new
-    end
-
-    def self.new *args
-      obj = self.real_new *args
-      ptr = Lib.gtk_button_new()
-      obj.instance_variable_set :@gobj, ptr
-      obj
-    end
-
-    def self.new_with_label text, *args
-      obj = self.real_new *args
-      ptr = Lib.gtk_button_new_with_label(text)
-      obj.instance_variable_set :@gobj, ptr
-      obj
-    end
-  end
-
-  class MyButton < Button
-    def initialize sym
-      puts "Initializing a #{self.class} with symbol #{sym}"
-    end
-
-    def self.new
-      super :foo
-    end
-
-    def self.new_with_label sym
-      super "Hello world", sym
-    end
-  end
-end
-
-(my_len, my_args) = Gtk.init ARGV.length + 1, [$0, *ARGV]
-p [my_len, my_args]
-win = Gtk::Window.new(:GTK_WINDOW_TOPLEVEL)
-
-#btn = Gtk::Button.new_with_label('Hello World')
-#btn = Gtk::MyButton.new
-btn = Gtk::MyButton.new_with_label :foobar2
-
-win.add btn
-
-quit_prc = Proc.new { Gtk.main_quit }
-
-# We can create callbacks with a different signature by using FFI::Function
-# directly.
-del_prc = FFI::Function.new(:bool, [:pointer, :pointer]) {|a, b|
-  puts "delete event occured"
-  true
-}
-GObject.signal_connect_data(win, "destroy", quit_prc, nil, nil, 0)
-GObject.signal_connect_data(win, "delete-event", del_prc, nil, nil, 0)
-GObject.signal_connect_data(btn, "clicked", Proc.new { win.destroy }, nil, nil, :SWAPPED)
-
-btn.show
-win.show
-Gtk.main
diff --git a/examples/leak_test.rb b/examples/leak_test.rb
deleted file mode 100644
index f9aac68..0000000
--- a/examples/leak_test.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# Test program to train Valgrind.
-require 'ffi'
-
-module LibC
-  extend FFI::Library
-  ffi_lib FFI::Library::LIBC
-
-  attach_function :malloc, [:size_t], :pointer
-end
-
-LibC.malloc 2000
diff --git a/examples/main_loop.rb b/examples/main_loop.rb
new file mode 100644
index 0000000..412f041
--- /dev/null
+++ b/examples/main_loop.rb
@@ -0,0 +1,12 @@
+require 'gir_ffi'
+
+main_loop = GLib::MainLoop.new nil, false
+
+Signal.trap("INT") do
+  if main_loop.is_running
+    main_loop.quit
+  end
+  exit
+end
+
+main_loop.run
diff --git a/examples/print_class.rb b/examples/print_class.rb
deleted file mode 100644
index 7b517c5..0000000
--- a/examples/print_class.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
-require 'gir_ffi'
-
-# File activesupport/lib/active_support/inflector/methods.rb, line 48
-def underscore(camel_cased_word)
-  word = camel_cased_word.to_s.dup
-  word.gsub!(/::/, '/')
-  word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
-  word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
-  word.tr!("-", "_")
-  word.downcase!
-  word
-end
-
-namespace = 'GObject'
-GirFFI.setup namespace
-modul = Kernel.const_get(namespace)
-
-gir = GObjectIntrospection::IRepository.default
-gir.require namespace, nil
-infos = gir.infos namespace
-
-main_file = File.open(File.join('.', "#{underscore(namespace)}.rb"), 'w')
-
-main_file.write "module #{namespace}\n"
-
-infos.each do |info|
-  case info.info_type
-  when :function
-    fbuilder = GirFFI::Builder::Function.new info, modul::Lib
-    main_file.write "\n"
-    main_file.write fbuilder.generate
-    main_file.write "\n"
-  when :object
-    main_file.write "class #{info.name} < #{info.parent.name}\n"
-    info.get_methods.each do |minfo|
-      main_file.write "\n"
-      unless minfo.method?
-        main_file.write "class << self\n"
-      end
-      if minfo.constructor?
-        main_file.write "# This method is a constructor\n"
-      end
-      main_file.write "# @return [#{minfo.return_type.tag}]\n"
-
-      fbuilder = GirFFI::Builder::Function.new minfo, modul::Lib
-      main_file.write fbuilder.generate
-      unless minfo.method?
-        main_file.write "end\n"
-      end
-      main_file.write "\n"
-    end
-    main_file.write "end\n"
-  else
-    puts "#{info.info_type}: #{info.name}\n"
-  end
-end
-
-main_file.write "end\n"
-main_file.close
-
diff --git a/gir_ffi.gemspec b/gir_ffi.gemspec
new file mode 100644
index 0000000..aae8b4b
--- /dev/null
+++ b/gir_ffi.gemspec
@@ -0,0 +1,41 @@
+# -*- encoding: utf-8 -*-
+require File.join(File.dirname(__FILE__), 'lib/gir_ffi/version.rb')
+
+Gem::Specification.new do |s|
+  s.name = "gir_ffi"
+  s.version = GirFFI::VERSION
+
+  s.summary = "FFI-based GObject binding using the GObject Introspection Repository"
+  s.required_ruby_version = %q{>= 1.9.3}
+
+  s.authors = ["Matijs van Zuijlen"]
+  s.email = ["matijs at matijs.net"]
+  s.homepage = "http://www.github.com/mvz/ruby-gir-ffi"
+
+  s.license = 'LGPL-2.1'
+
+  s.description = <<-DESC
+    GirFFI creates bindings for GObject-based libraries at runtime based on introspection
+    data provided by the GObject Introspection Repository (GIR) system. Bindings are created
+    at runtime and use FFI to interface with the C libraries. In cases where the GIR does not
+    provide enough or correct information to create sane bindings, overrides may be created.
+  DESC
+
+  s.files = Dir[ '{lib,test,tasks,examples}/**/*',
+                 "*.md",
+                 "*.gemspec",
+                 "Rakefile",
+                 "COPYING.LIB" ] & `git ls-files -z`.split("\0")
+
+  s.rdoc_options = ["--main", "README.md"]
+  s.extra_rdoc_files = ["DESIGN.md", "Changelog.md", "README.md", "TODO.md"]
+
+  s.add_runtime_dependency('ffi', ["~> 1.8"])
+  s.add_runtime_dependency('indentation', ["~> 0.1.1"])
+
+  s.add_development_dependency('minitest', ["~> 5.2"])
+  s.add_development_dependency('rr', ["~> 1.1.2"])
+  s.add_development_dependency('rake', ["~> 10.1"])
+
+  s.require_paths = ["lib"]
+end
diff --git a/lib/ffi-glib.rb b/lib/ffi-glib.rb
index 5c7d415..d8b12e3 100644
--- a/lib/ffi-glib.rb
+++ b/lib/ffi-glib.rb
@@ -10,6 +10,7 @@ require 'ffi-glib/error'
 require 'ffi-glib/hash_table'
 require 'ffi-glib/iconv'
 require 'ffi-glib/list'
+require 'ffi-glib/main_loop'
 require 'ffi-glib/ptr_array'
 require 'ffi-glib/s_list'
 require 'ffi-glib/strv'
diff --git a/lib/ffi-glib/array.rb b/lib/ffi-glib/array.rb
index 7fca018..21d7c88 100644
--- a/lib/ffi-glib/array.rb
+++ b/lib/ffi-glib/array.rb
@@ -44,20 +44,24 @@ module GLib
       Lib.g_array_get_element_size self
     end
 
-    alias element_size get_element_size
+    alias_method :element_size, :get_element_size
 
     def == other
       to_a == other.to_a
     end
 
-    def reset_typespec typespec
-      @element_type = typespec
-      check_element_size_match
+    def reset_typespec typespec = nil
+      if typespec
+        @element_type = typespec
+        check_element_size_match
+      else
+        @element_type = guess_element_type
+      end
       self
     end
 
     def self.from_enumerable elmtype, it
-      new(elmtype).tap {|arr| arr.append_vals it }
+      new(elmtype).tap { |arr| arr.append_vals it }
     end
 
     private
@@ -76,5 +80,14 @@ module GLib
         warn "WARNING: Element sizes do not match"
       end
     end
+
+    def guess_element_type
+      case get_element_size
+      when 1 then :uint8
+      when 2 then :uint16
+      when 4 then :uint32
+      when 8 then :uint64
+      end
+    end
   end
 end
diff --git a/lib/ffi-glib/array_methods.rb b/lib/ffi-glib/array_methods.rb
index 94b807f..f72fd33 100644
--- a/lib/ffi-glib/array_methods.rb
+++ b/lib/ffi-glib/array_methods.rb
@@ -3,7 +3,7 @@ module GLib
   module ArrayMethods
     # Re-implementation of the g_array_index and g_ptr_array_index macros
     def index idx
-      if idx >= length or idx < 0
+      if idx >= length || idx < 0
         raise IndexError, "Index #{idx} outside of bounds 0..#{length - 1}"
       end
       ptr = GirFFI::InOutPointer.new element_type, data_ptr + idx * element_size
diff --git a/lib/ffi-glib/list.rb b/lib/ffi-glib/list.rb
index 1acac47..29d35e4 100644
--- a/lib/ffi-glib/list.rb
+++ b/lib/ffi-glib/list.rb
@@ -8,7 +8,7 @@ module GLib
     include ListMethods
 
     def self.from_enumerable type, arr
-      arr.inject(new type) { |lst, val| lst.append val }
+      arr.reduce(new type) { |lst, val| lst.append val }
     end
 
     def append data
diff --git a/lib/ffi-glib/list_methods.rb b/lib/ffi-glib/list_methods.rb
index f320a14..716e3c0 100644
--- a/lib/ffi-glib/list_methods.rb
+++ b/lib/ffi-glib/list_methods.rb
@@ -55,7 +55,7 @@ module GLib
     end
 
     def next_element
-      return if !@current
+      return unless @current
       element = @current.head
       @current = @current.tail
       element
diff --git a/lib/ffi-glib/main_loop.rb b/lib/ffi-glib/main_loop.rb
new file mode 100644
index 0000000..8a56541
--- /dev/null
+++ b/lib/ffi-glib/main_loop.rb
@@ -0,0 +1,49 @@
+require 'singleton'
+
+GLib.load_class :MainLoop
+
+module GLib
+  # Overrides for GMainLoop, GLib's event loop
+  class MainLoop
+    # Class encapsulationg logic for running an idle handler to make Ruby code
+    # run during GLib's event loop.
+    class ThreadEnabler
+      include Singleton
+
+      FRAMERATE = 25
+      DEFAULT_TIMEOUT = 1000 / FRAMERATE
+
+      def initialize timeout = DEFAULT_TIMEOUT
+        @timeout = timeout
+      end
+
+      def setup_idle_handler
+        @handler_id ||= GLib.timeout_add(GLib::PRIORITY_DEFAULT,
+                                         @timeout, handler_proc,
+                                         nil, nil)
+      end
+
+      private
+
+      def handler_proc
+        proc do
+          Thread.pass
+          true
+        end
+      end
+    end
+
+    def run_with_thread_enabler
+      case RUBY_ENGINE
+      when 'jruby'
+      when 'rbx'
+      else # 'ruby' most likely
+        ThreadEnabler.instance.setup_idle_handler
+      end
+      run_without_thread_enabler
+    end
+
+    alias_method :run_without_thread_enabler, :run
+    alias_method :run, :run_with_thread_enabler
+  end
+end
diff --git a/lib/ffi-glib/ptr_array.rb b/lib/ffi-glib/ptr_array.rb
index a7898b8..b0d8ed6 100644
--- a/lib/ffi-glib/ptr_array.rb
+++ b/lib/ffi-glib/ptr_array.rb
@@ -26,7 +26,7 @@ module GLib
     end
 
     def self.from_enumerable type, it
-      new(type).tap {|arr| arr.add_array it}
+      new(type).tap { |arr| arr.add_array it }
     end
 
     def self.add array, data
@@ -44,7 +44,7 @@ module GLib
     end
 
     def add_array ary
-      ary.each {|item| add item}
+      ary.each { |item| add item }
     end
 
     def data_ptr
diff --git a/lib/ffi-glib/s_list.rb b/lib/ffi-glib/s_list.rb
index 8b26637..9de1c9f 100644
--- a/lib/ffi-glib/s_list.rb
+++ b/lib/ffi-glib/s_list.rb
@@ -8,7 +8,7 @@ module GLib
     include ListMethods
 
     def self.from_enumerable type, arr
-      arr.reverse.inject(new type) { |lst, val| lst.prepend val }
+      arr.reverse.reduce(new type) { |lst, val| lst.prepend val }
     end
 
     def prepend data
diff --git a/lib/ffi-glib/variant.rb b/lib/ffi-glib/variant.rb
index 792c796..599ab0b 100644
--- a/lib/ffi-glib/variant.rb
+++ b/lib/ffi-glib/variant.rb
@@ -10,10 +10,10 @@ module GLib
     end
 
     def self.constructor_wrap ptr
-      super.tap {|variant| variant.ref }
+      super.tap(&:ref)
     end
 
-    alias get_string_without_override get_string
-    alias get_string get_string_with_override
+    alias_method :get_string_without_override, :get_string
+    alias_method :get_string, :get_string_with_override
   end
 end
diff --git a/lib/ffi-gobject.rb b/lib/ffi-gobject.rb
index d922721..7ba6d2a 100644
--- a/lib/ffi-gobject.rb
+++ b/lib/ffi-gobject.rb
@@ -15,22 +15,6 @@ require 'gir_ffi/builders/user_defined_builder'
 
 # Module representing GLib's GObject namespace.
 module GObject
-  def self.object_ref obj
-    Lib.g_object_ref obj.to_ptr
-  end
-
-  def self.object_ref_sink obj
-    Lib.g_object_ref_sink obj.to_ptr
-  end
-
-  def self.object_unref obj
-    Lib.g_object_unref obj.to_ptr
-  end
-
-  def self.object_is_floating obj
-    Lib.g_object_is_floating obj.to_ptr
-  end
-
   def self.type_from_instance_pointer inst_ptr
     return nil if inst_ptr.null?
     klsptr = inst_ptr.get_pointer 0
@@ -70,12 +54,12 @@ module GObject
     return_gvalue
   end
 
-  def self.signal_connect object, detailed_signal, data=nil, &block
+  def self.signal_connect object, detailed_signal, data = nil, &block
     raise ArgumentError, "Block needed" unless block_given?
     signal_name, _ = detailed_signal.split('::')
     sig_info = object.class.find_signal signal_name
 
-    closure = sig_info.wrap_in_closure {|*args| block.call(*args << data) }
+    closure = sig_info.wrap_in_closure { |*args| block.call(*args << data) }
 
     # TODO: Provide _after variant
     signal_connect_closure object, detailed_signal, closure, false
@@ -96,12 +80,10 @@ module GObject
 
   # NOTE: This Lib module is set up in `gir_ffi-base/gobject/lib.rb`.
   module Lib
-    attach_function :g_object_ref, [:pointer], :void
     attach_function :g_object_ref_sink, [:pointer], :void
-    attach_function :g_object_unref, [:pointer], :void
-    attach_function :g_object_is_floating, [:pointer], :bool
 
     attach_function :g_array_get_type, [], :size_t
+    attach_function :g_byte_array_get_type, [], :size_t
     attach_function :g_hash_table_get_type, [], :size_t
     attach_function :g_strv_get_type, [], :size_t
 
@@ -117,6 +99,7 @@ module GObject
   end
 
   TYPE_ARRAY = Lib.g_array_get_type
+  TYPE_BYTE_ARRAY = Lib.g_byte_array_get_type
   TYPE_HASH_TABLE = Lib.g_hash_table_get_type
   TYPE_STRV = Lib.g_strv_get_type
 end
diff --git a/lib/ffi-gobject/initially_unowned.rb b/lib/ffi-gobject/initially_unowned.rb
index 6e71148..ecaa1b7 100644
--- a/lib/ffi-gobject/initially_unowned.rb
+++ b/lib/ffi-gobject/initially_unowned.rb
@@ -7,7 +7,7 @@ module GObject
     # Wrapping method used in constructors. For InitiallyUnowned and
     # descendants, this needs to sink the object's floating reference.
     def self.constructor_wrap ptr
-      super.tap {|obj| ::GObject.object_ref_sink obj}
+      super.tap { |obj| ::GObject::Lib.g_object_ref_sink obj }
     end
   end
 end
diff --git a/lib/ffi-gobject/object.rb b/lib/ffi-gobject/object.rb
index ad72897..590a388 100644
--- a/lib/ffi-gobject/object.rb
+++ b/lib/ffi-gobject/object.rb
@@ -3,22 +3,21 @@ GObject.load_class :Object
 module GObject
   # Overrides for GObject, GObject's generic base class.
   class Object
-
     setup_method "new"
 
     # TODO: Generate accessor methods from GIR at class definition time
     def method_missing method, *args
-      if respond_to?("get_#{method}")
-        return send("get_#{method}", *args)
-      end
-      if method.to_s =~ /(.*)=$/ && respond_to?("set_#{$1}")
-        return send("set_#{$1}", *args)
+      getter_name = "get_#{method}"
+      return send(getter_name, *args) if respond_to?(getter_name)
+      if method.to_s =~ /(.*)=$/
+        setter_name = "set_#{Regexp.last_match[1]}"
+        return send(setter_name, *args) if respond_to?(setter_name)
       end
       super
     end
 
-    def signal_connect event, &block
-      GObject.signal_connect(self, event, &block)
+    def signal_connect event, data = nil, &block
+      GObject.signal_connect(self, event, data, &block)
     end
 
     setup_instance_method "get_property"
@@ -62,11 +61,14 @@ module GObject
       GObject::ObjectClass.wrap(to_ptr.get_pointer 0)
     end
 
-    alias get_property_without_override get_property
-    alias get_property get_property_with_override
+    alias_method :get_property_without_override, :get_property
+    alias_method :get_property, :get_property_with_override
+
+    alias_method :set_property_without_override, :set_property
+    alias_method :set_property, :set_property_with_override
 
-    alias set_property_without_override set_property
-    alias set_property set_property_with_override
+    setup_instance_method 'is_floating'
+    alias_method :floating?, :is_floating
 
     private
 
diff --git a/lib/ffi-gobject/ruby_closure.rb b/lib/ffi-gobject/ruby_closure.rb
index 798a2eb..748a85b 100644
--- a/lib/ffi-gobject/ruby_closure.rb
+++ b/lib/ffi-gobject/ruby_closure.rb
@@ -32,16 +32,17 @@ module GObject
 
       closure = wrap(new_simple(self::Struct.size, nil).to_ptr)
       closure.block = block
-      closure.set_marshal Proc.new {|*args| marshaller(*args)}
+      closure.set_marshal proc { |*args| marshaller(*args) }
 
       closure
     end
 
     def self.marshaller closure, return_value, param_values, _invocation_hint, _marshal_data
+      # TODO: Improve by registering RubyClosure as a GObject type
       rclosure = wrap(closure.to_ptr)
       param_values ||= []
 
-      args = param_values.map {|value| value.get_value }
+      args = param_values.map(&:get_value)
 
       result = rclosure.invoke_block(*args)
 
diff --git a/lib/ffi-gobject/value.rb b/lib/ffi-gobject/value.rb
index d716120..802ad0c 100644
--- a/lib/ffi-gobject/value.rb
+++ b/lib/ffi-gobject/value.rb
@@ -5,10 +5,7 @@ module GObject
   class Value
     # TODO: Give more generic name
     def set_ruby_value val
-      if current_gtype == 0
-        init_for_ruby_value val
-      end
-
+      init_for_ruby_value val if current_gtype == 0
       set_value val
     end
 
@@ -35,25 +32,22 @@ module GObject
       TYPE_VARIANT => [:get_variant,       :set_variant]
     }
 
-    def value= val
-      set_value val
-    end
-
     def set_value val
       send set_method, val
-      self
     end
 
+    alias_method :value=, :set_value
+
     CLASS_TO_GTYPE_MAP = {
-      true => TYPE_BOOLEAN,
-      false => TYPE_BOOLEAN,
+      TrueClass => TYPE_BOOLEAN,
+      FalseClass => TYPE_BOOLEAN,
       Integer => TYPE_INT,
       String => TYPE_STRING
     }
 
     def init_for_ruby_value val
       CLASS_TO_GTYPE_MAP.each do |klass, type|
-        if klass === val
+        if val.is_a? klass
           init type
           return self
         end
@@ -88,7 +82,7 @@ module GObject
 
     # TODO: Give more generic name
     def self.wrap_ruby_value val
-      new.set_ruby_value val
+      new.tap { |gv| gv.set_ruby_value val }
     end
 
     def self.from val
@@ -104,7 +98,7 @@ module GObject
 
     def self.for_g_type g_type
       return nil if g_type == TYPE_NONE
-      new.tap {|it| it.init g_type }
+      new.tap { |it| it.init g_type }
     end
 
     # TODO: Combine with wrap_ruby_value
@@ -131,7 +125,7 @@ module GObject
     end
 
     def check_type_compatibility val
-      if !GObject::Value.type_compatible(GObject.type_from_instance(val), current_gtype)
+      unless GObject::Value.type_compatible(GObject.type_from_instance(val), current_gtype)
         raise ArgumentError, "#{val.class} is incompatible with #{current_gtype_name}"
       end
     end
@@ -142,6 +136,8 @@ module GObject
         GLib::Strv.wrap boxed
       when TYPE_HASH_TABLE
         GLib::HashTable.wrap [:gpointer, :gpointer], boxed
+      when TYPE_ARRAY
+        GLib::Array.wrap nil, boxed
       else
         current_gtype_class.wrap(boxed) unless boxed.null?
       end
@@ -157,7 +153,7 @@ module GObject
 
     def method_map_entry
       METHOD_MAP[current_gtype] || METHOD_MAP[current_fundamental_type] ||
-        fail("No method map entry for #{current_gtype_name}")
+        raise("No method map entry for #{current_gtype_name}")
     end
   end
 end
diff --git a/lib/ffi-gobject_introspection/i_base_info.rb b/lib/ffi-gobject_introspection/i_base_info.rb
index 637a20b..e978406 100644
--- a/lib/ffi-gobject_introspection/i_base_info.rb
+++ b/lib/ffi-gobject_introspection/i_base_info.rb
@@ -2,7 +2,7 @@ module GObjectIntrospection
   # Wraps GIBaseInfo struct, the base \type for all info types.
   # Decendant types will be implemented as needed.
   class IBaseInfo
-    def initialize ptr, lib=Lib
+    def initialize ptr, lib = Lib
       raise ArgumentError, "ptr must not be null" if ptr.null?
 
       unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
@@ -94,7 +94,7 @@ module GObjectIntrospection
     end
 
     def safe_namespace
-      namespace.gsub(/^(.)/) { $1.upcase }
+      namespace.gsub(/^./, &:upcase)
     end
 
     def container
@@ -112,7 +112,7 @@ module GObjectIntrospection
     end
 
     def == other
-      Lib.g_base_info_equal @gobj, other.to_ptr
+      other.is_a?(IBaseInfo) && Lib.g_base_info_equal(@gobj, other)
     end
   end
 end
diff --git a/lib/ffi-gobject_introspection/i_constant_info.rb b/lib/ffi-gobject_introspection/i_constant_info.rb
index db920af..7904015 100644
--- a/lib/ffi-gobject_introspection/i_constant_info.rb
+++ b/lib/ffi-gobject_introspection/i_constant_info.rb
@@ -2,21 +2,25 @@ module GObjectIntrospection
   # Wraps a GIConstantInfo struct; represents a constant.
   class IConstantInfo < IBaseInfo
     TYPE_TAG_TO_UNION_MEMBER = {
-      gint8:   :v_int8,
-      gint16:  :v_int16,
-      gint32:  :v_int32,
-      gint64:  :v_int64,
-      guint8:  :v_uint8,
-      guint16: :v_uint16,
-      guint32: :v_uint32,
-      guint64: :v_uint64,
-      gdouble: :v_double,
-      utf8:    :v_string
+      gboolean: :v_boolean,
+      gint8:    :v_int8,
+      gint16:   :v_int16,
+      gint32:   :v_int32,
+      gint64:   :v_int64,
+      guint8:   :v_uint8,
+      guint16:  :v_uint16,
+      guint32:  :v_uint32,
+      guint64:  :v_uint64,
+      gdouble:  :v_double,
+      utf8:     :v_string
     }
 
     def value
-      if type_tag == :utf8
+      case type_tag
+      when :utf8
         raw_value.force_encoding("utf-8")
+      when :gboolean
+        raw_value != 0
       else
         raw_value
       end
diff --git a/lib/ffi-gobject_introspection/i_interface_info.rb b/lib/ffi-gobject_introspection/i_interface_info.rb
index 9c7f70a..6bb68a6 100644
--- a/lib/ffi-gobject_introspection/i_interface_info.rb
+++ b/lib/ffi-gobject_introspection/i_interface_info.rb
@@ -23,6 +23,7 @@ module GObjectIntrospection
 
     ##
     build_array_method :properties, :property
+    build_finder_method :find_property, :n_properties
 
     def get_n_methods
       Lib.g_interface_info_get_n_methods @gobj
@@ -80,6 +81,5 @@ module GObjectIntrospection
     def iface_struct
       IStructInfo.wrap(Lib.g_interface_info_get_iface_struct @gobj)
     end
-
   end
 end
diff --git a/lib/ffi-gobject_introspection/i_repository.rb b/lib/ffi-gobject_introspection/i_repository.rb
index 825855c..9889561 100644
--- a/lib/ffi-gobject_introspection/i_repository.rb
+++ b/lib/ffi-gobject_introspection/i_repository.rb
@@ -72,7 +72,7 @@ module GObjectIntrospection
       Lib.g_type_tag_to_string type
     end
 
-    def require namespace, version=nil, flags=0
+    def require namespace, version = nil, flags = 0
       errpp = FFI::MemoryPointer.new(:pointer).write_pointer nil
 
       Lib.g_irepository_require @gobj, namespace, version, flags, errpp
diff --git a/lib/ffi-gobject_introspection/lib.rb b/lib/ffi-gobject_introspection/lib.rb
index 0bf976c..faa693c 100644
--- a/lib/ffi-gobject_introspection/lib.rb
+++ b/lib/ffi-gobject_introspection/lib.rb
@@ -7,7 +7,7 @@ module GObjectIntrospection
     ffi_lib "girepository-1.0"
 
     # IRepository
-    enum :IRepositoryLoadFlags, [:LAZY, (1<<0)]
+    enum :IRepositoryLoadFlags, [:LAZY, (1 << 0)]
 
     attach_function :g_irepository_get_default, [], :pointer
     attach_function :g_irepository_prepend_search_path, [:string], :void
diff --git a/lib/gir_ffi-base/glib/strv.rb b/lib/gir_ffi-base/glib/strv.rb
index 3751f79..135adee 100644
--- a/lib/gir_ffi-base/glib/strv.rb
+++ b/lib/gir_ffi-base/glib/strv.rb
@@ -17,7 +17,8 @@ module GLib
     end
 
     def each
-      reset_iterator or return
+      return if @ptr.null?
+      reset_iterator
       while (ptr = next_ptr)
         yield ptr.read_string
       end
@@ -30,7 +31,6 @@ module GLib
     private
 
     def reset_iterator
-      return if @ptr.null?
       @offset = 0
     end
 
diff --git a/lib/gir_ffi.rb b/lib/gir_ffi.rb
index 466d985..e20117e 100644
--- a/lib/gir_ffi.rb
+++ b/lib/gir_ffi.rb
@@ -20,7 +20,7 @@ require 'gir_ffi/version'
 # Main module containing classes and modules needed for generating GLib and
 # GObject bindings.
 module GirFFI
-  def self.setup module_name, version=nil
+  def self.setup module_name, version = nil
     module_name = module_name.to_s
     GirFFI::Builder.build_module module_name, version
   end
diff --git a/lib/gir_ffi/arg_helper.rb b/lib/gir_ffi/arg_helper.rb
index 2d2729e..812dcb9 100644
--- a/lib/gir_ffi/arg_helper.rb
+++ b/lib/gir_ffi/arg_helper.rb
@@ -20,7 +20,7 @@ module GirFFI
       def fetch ptr
         return if ptr.null?
         key = ptr.address
-        if @store.has_key? key
+        if @store.key? key
           @store[key]
         else
           ptr
@@ -74,7 +74,7 @@ module GirFFI
 
     def self.cast_uint32_to_int32 val
       if val >= 0x80000000
-        -(0x100000000-val)
+        -(0x100000000 - val)
       else
         val
       end
diff --git a/lib/gir_ffi/builder.rb b/lib/gir_ffi/builder.rb
index 741c03d..04e9ab6 100644
--- a/lib/gir_ffi/builder.rb
+++ b/lib/gir_ffi/builder.rb
@@ -21,7 +21,7 @@ module GirFFI
       build_class info
     end
 
-    def self.build_module namespace, version=nil
+    def self.build_module namespace, version = nil
       Builders::ModuleBuilder.new(namespace, version).generate
     end
 
diff --git a/lib/gir_ffi/builders/argument_builder.rb b/lib/gir_ffi/builders/argument_builder.rb
index b70d54b..ebbb1ff 100644
--- a/lib/gir_ffi/builders/argument_builder.rb
+++ b/lib/gir_ffi/builders/argument_builder.rb
@@ -9,37 +9,39 @@ module GirFFI
     # Implements building pre- and post-processing statements for arguments.
     class ArgumentBuilder < BaseArgumentBuilder
       def method_argument_name
-        if has_input_value? && !is_array_length_parameter?
-          name
-        end
+        name if has_input_value? && !array_length_parameter?
       end
 
       def post_converted_name
         @post_converted_name ||= if has_post_conversion?
                                    new_variable
                                  else
-                                   callarg
+                                   call_argument_name
                                  end
       end
 
       def return_value_name
         if has_output_value?
-          post_converted_name unless is_array_length_parameter?
+          post_converted_name unless array_length_parameter?
         end
       end
 
+      def capture_variable_name
+        nil
+      end
+
       def pre_conversion
         pr = []
         case direction
         when :in
           pr << fixed_array_size_check if needs_size_check?
-          pr << array_length_assignment if is_array_length_parameter?
-          pr << "#{callarg} = #{ingoing_convertor.conversion}"
+          pr << array_length_assignment if array_length_parameter?
+          pr << "#{call_argument_name} = #{ingoing_convertor.conversion}"
         when :inout
           pr << fixed_array_size_check if needs_size_check?
-          pr << array_length_assignment if is_array_length_parameter?
+          pr << array_length_assignment if array_length_parameter?
           pr << out_parameter_preparation
-          pr << "#{callarg}.set_value #{ingoing_convertor.conversion}"
+          pr << "#{call_argument_name}.set_value #{ingoing_convertor.conversion}"
         when :out
           pr << out_parameter_preparation
         end
@@ -58,11 +60,11 @@ module GirFFI
       private
 
       def has_post_conversion?
-        has_output_value? && !is_caller_allocated_object?
+        has_output_value? && !caller_allocated_object?
       end
 
       def output_value
-        base = "#{callarg}.to_value"
+        base = "#{call_argument_name}.to_value"
         if needs_out_conversion?
           CToRubyConvertor.new(@type_info, base, length_argument_name).conversion
         elsif allocated_by_them?
@@ -88,7 +90,7 @@ module GirFFI
         length_arg && length_arg.post_converted_name
       end
 
-      def is_array_length_parameter?
+      def array_length_parameter?
         @array_arg
       end
 
@@ -120,7 +122,7 @@ module GirFFI
       end
 
       def out_parameter_preparation
-        value = if is_caller_allocated_object?
+        value = if caller_allocated_object?
                   if specialized_type_tag == :array
                     "#{argument_class_name}.new #{type_info.element_type.inspect}"
                   else
@@ -129,18 +131,18 @@ module GirFFI
                 else
                   "GirFFI::InOutPointer.for #{type_info.tag_or_class.inspect}"
                 end
-        "#{callarg} = #{value}"
+        "#{call_argument_name} = #{value}"
       end
 
-      def is_caller_allocated_object?
-        [ :struct, :array ].include?(specialized_type_tag) &&
+      def caller_allocated_object?
+        [:struct, :array].include?(specialized_type_tag) &&
           @arginfo.caller_allocates?
       end
 
       def ingoing_convertor
         if skipped?
           NullConvertor.new("0")
-        elsif is_closure
+        elsif closure?
           ClosureToPointerConvertor.new(name)
         elsif @type_info.needs_ruby_to_c_conversion_for_functions?
           RubyToCConvertor.new(@type_info, name)
diff --git a/lib/gir_ffi/builders/argument_builder_collection.rb b/lib/gir_ffi/builders/argument_builder_collection.rb
index 8eb5f82..1a63e14 100644
--- a/lib/gir_ffi/builders/argument_builder_collection.rb
+++ b/lib/gir_ffi/builders/argument_builder_collection.rb
@@ -5,23 +5,21 @@ module GirFFI
     # and parameter and variable names for use by function builders.
     class ArgumentBuilderCollection
       attr_reader :return_value_builder
-      attr_reader :argument_builders
 
       def initialize return_value_builder, argument_builders, options = {}
         @receiver_builder = options[:receiver_builder]
-        @argument_builders = argument_builders
+        @error_argument_builder = options[:error_argument_builder]
+        @base_argument_builders = argument_builders
         @return_value_builder = return_value_builder
-        self.class.set_up_argument_relations argument_builders
-        @argument_builders.unshift @receiver_builder if @receiver_builder
+        set_up_argument_relations
       end
 
       def parameter_preparation
-        argument_builders.sort_by.with_index {|arg, i|
-          [arg.type_info.array_length, i] }.map(&:pre_conversion).flatten
+        builders_for_pre_conversion.map(&:pre_conversion).flatten
       end
 
       def return_value_conversion
-        all_builders.map(&:post_conversion).flatten
+        builders_for_post_conversion.map(&:post_conversion).flatten
       end
 
       def capture_variable_names
@@ -34,22 +32,39 @@ module GirFFI
       end
 
       def method_argument_names
-        @method_argument_names ||= argument_builders.map(&:method_argument_name)
+        @method_argument_names ||= argument_builders.map(&:method_argument_name).compact
       end
 
       def return_value_name
-        return_value_builder.return_value_name if return_value_builder.is_relevant?
+        return_value_builder.return_value_name if return_value_builder.relevant?
       end
 
-      def self.set_up_argument_relations argument_builders
-        argument_builders.each do |arg|
+      def return_value_names
+        @return_value_names ||= all_builders.map(&:return_value_name).compact
+      end
+
+      def has_return_values?
+        return_value_names.any?
+      end
+
+      private
+
+      def argument_builders
+        @argument_builders ||= @base_argument_builders.dup.tap do |builders|
+          builders.unshift @receiver_builder if @receiver_builder
+          builders.push @error_argument_builder if @error_argument_builder
+        end
+      end
+
+      def set_up_argument_relations
+        @base_argument_builders.each do |arg|
           if (idx = arg.arginfo.closure) >= 0
-            argument_builders[idx].is_closure = true
+            @base_argument_builders[idx].closure = true
           end
         end
-        argument_builders.each do |bldr|
+        all_builders.each do |bldr|
           if (idx = bldr.array_length_idx) >= 0
-            other = argument_builders[idx]
+            other = @base_argument_builders[idx]
 
             bldr.length_arg = other
             other.array_arg = bldr
@@ -57,11 +72,31 @@ module GirFFI
         end
       end
 
-      private
-
       def all_builders
         @all_builders ||= [return_value_builder] + argument_builders
       end
+
+      def builders_for_pre_conversion
+        @builders_for_pre_conversion ||=
+          sorted_base_argument_builders.dup.tap do |builders|
+            builders.unshift @receiver_builder if @receiver_builder
+            builders.push @error_argument_builder if @error_argument_builder
+          end
+      end
+
+      def builders_for_post_conversion
+        @builders_for_post_conversion ||=
+          sorted_base_argument_builders.dup.tap do |builders|
+            builders.unshift @receiver_builder if @receiver_builder
+            builders.unshift @error_argument_builder if @error_argument_builder
+            builders.push return_value_builder
+          end
+      end
+
+      def sorted_base_argument_builders
+        @sorted_base_argument_builders ||= @base_argument_builders.
+          sort_by.with_index { |arg, i| [arg.array_length_idx, i] }
+      end
     end
   end
 end
diff --git a/lib/gir_ffi/builders/base_argument_builder.rb b/lib/gir_ffi/builders/base_argument_builder.rb
index eca45d5..32b650e 100644
--- a/lib/gir_ffi/builders/base_argument_builder.rb
+++ b/lib/gir_ffi/builders/base_argument_builder.rb
@@ -4,17 +4,27 @@ module GirFFI
     # classes are used by FunctionBuilder to create the code that
     # processes each argument before and after the actual function call.
     class BaseArgumentBuilder
-      KEYWORDS = [
-        "alias", "and", "begin", "break", "case", "class", "def", "do",
-        "else", "elsif", "end", "ensure", "false", "for", "if", "in",
-        "module", "next", "nil", "not", "or", "redo", "rescue", "retry",
-        "return", "self", "super", "then", "true", "undef", "unless",
-        "until", "when", "while", "yield"
-      ]
+      KEYWORDS = %w(
+        alias and begin break case class def do
+        else elsif end ensure false for if in
+        module next nil not or redo rescue retry
+        return self super then true undef unless
+        until when while yield
+      )
 
       attr_reader :arginfo
       attr_accessor :length_arg, :array_arg
-      attr_accessor :is_closure
+
+      # TODO: closure unfortunately means two things in GLib: a closure
+      # argument (user_data), and the Closure class (a callable object). Make
+      # the distinction more explicit in GirFFI.
+      def closure?
+        @is_closure
+      end
+
+      def closure= arg
+        @is_closure = arg
+      end
 
       def initialize var_gen, arginfo
         @var_gen = var_gen
@@ -58,8 +68,8 @@ module GirFFI
         end
       end
 
-      def callarg
-        @callarg ||= new_variable
+      def call_argument_name
+        @call_argument_name ||= new_variable
       end
 
       def new_variable
diff --git a/lib/gir_ffi/builders/base_type_builder.rb b/lib/gir_ffi/builders/base_type_builder.rb
index 6727d34..94115a1 100644
--- a/lib/gir_ffi/builders/base_type_builder.rb
+++ b/lib/gir_ffi/builders/base_type_builder.rb
@@ -1,7 +1,6 @@
 require 'gir_ffi/builder_helper'
 
 module GirFFI
-
   # Base class for type builders.
   class BaseTypeBuilder
     include BuilderHelper
@@ -13,12 +12,14 @@ module GirFFI
     end
 
     def build_class
-      unless defined? @klass
-        instantiate_class
-      end
+      instantiate_class unless defined? @klass
       @klass
     end
 
+    def instantiate_class
+      setup_class unless already_set_up
+    end
+
     attr_reader :info
 
     private
@@ -28,7 +29,7 @@ module GirFFI
     end
 
     def lib
-      @lib ||= namespace_module.const_get :Lib
+      @lib ||= namespace_module::Lib
     end
 
     def setup_constants
diff --git a/lib/gir_ffi/builders/callback_argument_builder.rb b/lib/gir_ffi/builders/callback_argument_builder.rb
index 17ee193..b83c49c 100644
--- a/lib/gir_ffi/builders/callback_argument_builder.rb
+++ b/lib/gir_ffi/builders/callback_argument_builder.rb
@@ -29,9 +29,9 @@ module GirFFI
       def pre_conversion
         case direction
         when :in
-          [ "#{pre_converted_name} = #{pre_convertor.conversion}" ]
+          ["#{pre_converted_name} = #{pre_convertor.conversion}"]
         when :out
-          [ "#{pre_converted_name} = #{out_parameter_preparation}" ]
+          ["#{pre_converted_name} = #{out_parameter_preparation}"]
         when :error
           [
             "#{pre_converted_name} = #{out_parameter_preparation}",
@@ -43,7 +43,7 @@ module GirFFI
       def post_conversion
         case direction
         when :out
-          [ outgoing_post_conversion ]
+          [outgoing_post_conversion]
         when :error
           [
             "rescue => #{result_name}",
@@ -62,7 +62,7 @@ module GirFFI
       end
 
       def pre_convertor
-        @pre_convertor ||= if is_closure
+        @pre_convertor ||= if closure?
                              ClosureConvertor.new(method_argument_name)
                            elsif needs_c_to_ruby_conversion?
                              CToRubyConvertor.new(type_info,
@@ -92,7 +92,7 @@ module GirFFI
       def out_parameter_preparation
         type_spec = type_info.tag_or_class
         if allocated_by_us?
-          "GirFFI::InOutPointer.new(#{type_spec[1].inspect})" +
+          "GirFFI::InOutPointer.new(#{type_spec[1].inspect})" \
             ".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }"
         else
           "GirFFI::InOutPointer.new(#{type_spec.inspect}, #{method_argument_name})"
diff --git a/lib/gir_ffi/builders/callback_builder.rb b/lib/gir_ffi/builders/callback_builder.rb
index 3252c80..4603a8d 100644
--- a/lib/gir_ffi/builders/callback_builder.rb
+++ b/lib/gir_ffi/builders/callback_builder.rb
@@ -8,10 +8,6 @@ module GirFFI
     # attached to the appropriate namespace module, and will be defined
     # as a callback for FFI.
     class CallbackBuilder < BaseTypeBuilder
-      def instantiate_class
-        setup_class unless already_set_up
-      end
-
       def setup_class
         setup_callback
         setup_constants
diff --git a/lib/gir_ffi/builders/callback_return_value_builder.rb b/lib/gir_ffi/builders/callback_return_value_builder.rb
index 2a7243e..1a1f1b4 100644
--- a/lib/gir_ffi/builders/callback_return_value_builder.rb
+++ b/lib/gir_ffi/builders/callback_return_value_builder.rb
@@ -6,14 +6,12 @@ module GirFFI
     # Implements building post-processing statements for return values of
     # callbacks.
     class CallbackReturnValueBuilder < BaseArgumentBuilder
-      def is_relevant?
-        !is_void_return_value? && !arginfo.skip?
+      def relevant?
+        !void_return_value? && !arginfo.skip?
       end
 
       def capture_variable_name
-        if is_relevant?
-          @capture_variable_name ||= new_variable
-        end
+        @capture_variable_name ||= new_variable if relevant?
       end
 
       def post_converted_name
@@ -25,17 +23,15 @@ module GirFFI
       end
 
       def return_value_name
-        if is_relevant?
-          post_converted_name unless array_arg
-        end
+        post_converted_name if has_return_value_name?
       end
 
       def post_conversion
         if has_post_conversion?
           if type_info.flattened_tag == :object
-            [ "#{post_converted_name} = #{post_convertor.conversion}.to_ptr" ]
+            ["#{post_converted_name} = #{post_convertor.conversion}.to_ptr"]
           else
-            [ "#{post_converted_name} = #{post_convertor.conversion}" ]
+            ["#{post_converted_name} = #{post_convertor.conversion}"]
           end
         else
           []
@@ -52,9 +48,13 @@ module GirFFI
         @post_convertor ||= RubyToCConvertor.new(type_info, capture_variable_name)
       end
 
-      def is_void_return_value?
+      def void_return_value?
         specialized_type_tag == :void && !type_info.pointer?
       end
+
+      def has_return_value_name?
+        relevant? && !array_arg
+      end
     end
   end
 end
diff --git a/lib/gir_ffi/builders/constant_builder.rb b/lib/gir_ffi/builders/constant_builder.rb
index d0a9cb2..137c0fd 100644
--- a/lib/gir_ffi/builders/constant_builder.rb
+++ b/lib/gir_ffi/builders/constant_builder.rb
@@ -6,10 +6,8 @@ module GirFFI
     # triggered by a missing constant in the parent namespace.  The
     # constant will be attached to the appropriate namespace module.
     class ConstantBuilder < BaseTypeBuilder
-      private
-
-      def instantiate_class
-        @klass = optionally_define_constant namespace_module, @classname do
+      def build_class
+        @klass ||= optionally_define_constant namespace_module, @classname do
           info.value
         end
       end
diff --git a/lib/gir_ffi/builders/enum_builder.rb b/lib/gir_ffi/builders/enum_builder.rb
index 8de3143..ee5791e 100644
--- a/lib/gir_ffi/builders/enum_builder.rb
+++ b/lib/gir_ffi/builders/enum_builder.rb
@@ -20,14 +20,8 @@ module GirFFI
         }.flatten
       end
 
-      def instantiate_class
-        @enum = optionally_define_constant klass, :Enum do
-          lib.enum(enum_sym, value_spec)
-        end
-        setup_class unless already_set_up
-      end
-
       def setup_class
+        setup_ffi_enum
         klass.extend superclass
         setup_constants
         stub_methods
@@ -38,6 +32,12 @@ module GirFFI
         @klass ||= get_or_define_module namespace_module, @classname
       end
 
+      def setup_ffi_enum
+        @enum = optionally_define_constant klass, :Enum do
+          lib.enum(enum_sym, value_spec)
+        end
+      end
+
       def setup_inspect
         klass.instance_eval <<-EOS
           def self.inspect
diff --git a/lib/gir_ffi/builders/error_argument_builder.rb b/lib/gir_ffi/builders/error_argument_builder.rb
index 6138b1d..77cd8dc 100644
--- a/lib/gir_ffi/builders/error_argument_builder.rb
+++ b/lib/gir_ffi/builders/error_argument_builder.rb
@@ -6,12 +6,24 @@ module GirFFI
     # arguments are not part of the introspected signature, but their
     # presence is indicated by the 'throws' attribute of the function.
     class ErrorArgumentBuilder < BaseArgumentBuilder
-      def pre
-        [ "#{callarg} = FFI::MemoryPointer.new(:pointer).write_pointer nil" ]
+      def method_argument_name
+        nil
       end
 
-      def post
-        [ "GirFFI::ArgHelper.check_error(#{callarg})" ]
+      def return_value_name
+        nil
+      end
+
+      def capture_variable_name
+        nil
+      end
+
+      def pre_conversion
+        ["#{call_argument_name} = FFI::MemoryPointer.new(:pointer).write_pointer nil"]
+      end
+
+      def post_conversion
+        ["GirFFI::ArgHelper.check_error(#{call_argument_name})"]
       end
     end
   end
diff --git a/lib/gir_ffi/builders/field_builder.rb b/lib/gir_ffi/builders/field_builder.rb
index bc43b29..1b8c07f 100644
--- a/lib/gir_ffi/builders/field_builder.rb
+++ b/lib/gir_ffi/builders/field_builder.rb
@@ -27,11 +27,7 @@ module GirFFI
       end
 
       def setup_setter
-        container_class.class_eval setter_def if is_writable_field?
-      end
-
-      def is_writable_field?
-        info.writable?
+        container_class.class_eval setter_def if info.writable?
       end
 
       def getter_def
@@ -43,7 +39,7 @@ module GirFFI
         <<-CODE.reset_indentation
         def #{info.name}
           #{field_ptr} = @struct.to_ptr + #{info.offset}
-          #{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag_or_class.inspect}, #{field_ptr})
+          #{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag_or_class}, #{field_ptr})
           #{builder.capture_variable_name} = #{typed_ptr}.to_value
           #{builder.post_conversion.join("\n")}
           #{builder.return_value_name}
@@ -60,21 +56,17 @@ module GirFFI
         <<-CODE.reset_indentation
         def #{info.name}= #{builder.method_argument_name}
           #{field_ptr} = @struct.to_ptr + #{info.offset}
-          #{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag_or_class.inspect}, #{field_ptr})
+          #{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag_or_class}, #{field_ptr})
           #{builder.pre_conversion.join("\n          ")}
-          #{typed_ptr}.set_value #{builder.callarg}
+          #{typed_ptr}.set_value #{builder.call_argument_name}
         end
         CODE
       end
 
       private
 
-      def struct_class
-        container_class::Struct
-      end
-
       def field_type_tag_or_class
-        @field_type_tag_or_class ||= info.field_type.tag_or_class
+        @field_type_tag_or_class ||= info.field_type.tag_or_class.inspect
       end
 
       def container_class
@@ -89,10 +81,6 @@ module GirFFI
         @container_info ||= info.container
       end
 
-      def field_symbol
-        @info.name.to_sym
-      end
-
       def field_type
         @field_type ||= @info.field_type
       end
diff --git a/lib/gir_ffi/builders/function_builder.rb b/lib/gir_ffi/builders/function_builder.rb
index af8f6c3..a1d3db9 100644
--- a/lib/gir_ffi/builders/function_builder.rb
+++ b/lib/gir_ffi/builders/function_builder.rb
@@ -1,10 +1,10 @@
+require 'gir_ffi/variable_name_generator'
 require 'gir_ffi/builders/argument_builder'
 require 'gir_ffi/return_value_info'
 require 'gir_ffi/error_argument_info'
 require 'gir_ffi/builders/return_value_builder'
 require 'gir_ffi/builders/error_argument_builder'
-require 'gir_ffi/builders/null_argument_builder'
-require 'gir_ffi/variable_name_generator'
+require 'gir_ffi/builders/method_template'
 
 module GirFFI
   module Builders
@@ -13,116 +13,66 @@ module GirFFI
     class FunctionBuilder
       def initialize info
         @info = info
-      end
-
-      def generate
         vargen = GirFFI::VariableNameGenerator.new
-        @argument_builders = @info.args.map {|arg| ArgumentBuilder.new vargen, arg }
+        @argument_builders = @info.args.map { |arg| ArgumentBuilder.new vargen, arg }
+        return_value_info = ReturnValueInfo.new(@info.return_type, @info.skip_return?)
         @return_value_builder = ReturnValueBuilder.new(vargen,
-                                                       ReturnValueInfo.new(@info.return_type, @info.skip_return?),
+                                                       return_value_info,
                                                        @info.constructor?)
-
-        set_up_argument_relations
-        setup_error_argument vargen
-
-        filled_out_template
-      end
-
-      private
-
-      def lib_module_name
-        "#{@info.safe_namespace}::Lib"
-      end
-
-      def set_up_argument_relations
-        alldata = @argument_builders.dup << @return_value_builder
-
-        alldata.each do |data|
-          if (idx = data.array_length_idx) >= 0
-            other_data = @argument_builders[idx]
-            data.length_arg = other_data
-            other_data.array_arg = data
-          end
-        end
-
-        @argument_builders.each do |data|
-          if (idx = data.arginfo.closure) >= 0
-            @argument_builders[idx].is_closure = true
-          end
-        end
+        @argument_builder_collection = ArgumentBuilderCollection.new(
+          @return_value_builder, @argument_builders,
+          error_argument_builder: error_argument(vargen))
+        @template = MethodTemplate.new(self, @argument_builder_collection)
       end
 
-      def setup_error_argument vargen
-        @errarg = if @info.throws?
-                    ErrorArgumentBuilder.new vargen, ErrorArgumentInfo.new
-                  else
-                    NullArgumentBuilder.new
-                  end
-      end
-
-      def filled_out_template
-        meta = @info.method? ? '' : "self."
-
-        code = "def #{meta}#{@info.safe_name} #{method_arguments.join(', ')}\n"
-        code << method_body
-        code << "\nend\n"
-      end
-
-      def method_body
-        lines = preparation << function_call << post_processing
-        lines << "return #{return_values.join(', ')}" if has_return_values?
-        lines.flatten.join("\n").indent
+      def generate
+        @template.method_definition
       end
 
-      def function_call
-        "#{capture}#{lib_module_name}.#{@info.symbol} #{function_call_arguments.join(', ')}"
+      def method_name
+        @info.safe_name
       end
 
       def method_arguments
-        @argument_builders.map(&:method_argument_name).compact
+        @argument_builder_collection.method_argument_names
       end
 
-      def function_call_arguments
-        ca = @argument_builders.map(&:callarg)
-        ca << @errarg.callarg
-        ca.unshift "self" if @info.method?
-        ca.compact
+      def preparation
+        []
       end
 
-      def preparation
-        pr = @argument_builders.map(&:pre_conversion)
-        pr << @errarg.pre
-        pr.flatten
+      def invocation
+        "#{lib_name}.#{@info.symbol} #{function_call_arguments.join(', ')}"
       end
 
-      def capture
-        if has_capture?
-          "#{@return_value_builder.capture_variable_name} = "
+      def result
+        if @argument_builder_collection.has_return_values?
+          ["return #{@argument_builder_collection.return_value_names.join(', ')}"]
         else
-          ""
+          []
         end
       end
 
-      def post_processing
-        # FIXME: Sorting knows too much about internals of ArgumentBuilder.
-        args = @argument_builders.sort_by {|arg| arg.type_info.array_length}
-
-        result = args.map {|arg| arg.post_conversion}
-        result.unshift @errarg.post
-        result << @return_value_builder.post_conversion
+      def singleton_method?
+        !@info.method?
       end
 
-      def return_values
-        @return_values ||= ([@return_value_builder.return_value_name] +
-                            @argument_builders.map(&:return_value_name)).compact
+      private
+
+      def lib_name
+        "#{@info.safe_namespace}::Lib"
       end
 
-      def has_return_values?
-        !return_values.empty?
+      def error_argument vargen
+        if @info.throws?
+          ErrorArgumentBuilder.new vargen, ErrorArgumentInfo.new if @info.throws?
+        end
       end
 
-      def has_capture?
-        @return_value_builder.is_relevant?
+      def function_call_arguments
+        ca = @argument_builder_collection.call_argument_names
+        ca.unshift "self" if @info.method?
+        ca
       end
     end
   end
diff --git a/lib/gir_ffi/builders/interface_builder.rb b/lib/gir_ffi/builders/interface_builder.rb
index 0f1f230..263511e 100644
--- a/lib/gir_ffi/builders/interface_builder.rb
+++ b/lib/gir_ffi/builders/interface_builder.rb
@@ -11,17 +11,12 @@ module GirFFI
 
       private
 
-      # FIXME: The word 'class' is not really correct.
-      def instantiate_class
-        klass
-        setup_module unless already_set_up
-      end
-
       def klass
         @klass ||= get_or_define_module namespace_module, @classname
       end
 
-      def setup_module
+      # FIXME: The word 'class' is not really correct.
+      def setup_class
         klass.extend InterfaceBase
         setup_constants
         stub_methods
diff --git a/lib/gir_ffi/builders/mapping_method_builder.rb b/lib/gir_ffi/builders/mapping_method_builder.rb
index 95a89d1..1be81fc 100644
--- a/lib/gir_ffi/builders/mapping_method_builder.rb
+++ b/lib/gir_ffi/builders/mapping_method_builder.rb
@@ -1,6 +1,8 @@
+require 'gir_ffi/variable_name_generator'
 require 'gir_ffi/builders/callback_argument_builder'
 require 'gir_ffi/builders/callback_return_value_builder'
 require 'gir_ffi/builders/argument_builder_collection'
+require 'gir_ffi/builders/method_template'
 
 module GirFFI
   module Builders
@@ -9,43 +11,47 @@ module GirFFI
     # result from Ruby to C.
     class MappingMethodBuilder
       def self.for_callback argument_infos, return_value_info
-        vargen = VariableNameGenerator.new
-
-        argument_builders = argument_infos.map {|arg| CallbackArgumentBuilder.new vargen, arg }
-        return_value_builder = CallbackReturnValueBuilder.new(vargen, return_value_info)
-
-        new ArgumentBuilderCollection.new(return_value_builder, argument_builders)
+        new argument_infos, return_value_info
       end
 
       def self.for_vfunc receiver_info, argument_infos, return_value_info
-        vargen = VariableNameGenerator.new
+        new receiver_info, argument_infos, return_value_info
+      end
 
-        receiver_builder = CallbackArgumentBuilder.new vargen, receiver_info
-        argument_builders = argument_infos.map {|arg| CallbackArgumentBuilder.new vargen, arg }
-        return_value_builder = CallbackReturnValueBuilder.new(vargen, return_value_info)
+      def initialize receiver_info = nil, argument_infos, return_value_info
+        receiver_builder = make_argument_builder receiver_info if receiver_info
+        argument_builders = argument_infos.map { |info| make_argument_builder info }
+        return_value_builder =
+          CallbackReturnValueBuilder.new(variable_generator, return_value_info)
 
-        new ArgumentBuilderCollection.new(return_value_builder, argument_builders,
-                                          receiver_builder: receiver_builder)
+        @argument_builder_collection =
+          ArgumentBuilderCollection.new(return_value_builder, argument_builders,
+                                        receiver_builder: receiver_builder)
+        @template = MethodTemplate.new(self, @argument_builder_collection)
       end
 
-      def initialize argument_builder_collection
-        @argument_builder_collection = argument_builder_collection
+      def method_definition
+        @template.method_definition
       end
 
-      def method_definition
-        code = "def self.call_with_argument_mapping(#{method_arguments.join(', ')})"
-        method_lines.each { |line| code << "\n  #{line}" }
-        code << "\nend\n"
+      def method_name
+        "call_with_argument_mapping"
+      end
+
+      def method_arguments
+        @method_arguments ||=
+          @argument_builder_collection.method_argument_names.dup.unshift('_proc')
+      end
+
+      def preparation
+        []
       end
 
-      def method_lines
-        @argument_builder_collection.parameter_preparation +
-          call_to_proc +
-          @argument_builder_collection.return_value_conversion +
-          return_value
+      def invocation
+        "_proc.call(#{call_argument_list})"
       end
 
-      def return_value
+      def result
         if (name = @argument_builder_collection.return_value_name)
           ["return #{name}"]
         else
@@ -53,19 +59,22 @@ module GirFFI
         end
       end
 
-      def call_to_proc
-        ["#{capture}_proc.call(#{@argument_builder_collection.call_argument_names.join(', ')})"]
+      def singleton_method?
+        true
       end
 
-      def capture
-        @capture ||= begin
-                       names = @argument_builder_collection.capture_variable_names
-                       names.any? ? "#{names.join(", ")} = " : ""
-                     end
+      private
+
+      def call_argument_list
+        @argument_builder_collection.call_argument_names.join(', ')
       end
 
-      def method_arguments
-        @method_arguments ||= @argument_builder_collection.method_argument_names.dup.unshift('_proc')
+      def variable_generator
+        @variable_generator ||= VariableNameGenerator.new
+      end
+
+      def make_argument_builder argument_info
+        CallbackArgumentBuilder.new variable_generator, argument_info
       end
     end
   end
diff --git a/lib/gir_ffi/builders/marshalling_method_builder.rb b/lib/gir_ffi/builders/marshalling_method_builder.rb
index d78ba09..3b048eb 100644
--- a/lib/gir_ffi/builders/marshalling_method_builder.rb
+++ b/lib/gir_ffi/builders/marshalling_method_builder.rb
@@ -1,6 +1,8 @@
+require 'gir_ffi/variable_name_generator'
 require 'gir_ffi/builders/closure_argument_builder'
 require 'gir_ffi/builders/callback_return_value_builder'
 require 'gir_ffi/builders/argument_builder_collection'
+require 'gir_ffi/builders/method_template'
 
 module GirFFI
   module Builders
@@ -9,35 +11,46 @@ module GirFFI
     # result from Ruby to C.
     class MarshallingMethodBuilder
       def self.for_signal receiver_info, argument_infos, return_value_info
-        vargen = VariableNameGenerator.new
+        new receiver_info, argument_infos, return_value_info
+      end
 
-        receiver_builder = ClosureArgumentBuilder.new vargen, receiver_info
-        argument_builders = argument_infos.map {|arg| ClosureArgumentBuilder.new vargen, arg }
-        return_value_builder = CallbackReturnValueBuilder.new(vargen, return_value_info)
+      def initialize receiver_info, argument_infos, return_value_info
+        receiver_builder = make_argument_builder receiver_info
+        argument_builders = argument_infos.map { |arg| make_argument_builder arg }
+        return_value_builder =
+          CallbackReturnValueBuilder.new(variable_generator, return_value_info)
 
-        new ArgumentBuilderCollection.new(return_value_builder, argument_builders,
-                                          receiver_builder: receiver_builder)
+        @argument_builder_collection =
+          ArgumentBuilderCollection.new(return_value_builder, argument_builders,
+                                        receiver_builder: receiver_builder)
+        @template = MethodTemplate.new(self, @argument_builder_collection)
       end
 
-      def initialize argument_builder_collection
-        @argument_builder_collection = argument_builder_collection
+      def method_definition
+        @template.method_definition
       end
 
-      def method_definition
-        code = "def self.marshaller(#{marshaller_arguments.join(', ')})"
-        method_lines.each { |line| code << "\n  #{line}" }
-        code << "\nend\n"
+      def method_name
+        "marshaller"
+      end
+
+      def method_arguments
+        %w(closure return_value param_values _invocation_hint _marshal_data)
       end
 
-      def method_lines
-        param_values_unpack +
-          @argument_builder_collection.parameter_preparation +
-          call_to_closure +
-          @argument_builder_collection.return_value_conversion +
-          return_value
+      def preparation
+        if param_names.size == 1
+          ["#{param_names.first} = param_values.first.get_value_plain"]
+        else
+          ["#{param_names.join(", ")} = param_values.map(&:get_value_plain)"]
+        end
+      end
+
+      def invocation
+        "wrap(closure.to_ptr).invoke_block(#{call_argument_list})"
       end
 
-      def return_value
+      def result
         if (name = @argument_builder_collection.return_value_name)
           ["return_value.set_value #{name}"]
         else
@@ -45,28 +58,26 @@ module GirFFI
         end
       end
 
-      def call_to_closure
-        ["#{capture}wrap(closure.to_ptr).invoke_block(#{@argument_builder_collection.call_argument_names.join(', ')})"]
+      def singleton_method?
+        true
       end
 
-      def param_values_unpack
-        ["#{method_arguments.join(", ")} = param_values.map(&:get_value_plain)" ]
+      private
+
+      def call_argument_list
+        @argument_builder_collection.call_argument_names.join(', ')
       end
 
-      def capture
-        @capture ||= begin
-                       names = @argument_builder_collection.capture_variable_names
-                       names.any? ? "#{names.join(", ")} = " : ""
-                     end
+      def param_names
+        @param_names ||= @argument_builder_collection.method_argument_names
       end
 
-      def method_arguments
-        # FIXME: Don't add _ if method_argument_names has more than one element
-        @method_arguments ||= @argument_builder_collection.method_argument_names.dup.push('_')
+      def variable_generator
+        @variable_generator ||= VariableNameGenerator.new
       end
 
-      def marshaller_arguments
-        %w(closure return_value param_values _invocation_hint _marshal_data)
+      def make_argument_builder argument_info
+        ClosureArgumentBuilder.new variable_generator, argument_info
       end
     end
   end
diff --git a/lib/gir_ffi/builders/method_template.rb b/lib/gir_ffi/builders/method_template.rb
new file mode 100644
index 0000000..e3c98f4
--- /dev/null
+++ b/lib/gir_ffi/builders/method_template.rb
@@ -0,0 +1,81 @@
+module GirFFI
+  module Builders
+    # Encapsulates the general structure of generated methods, consisting of a
+    # preparation phase where arguments are converted to the form needed by the
+    # main call of the method, the main call itself, a post-processing phase
+    # where the return values and any 'out' arguments of the main call are
+    # converted into a form suitable for returning, and finally the returning
+    # of said values to the caller.
+    #
+    # The different method builders collaborate with MethodTemplate to build
+    # the desired method.
+    class MethodTemplate
+      def initialize builder, argument_builder_collection
+        @builder = builder
+        @argument_builder_collection = argument_builder_collection
+      end
+
+      def method_definition
+        code = "def #{qualified_method_name}"
+        code << "(#{method_arguments.join(', ')})" if method_arguments.any?
+        method_lines.each { |line| code << "\n  #{line}" }
+        code << "\nend\n"
+      end
+
+      private
+
+      def qualified_method_name
+        "#{@builder.singleton_method? ? 'self.' : ''}#{@builder.method_name}"
+      end
+
+      def method_arguments
+        @builder.method_arguments
+      end
+
+      def method_lines
+        method_preparation +
+          parameter_preparation +
+          invocation +
+          return_value_conversion +
+          result
+      end
+
+      def method_preparation
+        @builder.preparation
+      end
+
+      def parameter_preparation
+        @argument_builder_collection.parameter_preparation
+      end
+
+      def invocation
+        if result_name_list.empty?
+          plain_invocation
+        else
+          capturing_invocation
+        end
+      end
+
+      def return_value_conversion
+        @argument_builder_collection.return_value_conversion
+      end
+
+      def result
+        @builder.result
+      end
+
+      def result_name_list
+        @result_name_list ||=
+          @argument_builder_collection.capture_variable_names.join(", ")
+      end
+
+      def capturing_invocation
+        ["#{result_name_list} = #{@builder.invocation}"]
+      end
+
+      def plain_invocation
+        [@builder.invocation]
+      end
+    end
+  end
+end
diff --git a/lib/gir_ffi/builders/module_builder.rb b/lib/gir_ffi/builders/module_builder.rb
index 7250d5a..0fe3719 100644
--- a/lib/gir_ffi/builders/module_builder.rb
+++ b/lib/gir_ffi/builders/module_builder.rb
@@ -10,11 +10,11 @@ module GirFFI
     class ModuleBuilder
       include BuilderHelper
 
-      def initialize namespace, version=nil
+      def initialize namespace, version = nil
         @namespace = namespace
         @version = version
         # FIXME: Pass safe namespace as an argument
-        @safe_namespace = @namespace.gsub(/^(.)/) { $1.upcase }
+        @safe_namespace = @namespace.gsub(/^./, &:upcase)
       end
 
       def generate
@@ -34,8 +34,8 @@ module GirFFI
       def build_namespaced_class classname
         info = gir.find_by_name @namespace, classname.to_s
         unless info
-          raise NameError.new(
-            "Class #{classname} not found in namespace #{@namespace}")
+          raise NameError,
+            "Class #{classname} not found in namespace #{@namespace}"
         end
         Builder.build_class info
       end
@@ -70,7 +70,7 @@ module GirFFI
       end
 
       def already_set_up
-        @module.respond_to? :method_missing
+        @module.const_defined? :GIR_FFI_BUILDER
       end
 
       def setup_lib_for_ffi
diff --git a/lib/gir_ffi/builders/null_argument_builder.rb b/lib/gir_ffi/builders/null_argument_builder.rb
deleted file mode 100644
index 9128b3c..0000000
--- a/lib/gir_ffi/builders/null_argument_builder.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-module GirFFI
-  # Argument builder that does nothing. Implements the Null Object pattern.
-  class NullArgumentBuilder
-    def initialize *; end
-
-    def pre; []; end
-
-    def post; []; end
-
-    def callarg; end
-  end
-end
diff --git a/lib/gir_ffi/builders/null_builder.rb b/lib/gir_ffi/builders/null_builder.rb
deleted file mode 100644
index 0877777..0000000
--- a/lib/gir_ffi/builders/null_builder.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-module GirFFI
-  # Object Builder that does nothing. Implements the Null Object pattern.
-  class NullBuilder
-    def find_signal _
-      nil
-    end
-
-    def find_property _
-      nil
-    end
-  end
-end
diff --git a/lib/gir_ffi/builders/object_builder.rb b/lib/gir_ffi/builders/object_builder.rb
index 24d9aa6..dc280c8 100644
--- a/lib/gir_ffi/builders/object_builder.rb
+++ b/lib/gir_ffi/builders/object_builder.rb
@@ -9,18 +9,24 @@ module GirFFI
     class ObjectBuilder < RegisteredTypeBuilder
       include WithLayout
 
-      def find_signal signal_name
-        signal_definers.each do |inf|
-          sig = inf.find_signal signal_name
-          return sig if sig
+      # Dummy builder for the ObjectBase class
+      class ObjectBaseBuilder
+        def build_class
+          ObjectBase
+        end
+
+        def ancestor_infos
+          []
         end
-        superclass.find_signal signal_name or
+      end
+
+      def find_signal signal_name
+        seek_in_ancestor_infos { |info| info.find_signal signal_name } or
           raise "Signal #{signal_name} not found"
       end
 
       def find_property property_name
-        info.find_property property_name or
-          superclass.find_property property_name or
+        seek_in_ancestor_infos { |info| info.find_property property_name } or
           raise "Property #{property_name} not found"
       end
 
@@ -28,6 +34,10 @@ module GirFFI
         @object_class_struct ||= Builder.build_class object_class_struct_info
       end
 
+      def ancestor_infos
+        @ancestor_infos ||= [info] + info.interfaces + parent_ancestor_infos
+      end
+
       private
 
       def setup_class
@@ -48,24 +58,29 @@ module GirFFI
         FFI::Struct
       end
 
-      def parent
-        unless defined? @parent
-          pr = info.parent
-          if pr.nil? or (pr.safe_name == @classname and pr.namespace == @namespace)
-            @parent = nil
-          else
-            @parent = pr
-          end
+      def parent_info
+        unless defined? @parent_info
+          @parent_info = if (parent = info.parent) && parent != info
+                           parent
+                         end
         end
-        @parent
+        @parent_info
       end
 
       def superclass
-        @superclass ||= if parent
-                          Builder.build_class parent
-                        else
-                          ObjectBase
-                        end
+        @superclass ||= parent_builder.build_class
+      end
+
+      def parent_builder
+        @parent_builder ||= if parent_info
+                              Builders::TypeBuilder.builder_for(parent_info)
+                            else
+                              ObjectBaseBuilder.new
+                            end
+      end
+
+      def parent_ancestor_infos
+        @parent_ancestor_infos ||= parent_builder.ancestor_infos
       end
 
       def setup_property_accessors
@@ -99,10 +114,6 @@ module GirFFI
         end
       end
 
-      def signal_definers
-        [info] + info.interfaces
-      end
-
       def interfaces
         info.interfaces.map do |ifinfo|
           GirFFI::Builder.build_class ifinfo
@@ -112,6 +123,14 @@ module GirFFI
       def object_class_struct_info
         @object_class_struct_info ||= info.class_struct
       end
+
+      def seek_in_ancestor_infos
+        ancestor_infos.each do |info|
+          item = yield info
+          return item if item
+        end
+        nil
+      end
     end
   end
 end
diff --git a/lib/gir_ffi/builders/property_builder.rb b/lib/gir_ffi/builders/property_builder.rb
index ac1adb3..1710c45 100644
--- a/lib/gir_ffi/builders/property_builder.rb
+++ b/lib/gir_ffi/builders/property_builder.rb
@@ -23,6 +23,7 @@ module GirFFI
         container_class.class_eval setter_def
       end
 
+      # TODO: Fix argument builders so converting_getter_def can always be used.
       def getter_def
         case type_info.tag
         when :glist, :ghash
@@ -32,6 +33,7 @@ module GirFFI
         end
       end
 
+      # TODO: Fix argument builders so converting_setter_def can always be used.
       def setter_def
         case type_info.flattened_tag
         when :glist, :ghash, :strv
@@ -43,10 +45,12 @@ module GirFFI
 
       private
 
+      # TODO: Use a builder like MarshallingMethodBuilder
       def converting_getter_def
+        capture = getter_builder.capture_variable_name
         <<-CODE.reset_indentation
         def #{getter_name}
-          #{getter_builder.capture_variable_name} = get_property("#{property_name}").get_value_plain
+          #{capture} = get_property("#{property_name}").get_value_plain
           #{getter_builder.post_conversion.join("\n")}
           #{getter_builder.return_value_name}
         end
@@ -70,7 +74,7 @@ module GirFFI
         <<-CODE.reset_indentation
         def #{setter_name} value
           #{setter_builder.pre_conversion.join("\n")}
-          set_property("#{property_name}", #{setter_builder.callarg})
+          set_property("#{property_name}", #{setter_builder.call_argument_name})
         end
         CODE
       end
diff --git a/lib/gir_ffi/builders/registered_type_builder.rb b/lib/gir_ffi/builders/registered_type_builder.rb
index 11649ca..5f25e11 100644
--- a/lib/gir_ffi/builders/registered_type_builder.rb
+++ b/lib/gir_ffi/builders/registered_type_builder.rb
@@ -61,17 +61,13 @@ module GirFFI
         }
       end
 
-      def parent
+      def parent_info
         nil
       end
 
       def fields
         info.fields
       end
-
-      def superclass
-        ClassBase
-      end
     end
   end
 end
diff --git a/lib/gir_ffi/builders/return_value_builder.rb b/lib/gir_ffi/builders/return_value_builder.rb
index 8ba0e85..cc0e26b 100644
--- a/lib/gir_ffi/builders/return_value_builder.rb
+++ b/lib/gir_ffi/builders/return_value_builder.rb
@@ -7,17 +7,17 @@ module GirFFI
   module Builders
     # Implements building post-processing statements for return values.
     class ReturnValueBuilder < BaseArgumentBuilder
-      def initialize var_gen, arginfo, is_constructor = false
+      def initialize var_gen, arginfo, constructor_result = false
         super var_gen, arginfo
-        @is_constructor = is_constructor
+        @constructor_result = constructor_result
       end
 
-      def is_relevant?
-        !is_void_return_value? && !arginfo.skip?
+      def relevant?
+        !void_return_value? && !arginfo.skip?
       end
 
       def capture_variable_name
-        @capture_variable_name ||= new_variable
+        @capture_variable_name ||= new_variable if relevant?
       end
 
       def post_converted_name
@@ -29,32 +29,33 @@ module GirFFI
       end
 
       def return_value_name
-        if is_relevant?
-          post_converted_name unless array_arg
-        end
+        post_converted_name if has_return_value_name?
       end
 
       def post_conversion
+        # TODO: Avoid conditional by using NullConvertor
         if has_post_conversion?
-          [ "#{post_converted_name} = #{post_convertor.conversion}" ]
+          ["#{post_converted_name} = #{post_convertor.conversion}"]
         else
           []
         end
       end
 
-      attr_reader :is_constructor
-
       private
 
+      def constructor_result?
+        @constructor_result
+      end
+
       def has_post_conversion?
-        is_closure || is_constructor ||
+        closure? || constructor_result? ||
           type_info.needs_c_to_ruby_conversion_for_functions?
       end
 
       def post_convertor
-        @post_convertor ||= if is_closure
+        @post_convertor ||= if closure?
                               ClosureConvertor.new(capture_variable_name)
-                            elsif is_constructor
+                            elsif constructor_result?
                               ConstructorResultConvertor.new(capture_variable_name)
                             else
                               CToRubyConvertor.new(type_info,
@@ -67,9 +68,13 @@ module GirFFI
         length_arg && length_arg.post_converted_name
       end
 
-      def is_void_return_value?
+      def void_return_value?
         specialized_type_tag == :void && !type_info.pointer?
       end
+
+      def has_return_value_name?
+        relevant? && !array_arg
+      end
     end
   end
 end
diff --git a/lib/gir_ffi/builders/signal_closure_builder.rb b/lib/gir_ffi/builders/signal_closure_builder.rb
index 51c4476..9341abb 100644
--- a/lib/gir_ffi/builders/signal_closure_builder.rb
+++ b/lib/gir_ffi/builders/signal_closure_builder.rb
@@ -6,12 +6,9 @@ module GirFFI
     # Implements the creation of a closure class for handling a particular
     # signal. The type will be attached to the appropriate class.
     class SignalClosureBuilder < BaseTypeBuilder
-      def instantiate_class
-        unless already_set_up
-          setup_constants
-          klass.class_eval marshaller_definition
-        end
-        klass
+      def setup_class
+        setup_constants
+        klass.class_eval marshaller_definition
       end
 
       def setup_method _method
diff --git a/lib/gir_ffi/builders/type_builder.rb b/lib/gir_ffi/builders/type_builder.rb
index e5cf69c..938f1f7 100644
--- a/lib/gir_ffi/builders/type_builder.rb
+++ b/lib/gir_ffi/builders/type_builder.rb
@@ -29,7 +29,7 @@ module GirFFI
       }
 
       def self.build info
-        TYPE_MAP[info.info_type].new(info).build_class
+        builder_for(info).build_class
       end
 
       # TODO: Pull up to include :function and :module
diff --git a/lib/gir_ffi/builders/unintrospectable_builder.rb b/lib/gir_ffi/builders/unintrospectable_builder.rb
index 707ecce..7441139 100644
--- a/lib/gir_ffi/builders/unintrospectable_builder.rb
+++ b/lib/gir_ffi/builders/unintrospectable_builder.rb
@@ -6,10 +6,6 @@ module GirFFI
     # which no data is found in the GIR. Typically, these are created to
     # cast objects returned by a function that returns an interface.
     class UnintrospectableBuilder < ObjectBuilder
-      def instantiate_class
-        setup_class unless already_set_up
-      end
-
       def klass
         @klass ||= TypeBuilder::CACHE[target_gtype] ||= Class.new(superclass)
       end
@@ -26,7 +22,7 @@ module GirFFI
 
       private
 
-      def signal_definers
+      def ancestor_infos
         info.interfaces
       end
     end
diff --git a/lib/gir_ffi/builders/user_defined_builder.rb b/lib/gir_ffi/builders/user_defined_builder.rb
index d709901..2d96f67 100644
--- a/lib/gir_ffi/builders/user_defined_builder.rb
+++ b/lib/gir_ffi/builders/user_defined_builder.rb
@@ -9,37 +9,33 @@ module GirFFI
         @info = info
       end
 
-      def instantiate_class
-        if already_set_up
-          @gtype = klass.get_gtype
-        else
-          @gtype = GObject.type_register_static(parent_gtype.to_i,
-                                                info.g_name,
-                                                gobject_type_info, 0)
-          included_interfaces.each do |interface|
-            ifinfo = gobject_interface_info interface
-            GObject.type_add_interface_static @gtype, interface.get_gtype, ifinfo
-          end
-          setup_class
-          TypeBuilder::CACHE[@gtype] = klass
-        end
-      end
-
       def setup_class
+        register_type
         setup_layout
         setup_constants
         setup_property_accessors
         setup_constructor
+        TypeBuilder::CACHE[@gtype] = klass
       end
 
       def target_gtype
-        @gtype
+        @gtype ||= klass.get_gtype
       end
 
       private
 
-      def parent
-        @parent ||= gir.find_by_gtype(parent_gtype.to_i)
+      def register_type
+        @gtype = GObject.type_register_static(parent_gtype.to_i,
+                                              info.g_name,
+                                              gobject_type_info, 0)
+        included_interfaces.each do |interface|
+          ifinfo = gobject_interface_info interface
+          GObject.type_add_interface_static @gtype, interface.get_gtype, ifinfo
+        end
+      end
+
+      def parent_info
+        @parent_info ||= gir.find_by_gtype(parent_gtype.to_i)
       end
 
       def parent_gtype
@@ -47,7 +43,7 @@ module GirFFI
       end
 
       def interface_gtypes
-        included_interfaces.map {|interface| GType.new(interface.get_gtype) }
+        included_interfaces.map { |interface| GType.new(interface.get_gtype) }
       end
 
       def included_interfaces
@@ -121,7 +117,8 @@ module GirFFI
       end
 
       def setup_vfuncs object_class_ptr
-        super_class_struct = superclass.gir_ffi_builder.object_class_struct::Struct.new(object_class_ptr)
+        super_class_struct =
+          superclass.gir_ffi_builder.object_class_struct::Struct.new(object_class_ptr)
 
         info.vfunc_implementations.each do |impl|
           setup_vfunc super_class_struct, impl
@@ -141,7 +138,7 @@ module GirFFI
 
       def setup_vfunc super_class_struct, impl
         vfunc_name = impl.name
-        vfunc_info = parent.find_vfunc vfunc_name.to_s
+        vfunc_info = parent_info.find_vfunc vfunc_name.to_s
 
         if vfunc_info
           install_vfunc super_class_struct, vfunc_name, vfunc_info, impl.implementation
diff --git a/lib/gir_ffi/builders/vfunc_builder.rb b/lib/gir_ffi/builders/vfunc_builder.rb
index 042b4b8..5374a7b 100644
--- a/lib/gir_ffi/builders/vfunc_builder.rb
+++ b/lib/gir_ffi/builders/vfunc_builder.rb
@@ -12,12 +12,9 @@ module GirFFI
     # can serve as such an implementation in C. The class will be namespaced
     # inside class defining the vfunc.
     class VFuncBuilder < BaseTypeBuilder
-      def instantiate_class
-        unless already_set_up
-          setup_constants
-          klass.class_eval mapping_method_definition
-        end
-        klass
+      def setup_class
+        setup_constants
+        klass.class_eval mapping_method_definition
       end
 
       def klass
diff --git a/lib/gir_ffi/builders/with_layout.rb b/lib/gir_ffi/builders/with_layout.rb
index 8ba60ae..c4f3025 100644
--- a/lib/gir_ffi/builders/with_layout.rb
+++ b/lib/gir_ffi/builders/with_layout.rb
@@ -23,15 +23,15 @@ module GirFFI
       end
 
       def dummy_layout_specification
-        if parent
-          [:parent, superclass.const_get(:Struct), 0]
+        if parent_info
+          [:parent, superclass::Struct, 0]
         else
           [:dummy, :char, 0]
         end
       end
 
       def base_layout_specification
-        fields.map { |finfo| finfo.layout_specification }.flatten(1)
+        fields.map(&:layout_specification).flatten(1)
       end
 
       def setup_field_accessors
@@ -40,10 +40,6 @@ module GirFFI
         end
       end
 
-      def instantiate_class
-        setup_class unless already_set_up
-      end
-
       def klass
         @klass ||= get_or_define_class namespace_module, @classname, superclass
       end
diff --git a/lib/gir_ffi/callback_base.rb b/lib/gir_ffi/callback_base.rb
index b698cac..b684e4e 100644
--- a/lib/gir_ffi/callback_base.rb
+++ b/lib/gir_ffi/callback_base.rb
@@ -19,9 +19,14 @@ module GirFFI
     end
 
     def self.to_native value, _context
-      return nil unless value
-      return value if FFI::Function === value
-      value.to_native
+      case value
+      when CallbackBase
+        value.to_native
+      when FFI::Function
+        value
+      else
+        nil
+      end
     end
 
     def self.wrap ptr
@@ -43,8 +48,8 @@ module GirFFI
     end
 
     def self.wrap_in_callback_args_mapper prc
-      return nil unless prc
-      return prc if FFI::Function === prc
+      return unless prc
+
       new do |*args|
         call_with_argument_mapping(prc, *args)
       end
diff --git a/lib/gir_ffi/class_base.rb b/lib/gir_ffi/class_base.rb
index 420514a..8aad911 100644
--- a/lib/gir_ffi/class_base.rb
+++ b/lib/gir_ffi/class_base.rb
@@ -1,5 +1,4 @@
 require 'forwardable'
-require 'gir_ffi/builders/null_builder'
 require 'gir_ffi/registered_type_base'
 
 module GirFFI
@@ -12,13 +11,11 @@ module GirFFI
     attr_reader :struct
     def_delegators :@struct, :to_ptr
 
-    GIR_FFI_BUILDER = NullBuilder.new
-
-    def setup_and_call method, *arguments, &block
+    def setup_and_call method, arguments, &block
       method_name = self.class.try_in_ancestors(:setup_instance_method, method.to_s)
 
       unless method_name
-        raise RuntimeError, "Unable to set up instance method '#{method}' in #{self}"
+        raise "Unable to set up instance method '#{method}' in #{self}"
       end
 
       send method_name, *arguments, &block
@@ -30,11 +27,11 @@ module GirFFI
       other.class == self.class && to_ptr.address == other.to_ptr.address
     end
 
-    def self.setup_and_call method, *arguments, &block
+    def self.setup_and_call method, arguments, &block
       method_name = try_in_ancestors(:setup_method, method.to_s)
 
       unless method_name
-        raise RuntimeError, "Unable to set up method '#{method}' in #{self}"
+        raise "Unable to set up method '#{method}' in #{self}"
       end
 
       send method_name, *arguments, &block
@@ -74,9 +71,9 @@ module GirFFI
       # Wrap the passed pointer in an instance of the current class. Will not
       # do any casting to subtypes.
       def direct_wrap ptr
-        return nil if !ptr or ptr.null?
+        return nil if !ptr || ptr.null?
         obj = _real_new
-        obj.instance_variable_set :@struct, self::Struct.new(ptr.to_ptr)
+        obj.instance_variable_set :@struct, self::Struct.new(ptr)
         obj
       end
 
diff --git a/lib/gir_ffi/enum_base.rb b/lib/gir_ffi/enum_base.rb
index 08efc93..e41cf7d 100644
--- a/lib/gir_ffi/enum_base.rb
+++ b/lib/gir_ffi/enum_base.rb
@@ -38,11 +38,11 @@ module GirFFI
       from_native pointer.get_int32(0), nil
     end
 
-    def setup_and_call method, *arguments, &block
+    def setup_and_call method, arguments, &block
       result = setup_method method.to_s
 
       unless result
-        raise RuntimeError, "Unable to set up method #{method} in #{self}"
+        raise "Unable to set up method #{method} in #{self}"
       end
 
       send method, *arguments, &block
diff --git a/lib/gir_ffi/g_type.rb b/lib/gir_ffi/g_type.rb
index 987d7ec..514db35 100644
--- a/lib/gir_ffi/g_type.rb
+++ b/lib/gir_ffi/g_type.rb
@@ -1,25 +1,27 @@
-# Wrapper class providing extended functionality for a GType, which is normally
-# just a kind of integer
-class GirFFI::GType
-  def initialize gtype
-    @gtype = gtype
-  end
+module GirFFI
+  # Wrapper class providing extended functionality for a GType, which is
+  # normally just a kind of integer
+  class GType
+    def initialize gtype
+      @gtype = gtype
+    end
 
-  def to_i
-    @gtype
-  end
-  
-  def class_size
-    type_query.class_size
-  end
+    def to_i
+      @gtype
+    end
 
-  def instance_size
-    type_query.instance_size
-  end
+    def class_size
+      type_query.class_size
+    end
+
+    def instance_size
+      type_query.instance_size
+    end
 
-  private
+    private
 
-  def type_query
-    @type_query ||= GObject.type_query @gtype
+    def type_query
+      @type_query ||= GObject.type_query @gtype
+    end
   end
 end
diff --git a/lib/gir_ffi/in_out_pointer.rb b/lib/gir_ffi/in_out_pointer.rb
index dc16c60..12322d3 100644
--- a/lib/gir_ffi/in_out_pointer.rb
+++ b/lib/gir_ffi/in_out_pointer.rb
@@ -13,8 +13,6 @@ module GirFFI
       super ptr
     end
 
-    private :initialize
-
     # TODO: Create type classes that extract values from pointers.
     def to_value
       case value_ffi_type
@@ -58,11 +56,11 @@ module GirFFI
     end
 
     def self.for type
-      new(type).tap {|ptr| ptr.clear}
+      new(type).tap(&:clear)
     end
 
     def self.from type, value
-      new(type).tap {|ptr| ptr.set_value value}
+      new(type).tap { |ptr| ptr.set_value value }
     end
 
     private
diff --git a/lib/gir_ffi/in_pointer.rb b/lib/gir_ffi/in_pointer.rb
index ed2dc39..bfd97a9 100644
--- a/lib/gir_ffi/in_pointer.rb
+++ b/lib/gir_ffi/in_pointer.rb
@@ -4,7 +4,7 @@ module GirFFI
   # arrays, strings, or interfaces.
   class InPointer < FFI::Pointer
     def self.from_array type, ary
-      return if !ary
+      return unless ary
       case type
       when :utf8, :filename
         from_utf8_array ary
@@ -30,7 +30,7 @@ module GirFFI
     end
 
     def self.from type, val
-      return if !val
+      return unless val
       case type
       when :utf8, :filename
         from_utf8 val
@@ -47,22 +47,23 @@ module GirFFI
 
     class << self
       def from_closure_data obj
-        FFI::Pointer.new(obj.object_id).tap {|ptr|
-          ArgHelper::OBJECT_STORE.store(ptr, obj) }
+        FFI::Pointer.new(obj.object_id).tap do |ptr|
+          ArgHelper::OBJECT_STORE.store(ptr, obj)
+        end
       end
 
       private
 
       def from_utf8_array ary
-        from_basic_type_array :pointer, ary.map {|str| from_utf8 str}
+        from_basic_type_array :pointer, ary.map { |str| from_utf8 str }
       end
 
       def from_boolean_array ary
-        from_basic_type_array :int, ary.map {|val| val ? 1 : 0}
+        from_basic_type_array :int, ary.map { |val| val ? 1 : 0 }
       end
 
       def from_pointer_array type, ary
-        from_basic_type_array :pointer, ary.map {|elem| from type, elem }
+        from_basic_type_array :pointer, ary.map { |elem| from type, elem }
       end
 
       def from_gvalue_array type, ary
@@ -90,7 +91,7 @@ module GirFFI
       end
 
       def from_enum_array type, ary
-        from_basic_type_array :int32, ary.map {|sym| type.to_native sym, nil }
+        from_basic_type_array :int32, ary.map { |sym| type.to_native sym, nil }
       end
 
       def from_utf8 str
diff --git a/lib/gir_ffi/info_ext/i_callable_info.rb b/lib/gir_ffi/info_ext/i_callable_info.rb
index 7a4cc50..131addf 100644
--- a/lib/gir_ffi/info_ext/i_callable_info.rb
+++ b/lib/gir_ffi/info_ext/i_callable_info.rb
@@ -3,7 +3,7 @@ module GirFFI
     # Extensions for GObjectIntrospection::ICallableInfo needed by GirFFI
     module ICallableInfo
       def argument_ffi_types
-        args.map { |arg| arg.to_ffitype }
+        args.map(&:to_ffitype)
       end
     end
   end
diff --git a/lib/gir_ffi/info_ext/i_callback_info.rb b/lib/gir_ffi/info_ext/i_callback_info.rb
index 42d5495..641a63c 100644
--- a/lib/gir_ffi/info_ext/i_callback_info.rb
+++ b/lib/gir_ffi/info_ext/i_callback_info.rb
@@ -7,7 +7,7 @@ module GirFFI
       end
 
       def argument_ffi_types
-        args.map { |arg| arg.to_callback_ffitype }
+        args.map(&:to_callback_ffitype)
       end
 
       def return_ffi_type
diff --git a/lib/gir_ffi/info_ext/i_field_info.rb b/lib/gir_ffi/info_ext/i_field_info.rb
index d21880e..a9ed5a6 100644
--- a/lib/gir_ffi/info_ext/i_field_info.rb
+++ b/lib/gir_ffi/info_ext/i_field_info.rb
@@ -3,9 +3,7 @@ module GirFFI
     # Extensions for GObjectIntrospection::IFieldInfo needed by GirFFI
     module IFieldInfo
       def layout_specification
-        [ name.to_sym,
-          field_type.to_ffitype,
-          offset ]
+        [name.to_sym, field_type.to_ffitype, offset]
       end
     end
   end
diff --git a/lib/gir_ffi/info_ext/i_registered_type_info.rb b/lib/gir_ffi/info_ext/i_registered_type_info.rb
index 28d77d6..c290090 100644
--- a/lib/gir_ffi/info_ext/i_registered_type_info.rb
+++ b/lib/gir_ffi/info_ext/i_registered_type_info.rb
@@ -20,4 +20,5 @@ module GirFFI
   end
 end
 
-GObjectIntrospection::IRegisteredTypeInfo.send :include, GirFFI::InfoExt::IRegisteredTypeInfo
+GObjectIntrospection::IRegisteredTypeInfo.send :include,
+  GirFFI::InfoExt::IRegisteredTypeInfo
diff --git a/lib/gir_ffi/info_ext/i_signal_info.rb b/lib/gir_ffi/info_ext/i_signal_info.rb
index 9435183..9fe40bc 100644
--- a/lib/gir_ffi/info_ext/i_signal_info.rb
+++ b/lib/gir_ffi/info_ext/i_signal_info.rb
@@ -14,13 +14,13 @@ module GirFFI
         bldr.build_class.new(&block)
       end
 
-      # TODO: Use argument info to convert out arguments and array lengths.
       def arguments_to_gvalues instance, arguments
-        arg_values = args.zip(arguments).map do |info, arg|
-          info.argument_type.make_g_value.set_value(arg)
+        arg_g_values = args.map { |info| info.argument_type.make_g_value }
+        arg_g_values.zip(arguments).each do |g_value, arg|
+          g_value.set_value arg
         end
 
-        arg_values.unshift GObject::Value.wrap_instance(instance)
+        arg_g_values.unshift GObject::Value.wrap_instance(instance)
       end
 
       def gvalue_for_return_value
diff --git a/lib/gir_ffi/info_ext/i_type_info.rb b/lib/gir_ffi/info_ext/i_type_info.rb
index 529da75..6c6aebc 100644
--- a/lib/gir_ffi/info_ext/i_type_info.rb
+++ b/lib/gir_ffi/info_ext/i_type_info.rb
@@ -4,7 +4,6 @@ module GirFFI
   module InfoExt
     # Extensions for GObjectIntrospection::ITypeInfo needed by GirFFI
     module ITypeInfo
-
       def self.flattened_tag_to_gtype_map
         @flattened_tag_to_gtype_map ||= {
           array:    GObject::TYPE_ARRAY,
@@ -22,10 +21,11 @@ module GirFFI
 
       def g_type
         if tag == :interface
-          interface.g_type
+          return interface.g_type
+        elsif (type = ITypeInfo.flattened_tag_to_gtype_map[flattened_tag])
+          return type
         else
-          ITypeInfo.flattened_tag_to_gtype_map[flattened_tag] or
-            raise "Can't find type for #{flattened_tag} pointer? = #{pointer?}"
+          raise "Can't find GType for #{flattened_tag} pointer? = #{pointer?}"
         end
       end
 
@@ -36,7 +36,7 @@ module GirFFI
       def element_type
         case tag
         when :glist, :gslist, :array, :c
-          enumerable_element_type 
+          enumerable_element_type
         when :ghash
           dictionary_element_type
         else
@@ -197,7 +197,7 @@ module GirFFI
         subtype = param_type(index).to_ffitype
         if subtype == :pointer
           # NOTE: Don't use pointer directly to appease JRuby.
-          :"uint#{FFI.type_size(:pointer)*8}"
+          :"uint#{FFI.type_size(:pointer) * 8}"
         else
           subtype
         end
diff --git a/lib/gir_ffi/info_ext/i_vfunc_info.rb b/lib/gir_ffi/info_ext/i_vfunc_info.rb
index 7e4ddc5..b6b3ec8 100644
--- a/lib/gir_ffi/info_ext/i_vfunc_info.rb
+++ b/lib/gir_ffi/info_ext/i_vfunc_info.rb
@@ -4,7 +4,7 @@ module GirFFI
     # TODO: Merge implementation with ICallbackInfo and ISignalInfo extensions.
     module IVFuncInfo
       def argument_ffi_types
-        args.map { |arg| arg.to_callback_ffitype }.tap do |types|
+        args.map(&:to_callback_ffitype).tap do |types|
           types << :pointer if throws?
         end
       end
diff --git a/lib/gir_ffi/method_stubber.rb b/lib/gir_ffi/method_stubber.rb
index aaf5f5b..1dad5a3 100644
--- a/lib/gir_ffi/method_stubber.rb
+++ b/lib/gir_ffi/method_stubber.rb
@@ -9,7 +9,7 @@ module GirFFI
     def method_stub
       <<-STUB.reset_indentation
         def #{@info.method? ? '' : 'self.'}#{@info.safe_name} *args, &block
-          setup_and_call #{@info.name.to_sym.inspect}, *args, &block
+          setup_and_call "#{@info.name}", args, &block
         end
       STUB
     end
diff --git a/lib/gir_ffi/module_base.rb b/lib/gir_ffi/module_base.rb
index ac3983d..04c57b0 100644
--- a/lib/gir_ffi/module_base.rb
+++ b/lib/gir_ffi/module_base.rb
@@ -11,14 +11,15 @@ module GirFFI
       load_class(classname) || super
     end
 
+    # @deprecated The load_class method should always be used. Remove in 0.8.0
     def setup_class classname
       gir_ffi_builder.build_namespaced_class classname.to_s
     end
 
-    alias load_class setup_class
+    alias_method :load_class, :setup_class
 
     def gir_ffi_builder
-      const_get :GIR_FFI_BUILDER
+      self::GIR_FFI_BUILDER
     end
 
     def setup_method name
diff --git a/lib/gir_ffi/object_base.rb b/lib/gir_ffi/object_base.rb
index 7fa06d9..1ee1f3b 100644
--- a/lib/gir_ffi/object_base.rb
+++ b/lib/gir_ffi/object_base.rb
@@ -33,7 +33,7 @@ module GirFFI
       :pointer
     end
 
-    def self.copy_value_to_pointer value, pointer, offset=0
+    def self.copy_value_to_pointer value, pointer, offset = 0
       pointer.put_pointer offset, value.to_ptr
     end
 
diff --git a/lib/gir_ffi/struct_base.rb b/lib/gir_ffi/struct_base.rb
index 1d3a170..0fc67b0 100644
--- a/lib/gir_ffi/struct_base.rb
+++ b/lib/gir_ffi/struct_base.rb
@@ -21,7 +21,7 @@ module GirFFI
       pointer.to_ptr
     end
 
-    def self.copy_value_to_pointer value, pointer, offset=0
+    def self.copy_value_to_pointer value, pointer, offset = 0
       size = self::Struct.size
       pointer.put_bytes offset, value.to_ptr.read_bytes(size), 0, size
     end
diff --git a/lib/gir_ffi/type_base.rb b/lib/gir_ffi/type_base.rb
index 4fae939..760ae91 100644
--- a/lib/gir_ffi/type_base.rb
+++ b/lib/gir_ffi/type_base.rb
@@ -2,11 +2,11 @@ module GirFFI
   # Base module for all generated GLib types.
   module TypeBase
     def gir_ffi_builder
-      const_get :GIR_FFI_BUILDER
+      self::GIR_FFI_BUILDER
     end
 
     def gir_info
-      const_get :GIR_INFO
+      self::GIR_INFO
     end
   end
 end
diff --git a/lib/gir_ffi/unintrospectable_type_info.rb b/lib/gir_ffi/unintrospectable_type_info.rb
index 5a3cc07..531b260 100644
--- a/lib/gir_ffi/unintrospectable_type_info.rb
+++ b/lib/gir_ffi/unintrospectable_type_info.rb
@@ -1,3 +1,5 @@
+require 'gir_ffi/info_ext/full_type_name'
+
 module GirFFI
   # Represents a type not found in the GIR, conforming, as needed, to the
   # interface of GObjectIntrospection::IObjectInfo.
diff --git a/lib/gir_ffi/version.rb b/lib/gir_ffi/version.rb
index ceb9c0a..52cca4e 100644
--- a/lib/gir_ffi/version.rb
+++ b/lib/gir_ffi/version.rb
@@ -1,4 +1,4 @@
 # Current GirFFI version
 module GirFFI
-  VERSION = "0.7.5"
+  VERSION = "0.7.7"
 end
diff --git a/lib/gir_ffi/zero_terminated.rb b/lib/gir_ffi/zero_terminated.rb
index 4f3a77f..6d3d834 100644
--- a/lib/gir_ffi/zero_terminated.rb
+++ b/lib/gir_ffi/zero_terminated.rb
@@ -25,7 +25,7 @@ module GirFFI
     def each
       return if @ptr.null?
       offset = 0
-      while val = read_value(offset)
+      while (val = read_value(offset))
         offset += ffi_type_size
         yield wrap_value(val)
       end
diff --git a/metadata.yml b/metadata.yml
index 7faae47..7381328 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: gir_ffi
 version: !ruby/object:Gem::Version
-  version: 0.7.5
+  version: 0.7.7
 platform: ruby
 authors:
 - Matijs van Zuijlen
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2014-06-22 00:00:00.000000000 Z
+date: 2014-10-21 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: ffi
@@ -80,62 +80,6 @@ dependencies:
     - - "~>"
       - !ruby/object:Gem::Version
         version: '10.1'
-- !ruby/object:Gem::Dependency
-  name: simplecov
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: pry
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: repl_rake
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: yard
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
 description: |2
       GirFFI creates bindings for GObject-based libraries at runtime based on introspection
       data provided by the GObject Introspection Repository (GIR) system. Bindings are created
@@ -157,12 +101,8 @@ files:
 - README.md
 - Rakefile
 - TODO.md
-- examples/demo_ffi_inherited_layout.rb
-- examples/demo_ffi_nested_struct.rb
-- examples/demo_ffi_safe_inherited_layout.rb
-- examples/hard_coded.rb
-- examples/leak_test.rb
-- examples/print_class.rb
+- examples/main_loop.rb
+- gir_ffi.gemspec
 - lib/ffi-glib.rb
 - lib/ffi-glib/array.rb
 - lib/ffi-glib/array_methods.rb
@@ -174,6 +114,7 @@ files:
 - lib/ffi-glib/iconv.rb
 - lib/ffi-glib/list.rb
 - lib/ffi-glib/list_methods.rb
+- lib/ffi-glib/main_loop.rb
 - lib/ffi-glib/ptr_array.rb
 - lib/ffi-glib/s_list.rb
 - lib/ffi-glib/strv.rb
@@ -239,9 +180,8 @@ files:
 - lib/gir_ffi/builders/interface_builder.rb
 - lib/gir_ffi/builders/mapping_method_builder.rb
 - lib/gir_ffi/builders/marshalling_method_builder.rb
+- lib/gir_ffi/builders/method_template.rb
 - lib/gir_ffi/builders/module_builder.rb
-- lib/gir_ffi/builders/null_argument_builder.rb
-- lib/gir_ffi/builders/null_builder.rb
 - lib/gir_ffi/builders/null_convertor.rb
 - lib/gir_ffi/builders/object_builder.rb
 - lib/gir_ffi/builders/property_builder.rb
@@ -306,8 +246,6 @@ files:
 - lib/gir_ffi/vfunc_implementation.rb
 - lib/gir_ffi/zero_terminated.rb
 - tasks/test.rake
-- tasks/valgrind.rake
-- tasks/yard.rake
 - test/base_test_helper.rb
 - test/ffi-glib/array_test.rb
 - test/ffi-glib/byte_array_test.rb
@@ -315,6 +253,7 @@ files:
 - test/ffi-glib/hash_table_test.rb
 - test/ffi-glib/iconv_test.rb
 - test/ffi-glib/list_test.rb
+- test/ffi-glib/main_loop_test.rb
 - test/ffi-glib/ptr_array_test.rb
 - test/ffi-glib/ruby_closure_test.rb
 - test/ffi-glib/s_list_test.rb
@@ -329,7 +268,9 @@ files:
 - test/ffi-gobject_introspection/i_enum_info_test.rb
 - test/ffi-gobject_introspection/i_function_info_test.rb
 - test/ffi-gobject_introspection/i_object_info_test.rb
+- test/ffi-gobject_introspection/i_registered_type_info_test.rb
 - test/ffi-gobject_introspection/i_repository_test.rb
+- test/ffi-gobject_introspection/i_type_info_test.rb
 - test/ffi-gobject_introspection/lib_test.rb
 - test/ffi-gobject_test.rb
 - test/gir_ffi-base/glib/boolean_test.rb
@@ -400,6 +341,7 @@ files:
 - test/lib/autogen.sh
 - test/lib/configure.ac
 - test/lib/m4/jhflags.m4
+- test/minitest/stats_plugin.rb
 homepage: http://www.github.com/mvz/ruby-gir-ffi
 licenses:
 - LGPL-2.1
@@ -414,7 +356,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
   requirements:
   - - ">="
     - !ruby/object:Gem::Version
-      version: '0'
+      version: 1.9.3
 required_rubygems_version: !ruby/object:Gem::Requirement
   requirements:
   - - ">="
@@ -422,101 +364,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
       version: '0'
 requirements: []
 rubyforge_project: 
-rubygems_version: 2.2.2
+rubygems_version: 2.4.1
 signing_key: 
 specification_version: 4
 summary: FFI-based GObject binding using the GObject Introspection Repository
-test_files:
-- test/base_test_helper.rb
-- test/ffi-glib/array_test.rb
-- test/ffi-glib/byte_array_test.rb
-- test/ffi-glib/bytes_test.rb
-- test/ffi-glib/hash_table_test.rb
-- test/ffi-glib/iconv_test.rb
-- test/ffi-glib/list_test.rb
-- test/ffi-glib/ptr_array_test.rb
-- test/ffi-glib/ruby_closure_test.rb
-- test/ffi-glib/s_list_test.rb
-- test/ffi-glib/strv_test.rb
-- test/ffi-glib/variant_test.rb
-- test/ffi-gobject/gobject_test.rb
-- test/ffi-gobject/object_class_test.rb
-- test/ffi-gobject/object_test.rb
-- test/ffi-gobject/value_test.rb
-- test/ffi-gobject_introspection/i_base_info_test.rb
-- test/ffi-gobject_introspection/i_constant_info_test.rb
-- test/ffi-gobject_introspection/i_enum_info_test.rb
-- test/ffi-gobject_introspection/i_function_info_test.rb
-- test/ffi-gobject_introspection/i_object_info_test.rb
-- test/ffi-gobject_introspection/i_repository_test.rb
-- test/ffi-gobject_introspection/lib_test.rb
-- test/ffi-gobject_test.rb
-- test/gir_ffi-base/glib/boolean_test.rb
-- test/gir_ffi-base/glib/strv_test.rb
-- test/gir_ffi/arg_helper_test.rb
-- test/gir_ffi/builder_test.rb
-- test/gir_ffi/builders/argument_builder_test.rb
-- test/gir_ffi/builders/base_argument_builder_test.rb
-- test/gir_ffi/builders/callback_argument_builder_test.rb
-- test/gir_ffi/builders/callback_builder_test.rb
-- test/gir_ffi/builders/callback_return_value_builder_test.rb
-- test/gir_ffi/builders/constant_builder_test.rb
-- test/gir_ffi/builders/enum_builder_test.rb
-- test/gir_ffi/builders/field_builder_test.rb
-- test/gir_ffi/builders/function_builder_test.rb
-- test/gir_ffi/builders/interface_builder_test.rb
-- test/gir_ffi/builders/module_builder_test.rb
-- test/gir_ffi/builders/object_builder_test.rb
-- test/gir_ffi/builders/property_builder_test.rb
-- test/gir_ffi/builders/registered_type_builder_test.rb
-- test/gir_ffi/builders/return_value_builder_test.rb
-- test/gir_ffi/builders/signal_closure_builder_test.rb
-- test/gir_ffi/builders/struct_builder_test.rb
-- test/gir_ffi/builders/unintrospectable_builder_test.rb
-- test/gir_ffi/builders/union_builder_test.rb
-- test/gir_ffi/builders/user_defined_builder_test.rb
-- test/gir_ffi/builders/vfunc_builder_test.rb
-- test/gir_ffi/callback_base_test.rb
-- test/gir_ffi/class_base_test.rb
-- test/gir_ffi/error_type_info_test.rb
-- test/gir_ffi/ffi_ext/pointer_test.rb
-- test/gir_ffi/g_type_test.rb
-- test/gir_ffi/in_out_pointer_test.rb
-- test/gir_ffi/in_pointer_test.rb
-- test/gir_ffi/info_ext/i_callable_info_test.rb
-- test/gir_ffi/info_ext/i_callback_info_test.rb
-- test/gir_ffi/info_ext/i_field_info_test.rb
-- test/gir_ffi/info_ext/i_function_info_test.rb
-- test/gir_ffi/info_ext/i_signal_info_test.rb
-- test/gir_ffi/info_ext/i_type_info_test.rb
-- test/gir_ffi/info_ext/safe_constant_name_test.rb
-- test/gir_ffi/info_ext/safe_function_name_test.rb
-- test/gir_ffi/interface_base_test.rb
-- test/gir_ffi/method_stubber_test.rb
-- test/gir_ffi/object_base_test.rb
-- test/gir_ffi/sized_array_test.rb
-- test/gir_ffi/type_map_test.rb
-- test/gir_ffi/unintrospectable_type_info_test.rb
-- test/gir_ffi/user_defined_property_info_test.rb
-- test/gir_ffi/user_defined_type_info_test.rb
-- test/gir_ffi/variable_name_generator_test.rb
-- test/gir_ffi/version_test.rb
-- test/gir_ffi/zero_terminated_test.rb
-- test/gir_ffi_test.rb
-- test/gir_ffi_test_helper.rb
-- test/integration/derived_classes_test.rb
-- test/integration/generated_gimarshallingtests_test.rb
-- test/integration/generated_gio_test.rb
-- test/integration/generated_glib_test.rb
-- test/integration/generated_gobject_test.rb
-- test/integration/generated_pango_ft2_test.rb
-- test/integration/generated_pango_test.rb
-- test/integration/generated_regress_test.rb
-- test/integration/generated_secret_test.rb
-- test/integration/method_lookup_test.rb
-- test/introspection_test_helper.rb
-- test/lib/Makefile.am
-- test/lib/autogen.sh
-- test/lib/configure.ac
-- test/lib/m4/jhflags.m4
-has_rdoc: 
+test_files: []
diff --git a/tasks/test.rake b/tasks/test.rake
index fc5c21c..6bfc551 100644
--- a/tasks/test.rake
+++ b/tasks/test.rake
@@ -189,6 +189,6 @@ file "test/lib/Makefile" => "test/lib/configure" do
   sh %{cd test/lib && ./configure --enable-maintainer-mode}
 end
 
-file "test/lib/configure" do
+file "test/lib/configure" => ["test/lib/autogen.sh", "test/lib/configure.ac"] do
   sh %{cd test/lib && NOCONFIGURE=1 ./autogen.sh}
 end
diff --git a/tasks/valgrind.rake b/tasks/valgrind.rake
deleted file mode 100644
index d287936..0000000
--- a/tasks/valgrind.rake
+++ /dev/null
@@ -1,3 +0,0 @@
-task :valgrind do
-  `valgrind --suppressions=gir_ffi-ruby1.9.1.supp ruby1.9.1 -Ilib -e "require 'gir_ffi'"`
-end
diff --git a/tasks/yard.rake b/tasks/yard.rake
deleted file mode 100644
index f1a5021..0000000
--- a/tasks/yard.rake
+++ /dev/null
@@ -1,6 +0,0 @@
-begin
-  require 'yard'
-
-  YARD::Rake::YardocTask.new
-rescue LoadError
-end
diff --git a/test/ffi-glib/array_test.rb b/test/ffi-glib/array_test.rb
index 28e362e..accb9b3 100644
--- a/test/ffi-glib/array_test.rb
+++ b/test/ffi-glib/array_test.rb
@@ -153,4 +153,32 @@ describe GLib::Array do
       proc { arr.index(-1) }.must_raise IndexError
     end
   end
+
+  describe "#reset_typespec" do
+    describe "when it needs to guess the type" do
+      it "guesses :uint8 for size 1" do
+        arr = GLib::Array.from :int8, [1, 2, 3]
+        arr.reset_typespec
+        arr.element_type.must_equal :uint8
+      end
+
+      it "guesses :uint16 for size 2" do
+        arr = GLib::Array.from :int16, [1, 2, 3]
+        arr.reset_typespec
+        arr.element_type.must_equal :uint16
+      end
+
+      it "guesses :uint32 for size 4" do
+        arr = GLib::Array.from :int32, [1, 2, 3]
+        arr.reset_typespec
+        arr.element_type.must_equal :uint32
+      end
+
+      it "guesses :uint64 for size 8" do
+        arr = GLib::Array.from :int64, [1, 2, 3]
+        arr.reset_typespec
+        arr.element_type.must_equal :uint64
+      end
+    end
+  end
 end
diff --git a/test/ffi-glib/byte_array_test.rb b/test/ffi-glib/byte_array_test.rb
index d8d5921..cdd5f50 100644
--- a/test/ffi-glib/byte_array_test.rb
+++ b/test/ffi-glib/byte_array_test.rb
@@ -1,7 +1,7 @@
 require 'gir_ffi_test_helper'
 
 describe GLib::ByteArray do
-  it "can succesfully be created with Glib::ByteArray.new" do
+  it "can succesfully be created with GLib::ByteArray.new" do
     ba = GLib::ByteArray.new
     assert_instance_of GLib::ByteArray, ba
   end
diff --git a/test/ffi-glib/bytes_test.rb b/test/ffi-glib/bytes_test.rb
index e5c2a97..6906ef9 100644
--- a/test/ffi-glib/bytes_test.rb
+++ b/test/ffi-glib/bytes_test.rb
@@ -1,7 +1,7 @@
 require 'gir_ffi_test_helper'
 
 describe GLib::Bytes do
-  it "can succesfully be created with Glib::Bytes.new" do
+  it "can succesfully be created with GLib::Bytes.new" do
     bytes = GLib::Bytes.new [1, 2, 3]
     bytes.must_be_instance_of GLib::Bytes
   end
diff --git a/test/ffi-glib/iconv_test.rb b/test/ffi-glib/iconv_test.rb
index 4ff0298..9f18c7e 100644
--- a/test/ffi-glib/iconv_test.rb
+++ b/test/ffi-glib/iconv_test.rb
@@ -12,7 +12,7 @@ describe GLib::IConv do
 
   describe "#setup_and_call" do
     it "works for the method called ''" do
-      instance.setup_and_call :'', nil, nil, nil, nil
+      instance.setup_and_call :'', [nil, nil, nil, nil]
     end
   end
 end
diff --git a/test/ffi-glib/main_loop_test.rb b/test/ffi-glib/main_loop_test.rb
new file mode 100644
index 0000000..2bcb720
--- /dev/null
+++ b/test/ffi-glib/main_loop_test.rb
@@ -0,0 +1,27 @@
+require 'gir_ffi_test_helper'
+
+describe GLib::MainLoop do
+  describe "#run" do
+    it "allows other threads to run" do
+      main_loop = GLib::MainLoop.new nil, false
+
+      a = []
+      GLib.timeout_add(GLib::PRIORITY_DEFAULT, 100,
+                       proc { main_loop.quit },
+                       nil, nil)
+
+      slow_thread = Thread.new do
+        sleep 0.001
+        a << "During run"
+      end
+
+      a << "Before run"
+      main_loop.run
+      a << "After run"
+
+      slow_thread.join
+
+      a.last.must_equal "After run"
+    end
+  end
+end
diff --git a/test/ffi-gobject/object_test.rb b/test/ffi-gobject/object_test.rb
index 411136b..5405169 100644
--- a/test/ffi-gobject/object_test.rb
+++ b/test/ffi-gobject/object_test.rb
@@ -35,13 +35,23 @@ describe GObject::Object do
 
   describe "#signal_connect" do
     subject { GObject::Object.new GObject::TYPE_OBJECT, nil }
+
     it 'delegates to GObject' do
-      mock(GObject).signal_connect(subject, 'some-event')
+      mock(GObject).signal_connect(subject, 'some-event', nil)
       subject.signal_connect('some-event') do
         nothing
       end
 
       RR.verify
     end
+
+    it 'delegates to GObject if an optional data argument is passed' do
+      mock(GObject).signal_connect(subject, 'some-event', 'data')
+      subject.signal_connect('some-event', 'data') do
+        nothing
+      end
+
+      RR.verify
+    end
   end
 end
diff --git a/test/ffi-gobject/value_test.rb b/test/ffi-gobject/value_test.rb
index 179c353..de1c2d6 100644
--- a/test/ffi-gobject/value_test.rb
+++ b/test/ffi-gobject/value_test.rb
@@ -200,7 +200,7 @@ describe GObject::Value do
 
     it "works with a ByteArray" do
       ba = GLib::ByteArray.new.append("some bytes")
-      v = GObject::Value.for_g_type GObject.type_from_name("GByteArray")
+      v = GObject::Value.for_g_type GObject::TYPE_BYTE_ARRAY
       v.set_boxed ba
 
       result = v.get_value
@@ -208,6 +208,17 @@ describe GObject::Value do
       result.to_string.must_equal "some bytes"
       result.must_be_kind_of GLib::ByteArray
     end
+
+    it "works with an Array" do
+      arr = GLib::Array.from(:uint, [1, 2, 3])
+      v = GObject::Value.for_g_type GObject::TYPE_ARRAY
+      v.set_boxed arr
+
+      result = v.get_value
+
+      result.must_be_kind_of GLib::Array
+      result.reset_typespec(:uint).to_a.must_equal [1, 2, 3]
+    end
   end
 
   describe "::from" do
diff --git a/test/ffi-gobject_introspection/i_base_info_test.rb b/test/ffi-gobject_introspection/i_base_info_test.rb
index f997c8f..0b721ce 100644
--- a/test/ffi-gobject_introspection/i_base_info_test.rb
+++ b/test/ffi-gobject_introspection/i_base_info_test.rb
@@ -15,6 +15,20 @@ describe GObjectIntrospection::IBaseInfo do
     end
   end
 
+  describe "#deprecated?" do
+    let(:deprecated_info) { get_introspection_data 'Regress', 'test_versioning' }
+    let(:other_info) { get_introspection_data 'Regress', 'test_value_return' }
+
+    it "returns true for a deprecated item" do
+      skip unless deprecated_info
+      deprecated_info.must_be :deprecated?
+    end
+
+    it "returns false for a non-deprecated item" do
+      other_info.wont_be :deprecated?
+    end
+  end
+
   describe "upon garbage collection" do
     it "calls g_base_info_unref" do
       if defined?(RUBY_ENGINE) && ['jruby', 'rbx'].include?(RUBY_ENGINE)
diff --git a/test/ffi-gobject_introspection/i_constant_info_test.rb b/test/ffi-gobject_introspection/i_constant_info_test.rb
index 5eeb7a0..5dcaae2 100644
--- a/test/ffi-gobject_introspection/i_constant_info_test.rb
+++ b/test/ffi-gobject_introspection/i_constant_info_test.rb
@@ -2,16 +2,30 @@ require 'introspection_test_helper'
 
 describe GObjectIntrospection::IConstantInfo do
   describe "for GLib::USEC_PER_SEC, a constant of type :gint32" do
-    before do
-      @info = get_introspection_data 'GLib', 'USEC_PER_SEC'
-    end
+    let(:constant_info) { get_introspection_data 'GLib', 'USEC_PER_SEC' }
 
     it "returns :gint32 as its type" do
-      assert_equal :gint32, @info.constant_type.tag
+      assert_equal :gint32, constant_info.constant_type.tag
     end
 
     it "returns 1_000_000 as its value" do
-      assert_equal 1_000_000, @info.value
+      assert_equal 1_000_000, constant_info.value
+    end
+  end
+
+  describe "for GLib::SOURCE_CONTINUE, a constant of type :gboolean" do
+    let(:constant_info) { get_introspection_data 'GLib', 'SOURCE_CONTINUE' }
+
+    before do
+      skip unless constant_info
+    end
+
+    it "returns :gboolean as its type" do
+      assert_equal :gboolean, constant_info.constant_type.tag
+    end
+
+    it "returns true as its value" do
+      assert_equal true, constant_info.value
     end
   end
 end
diff --git a/test/ffi-gobject_introspection/i_object_info_test.rb b/test/ffi-gobject_introspection/i_object_info_test.rb
index 8bc110c..f027ebf 100644
--- a/test/ffi-gobject_introspection/i_object_info_test.rb
+++ b/test/ffi-gobject_introspection/i_object_info_test.rb
@@ -1,15 +1,17 @@
 require 'introspection_test_helper'
 
 describe GObjectIntrospection::IObjectInfo do
+  let(:object_info) { get_introspection_data('GObject', 'Object') }
+
   describe "#find_vfunc" do
-    before do
-      gir = GObjectIntrospection::IRepository.default
-      gir.require 'GObject', nil
-      @info = gir.find_by_name 'GObject', 'Object'
+    it "finds a vfunc by name" do
+      object_info.find_vfunc("finalize").wont_be_nil
     end
+  end
 
-    it "finds a vfunc by name" do
-      @info.find_vfunc("finalize").wont_be_nil
+  describe "#type_name" do
+    it "returns the correct name" do
+      object_info.type_name.must_equal 'GObject'
     end
   end
 end
diff --git a/test/ffi-gobject_introspection/i_registered_type_info_test.rb b/test/ffi-gobject_introspection/i_registered_type_info_test.rb
new file mode 100644
index 0000000..8f5b289
--- /dev/null
+++ b/test/ffi-gobject_introspection/i_registered_type_info_test.rb
@@ -0,0 +1,24 @@
+require 'introspection_test_helper'
+
+describe GObjectIntrospection::IRegisteredTypeInfo do
+  describe "#get_type_name" do
+    describe "for an interface" do
+      let(:registered_type_info) {
+        get_introspection_data('GIMarshallingTests', 'Interface') }
+
+      it "returns interface name" do
+        registered_type_info.type_name.must_equal 'GIMarshallingTestsInterface'
+      end
+    end
+
+    describe "for a type that is not an interface" do
+      let(:registered_type_info) {
+        get_introspection_data('GIMarshallingTests', 'Enum') }
+
+      it "returns nil" do
+        registered_type_info.type_name.must_be_nil
+      end
+    end
+  end
+end
+
diff --git a/test/ffi-gobject_introspection/i_type_info_test.rb b/test/ffi-gobject_introspection/i_type_info_test.rb
new file mode 100644
index 0000000..2d548c9
--- /dev/null
+++ b/test/ffi-gobject_introspection/i_type_info_test.rb
@@ -0,0 +1,17 @@
+require 'introspection_test_helper'
+
+describe GObjectIntrospection::ITypeInfo do
+  describe "#name?" do
+    let(:object_info) { get_introspection_data('GIMarshallingTests', 'Object') }
+    let(:vfunc_info) { object_info.find_vfunc('vfunc_array_out_parameter') }
+    let(:arg_info) { vfunc_info.args[0] }
+    let(:type_info) { arg_info.argument_type }
+
+    it "raises an error" do
+      skip unless vfunc_info
+      proc {
+        type_info.name
+      }.must_raise RuntimeError
+    end
+  end
+end
diff --git a/test/gir_ffi/builder_test.rb b/test/gir_ffi/builder_test.rb
index 5fde044..25e61d2 100644
--- a/test/gir_ffi/builder_test.rb
+++ b/test/gir_ffi/builder_test.rb
@@ -161,9 +161,10 @@ describe GirFFI::Builder do
       GirFFI::Builder.build_class get_introspection_data('Regress', 'TestSubObj')
     end
 
-    it "builds Regress namespace" do
+    it "sets up the Regress namespace" do
       assert Regress.const_defined? :Lib
-      assert Regress.respond_to? :method_missing
+      assert Regress.respond_to? :gir_ffi_builder
+      assert Regress.const_defined? :GIR_FFI_BUILDER
     end
 
     it "creates the Regress::Lib module ready to attach functions from the shared library" do
diff --git a/test/gir_ffi/builders/argument_builder_test.rb b/test/gir_ffi/builders/argument_builder_test.rb
index 8b76499..285079b 100644
--- a/test/gir_ffi/builders/argument_builder_test.rb
+++ b/test/gir_ffi/builders/argument_builder_test.rb
@@ -36,7 +36,7 @@ describe GirFFI::Builders::ArgumentBuilder do
 
       describe "when it is a regular argument" do
         before do
-          builder.is_closure = false
+          builder.closure = false
         end
 
         it "has the correct value for #pre_conversion" do
@@ -50,7 +50,7 @@ describe GirFFI::Builders::ArgumentBuilder do
 
       describe "when it is a closure" do
         before do
-          builder.is_closure = true
+          builder.closure = true
         end
 
         it "has the correct value for #pre_conversion" do
diff --git a/test/gir_ffi/builders/function_builder_test.rb b/test/gir_ffi/builders/function_builder_test.rb
index 3bd8656..8b60b9b 100644
--- a/test/gir_ffi/builders/function_builder_test.rb
+++ b/test/gir_ffi/builders/function_builder_test.rb
@@ -8,7 +8,7 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def self.test_array_fixed_out_objects 
+      def self.test_array_fixed_out_objects
         _v1 = GirFFI::InOutPointer.for [:pointer, :c]
         Regress::Lib.regress_test_array_fixed_out_objects _v1
         _v2 = GirFFI::SizedArray.wrap([:pointer, Regress::TestObj], 2, _v1.to_value)
@@ -25,7 +25,7 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def self.test_array_gint16_in ints
+      def self.test_array_gint16_in(ints)
         n_ints = ints.nil? ? 0 : ints.length
         _v1 = n_ints
         _v2 = GirFFI::SizedArray.from(:gint16, -1, ints)
@@ -43,7 +43,7 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def self.test_callback_destroy_notify callback, user_data, notify
+      def self.test_callback_destroy_notify(callback, user_data, notify)
         _v1 = Regress::TestCallbackUserData.from(callback)
         _v2 = GirFFI::InPointer.from_closure_data(user_data)
         _v3 = GLib::DestroyNotify.from(notify)
@@ -61,7 +61,7 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def self.new_from_file x
+      def self.new_from_file(x)
         _v1 = GirFFI::InPointer.from(:utf8, x)
         _v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil
         _v3 = Regress::Lib.regress_test_obj_new_from_file _v1, _v2
@@ -80,7 +80,7 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def self.gvalue_in value
+      def self.gvalue_in(value)
         _v1 = GObject::Value.from(value)
         GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_in _v1
       end
@@ -95,11 +95,11 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def self.test_array_int_null_in arr
-        _v1 = GirFFI::SizedArray.from(:gint32, -1, arr)
+      def self.test_array_int_null_in(arr)
         len = arr.nil? ? 0 : arr.length
-        _v2 = len
-        Regress::Lib.regress_test_array_int_null_in _v1, _v2
+        _v1 = len
+        _v2 = GirFFI::SizedArray.from(:gint32, -1, arr)
+        Regress::Lib.regress_test_array_int_null_in _v2, _v1
       end
     CODE
 
@@ -112,12 +112,12 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def self.test_array_int_null_out 
-        _v1 = GirFFI::InOutPointer.for [:pointer, :c]
-        _v2 = GirFFI::InOutPointer.for :gint32
-        Regress::Lib.regress_test_array_int_null_out _v1, _v2
-        _v3 = _v2.to_value
-        _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v1.to_value)
+      def self.test_array_int_null_out
+        _v1 = GirFFI::InOutPointer.for :gint32
+        _v2 = GirFFI::InOutPointer.for [:pointer, :c]
+        Regress::Lib.regress_test_array_int_null_out _v2, _v1
+        _v3 = _v1.to_value
+        _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.to_value)
         return _v4
       end
     CODE
@@ -131,15 +131,15 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def method_array_inout ints
-        _v1 = GirFFI::InOutPointer.for [:pointer, :c]
-        _v1.set_value GirFFI::SizedArray.from(:gint32, -1, ints)
+      def method_array_inout(ints)
         length = ints.nil? ? 0 : ints.length
-        _v2 = GirFFI::InOutPointer.for :gint32
-        _v2.set_value length
-        GIMarshallingTests::Lib.gi_marshalling_tests_object_method_array_inout self, _v1, _v2
-        _v3 = _v2.to_value
-        _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v1.to_value)
+        _v1 = GirFFI::InOutPointer.for :gint32
+        _v1.set_value length
+        _v2 = GirFFI::InOutPointer.for [:pointer, :c]
+        _v2.set_value GirFFI::SizedArray.from(:gint32, -1, ints)
+        GIMarshallingTests::Lib.gi_marshalling_tests_object_method_array_inout self, _v2, _v1
+        _v3 = _v1.to_value
+        _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.to_value)
         return _v4
       end
     CODE
@@ -153,7 +153,7 @@ describe GirFFI::Builders::FunctionBuilder do
     code = fbuilder.generate
 
     expected = <<-CODE
-      def instance_method 
+      def instance_method
         _v1 = Regress::Lib.regress_test_obj_instance_method self
         return _v1
       end
@@ -171,7 +171,7 @@ describe GirFFI::Builders::FunctionBuilder do
       it "builds a correct definition" do
         size_type = ":guint#{FFI.type_size(:size_t) * 8}"
         code.must_equal <<-CODE.reset_indentation
-          def get_strv 
+          def get_strv
             _v1 = GirFFI::InOutPointer.for #{size_type}
             _v2 = GLib::Lib.g_variant_get_strv self, _v1
             _v3 = GLib::Strv.wrap(_v2)
@@ -187,7 +187,7 @@ describe GirFFI::Builders::FunctionBuilder do
       it "builds a correct definition" do
         skip unless function_info
         code.must_equal <<-CODE.reset_indentation
-          def self.has_parameter_named_attrs foo, attributes
+          def self.has_parameter_named_attrs(foo, attributes)
             _v1 = foo
             GirFFI::ArgHelper.check_fixed_array_size 32, attributes, \"attributes\"
             _v2 = GirFFI::SizedArray.from([:pointer, :guint32], 32, attributes)
@@ -206,7 +206,7 @@ describe GirFFI::Builders::FunctionBuilder do
       it "builds a correct definition" do
         skip unless function_info
         code.must_equal <<-CODE.reset_indentation
-          def method_int8_arg_and_out_callee arg
+          def method_int8_arg_and_out_callee(arg)
             _v1 = arg
             _v2 = GirFFI::InOutPointer.for [:pointer, :gint8]
             GIMarshallingTests::Lib.gi_marshalling_tests_object_method_int8_arg_and_out_callee self, _v1, _v2
diff --git a/test/gir_ffi/builders/object_builder_test.rb b/test/gir_ffi/builders/object_builder_test.rb
index e714812..a7c09fd 100644
--- a/test/gir_ffi/builders/object_builder_test.rb
+++ b/test/gir_ffi/builders/object_builder_test.rb
@@ -22,6 +22,16 @@ describe GirFFI::Builders::ObjectBuilder do
       sig = builder.find_signal 'changed'
       sig.name.must_equal 'changed'
     end
+
+    it "raises an error for a signal that doesn't exist" do
+      msg = nil
+      begin
+        obj_builder.find_signal 'foo'
+      rescue RuntimeError => e
+        msg = e.message
+      end
+      assert_match(/^Signal/, msg)
+    end
   end
 
   describe "#find_property" do
diff --git a/test/gir_ffi/builders/return_value_builder_test.rb b/test/gir_ffi/builders/return_value_builder_test.rb
index 4871eb4..5db3b91 100644
--- a/test/gir_ffi/builders/return_value_builder_test.rb
+++ b/test/gir_ffi/builders/return_value_builder_test.rb
@@ -329,7 +329,7 @@ describe GirFFI::Builders::ReturnValueBuilder do
     end
 
     it "marks itself as irrelevant" do
-      builder.is_relevant?.must_equal false
+      builder.relevant?.must_equal false
     end
 
     it "returns nothing" do
@@ -342,7 +342,7 @@ describe GirFFI::Builders::ReturnValueBuilder do
       get_introspection_data("Regress", "TestCallbackUserData").args[0].argument_type }
 
     before do
-      builder.is_closure = true
+      builder.closure = true
     end
 
     it "fetches the stored object in #post_conversion" do
@@ -366,7 +366,7 @@ describe GirFFI::Builders::ReturnValueBuilder do
     end
 
     it "marks itself as irrelevant" do
-      builder.is_relevant?.must_equal false
+      builder.relevant?.must_equal false
     end
 
     it "returns nothing" do
diff --git a/test/gir_ffi/builders/signal_closure_builder_test.rb b/test/gir_ffi/builders/signal_closure_builder_test.rb
index 31cc681..f77c473 100644
--- a/test/gir_ffi/builders/signal_closure_builder_test.rb
+++ b/test/gir_ffi/builders/signal_closure_builder_test.rb
@@ -21,7 +21,7 @@ describe GirFFI::Builders::SignalClosureBuilder do
       it "returns a valid marshaller converting only the receiver" do
         expected = <<-CODE.reset_indentation
         def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data)
-          _instance, _ = param_values.map(&:get_value_plain)
+          _instance = param_values.first.get_value_plain
           _v1 = _instance
           wrap(closure.to_ptr).invoke_block(_v1)
         end
@@ -40,7 +40,7 @@ describe GirFFI::Builders::SignalClosureBuilder do
 
         expected = <<-CODE.reset_indentation
         def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data)
-          _instance, i, _ = param_values.map(&:get_value_plain)
+          _instance, i = param_values.map(&:get_value_plain)
           _v1 = _instance
           _v2 = i
           _v3 = wrap(closure.to_ptr).invoke_block(_v1, _v2)
@@ -59,7 +59,7 @@ describe GirFFI::Builders::SignalClosureBuilder do
       it "returns a valid mapping method" do
         expected = <<-CODE.reset_indentation
         def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data)
-          _instance, result, _ = param_values.map(&:get_value_plain)
+          _instance, result = param_values.map(&:get_value_plain)
           _v1 = _instance
           _v2 = result
           wrap(closure.to_ptr).invoke_block(_v1, _v2)
@@ -79,7 +79,7 @@ describe GirFFI::Builders::SignalClosureBuilder do
 
         expected = <<-CODE.reset_indentation
         def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data)
-          _instance, arr, len, _ = param_values.map(&:get_value_plain)
+          _instance, arr, len = param_values.map(&:get_value_plain)
           _v1 = _instance
           _v2 = len
           _v3 = GirFFI::SizedArray.wrap(:guint32, _v2, arr)
@@ -100,7 +100,7 @@ describe GirFFI::Builders::SignalClosureBuilder do
 
         expected = <<-CODE.reset_indentation
         def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data)
-          _instance, object, _ = param_values.map(&:get_value_plain)
+          _instance, object = param_values.map(&:get_value_plain)
           _v1 = _instance
           _v2 = Regress::TestSimpleBoxedA.wrap(object)
           wrap(closure.to_ptr).invoke_block(_v1, _v2)
@@ -120,7 +120,7 @@ describe GirFFI::Builders::SignalClosureBuilder do
 
         expected = <<-CODE.reset_indentation
         def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data)
-          _instance, i, _ = param_values.map(&:get_value_plain)
+          _instance, i = param_values.map(&:get_value_plain)
           _v1 = _instance
           _v2 = i
           _v3 = wrap(closure.to_ptr).invoke_block(_v1, _v2)
diff --git a/test/gir_ffi/class_base_test.rb b/test/gir_ffi/class_base_test.rb
index fcc6ab4..c5a442d 100644
--- a/test/gir_ffi/class_base_test.rb
+++ b/test/gir_ffi/class_base_test.rb
@@ -82,7 +82,7 @@ describe GirFFI::ClassBase do
       end
       sub_klass.const_set :GIR_FFI_BUILDER, sub_builder
 
-      sub_klass.setup_and_call :foo
+      sub_klass.setup_and_call :foo, []
     end
 
     it "calls the method given by the result of .setup_method" do
@@ -95,7 +95,7 @@ describe GirFFI::ClassBase do
       end
       klass.const_set :GIR_FFI_BUILDER, builder
 
-      result = klass.setup_and_call :foo
+      result = klass.setup_and_call :foo, []
       result.must_equal "correct-result"
     end
   end
@@ -116,7 +116,7 @@ describe GirFFI::ClassBase do
 
       obj = sub_klass.new
 
-      obj.setup_and_call :foo
+      obj.setup_and_call :foo, []
     end
 
     it "calls the method given by the result of .setup_instance_method" do
@@ -131,7 +131,7 @@ describe GirFFI::ClassBase do
 
       obj = klass.new
 
-      result = obj.setup_and_call :foo
+      result = obj.setup_and_call :foo, []
       result.must_equal "correct-result"
     end
   end
diff --git a/test/gir_ffi/in_out_pointer_test.rb b/test/gir_ffi/in_out_pointer_test.rb
index 860a13a..b9808b6 100644
--- a/test/gir_ffi/in_out_pointer_test.rb
+++ b/test/gir_ffi/in_out_pointer_test.rb
@@ -1,7 +1,5 @@
 require 'gir_ffi_test_helper'
 
-require 'gir_ffi/in_out_pointer'
-
 describe GirFFI::InOutPointer do
   describe ".new" do
     it "wraps an existing pointer and a type" do
diff --git a/test/gir_ffi/info_ext/i_type_info_test.rb b/test/gir_ffi/info_ext/i_type_info_test.rb
index b75f0af..0bfa3ce 100644
--- a/test/gir_ffi/info_ext/i_type_info_test.rb
+++ b/test/gir_ffi/info_ext/i_type_info_test.rb
@@ -408,7 +408,7 @@ describe GirFFI::InfoExt::ITypeInfo do
         stub(type_info).interface { interface_type_info }
       end
 
-      it "has the correct value for #pre" do
+      it "returns an empty array" do
         type_info.extra_conversion_arguments.must_equal []
       end
     end
diff --git a/test/gir_ffi/method_stubber_test.rb b/test/gir_ffi/method_stubber_test.rb
index 8762892..cd5ffdb 100644
--- a/test/gir_ffi/method_stubber_test.rb
+++ b/test/gir_ffi/method_stubber_test.rb
@@ -12,7 +12,7 @@ describe GirFFI::MethodStubber do
       it "creates a method stub" do
         result.must_equal <<-STUB.reset_indentation
           def instance_method *args, &block
-            setup_and_call :instance_method, *args, &block
+            setup_and_call "instance_method", args, &block
           end
         STUB
       end
@@ -25,7 +25,7 @@ describe GirFFI::MethodStubber do
       it "creates a class method stub" do
         result.must_equal <<-STUB.reset_indentation
           def self.static_method *args, &block
-            setup_and_call :static_method, *args, &block
+            setup_and_call "static_method", args, &block
           end
         STUB
       end
@@ -38,7 +38,7 @@ describe GirFFI::MethodStubber do
       it "creates a module method stub" do
         result.must_equal <<-STUB.reset_indentation
           def self.test_int *args, &block
-            setup_and_call :test_int, *args, &block
+            setup_and_call "test_int", args, &block
           end
         STUB
       end
@@ -50,7 +50,7 @@ describe GirFFI::MethodStubber do
       it "creates a method stub with a safe name that sets up the unsafe method" do
         result.must_equal <<-STUB.reset_indentation
           def _ *args, &block
-            setup_and_call :"", *args, &block
+            setup_and_call "", args, &block
           end
         STUB
       end
diff --git a/test/gir_ffi_test_helper.rb b/test/gir_ffi_test_helper.rb
index 1c9df3e..ca5cf39 100644
--- a/test/gir_ffi_test_helper.rb
+++ b/test/gir_ffi_test_helper.rb
@@ -59,10 +59,6 @@ class Minitest::Test
     GObject::Object::Struct.new(object.to_ptr)[:ref_count]
   end
 
-  def is_floating? object
-    (GObject::Object::Struct.new(object.to_ptr)[:qdata].address & 2) == 2
-  end
-
   def max_for_unsigned_type type
     ( 1 << (FFI.type_size(type) * 8) ) - 1
   end
diff --git a/test/integration/generated_gimarshallingtests_test.rb b/test/integration/generated_gimarshallingtests_test.rb
index bdecc7f..f33fd7a 100644
--- a/test/integration/generated_gimarshallingtests_test.rb
+++ b/test/integration/generated_gimarshallingtests_test.rb
@@ -242,7 +242,7 @@ describe GIMarshallingTests do
     it "has the member :value2" do
       assert_equal 2, GIMarshallingTests::NoTypeFlags[:value2]
     end
-    it "has the member :value" do
+    it "has the member :value3" do
       assert_equal 4, GIMarshallingTests::NoTypeFlags[:value3]
     end
     it "has the member :mask" do
diff --git a/test/integration/generated_regress_test.rb b/test/integration/generated_regress_test.rb
index 7a5089c..9361d8a 100644
--- a/test/integration/generated_regress_test.rb
+++ b/test/integration/generated_regress_test.rb
@@ -435,7 +435,7 @@ describe Regress do
       end
 
       it "has been sunk" do
-        assert !is_floating?(@o)
+        @o.wont_be :floating?
       end
     end
   end
@@ -564,7 +564,7 @@ describe Regress do
     end
 
     it "does not float" do
-      assert !is_floating?(instance)
+      instance.wont_be :floating?
     end
 
     it "has a working method #matrix" do
diff --git a/test/lib/autogen.sh b/test/lib/autogen.sh
index 161cb0b..4f15a04 100755
--- a/test/lib/autogen.sh
+++ b/test/lib/autogen.sh
@@ -74,6 +74,7 @@ libtoolize --force || exit $?
 $ACLOCAL -I m4 || exit $?
 
 autoconf || exit $?
+autoheader || exit $?
 
 $AUTOMAKE --add-missing || exit $?
 
diff --git a/test/lib/configure.ac b/test/lib/configure.ac
index 99c845a..c10c1ee 100644
--- a/test/lib/configure.ac
+++ b/test/lib/configure.ac
@@ -6,6 +6,7 @@ AC_INIT(dummy_test_lib, 0.0.1)
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([1.7 foreign])
 AM_MAINTAINER_MODE
+AM_CONFIG_HEADER([config.h])
 
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
 
diff --git a/test/minitest/stats_plugin.rb b/test/minitest/stats_plugin.rb
new file mode 100644
index 0000000..6dbeb93
--- /dev/null
+++ b/test/minitest/stats_plugin.rb
@@ -0,0 +1,26 @@
+module Minitest
+  class StatsReporter < AbstractReporter
+    def initialize _options
+      @results = []
+    end
+
+    def start
+      @current_time = Time.now
+    end
+
+    def record result
+      @results << result
+    end
+
+    def report
+      slowest = @results.sort_by(&:time).reverse.first(10)
+      slowest.each do |result|
+        puts "%10.4f %s" % [result.time, result.location]
+      end
+    end
+  end
+
+  def self.plugin_stats_init(options)
+    self.reporter << StatsReporter.new(options)
+  end
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-gir-ffi.git



More information about the Pkg-ruby-extras-commits mailing list