[perl-Glib/gio-support: 6/12] [gio] Adjust the dynamic method resolution for multiple inheritance



commit f43bb77ac7e941e7bf79145b8b03f7ea74512b7a
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date:   Wed Mar 3 00:04:17 2010 +0100

    [gio] Adjust the dynamic method resolution for multiple inheritance

 lib/Glib.pm |   69 ++++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 54 insertions(+), 15 deletions(-)
---
diff --git a/lib/Glib.pm b/lib/Glib.pm
index c27e8ac..047d57f 100644
--- a/lib/Glib.pm
+++ b/lib/Glib.pm
@@ -219,17 +219,22 @@ package Glib::Object::_Introspection;
 
 use strict;
 
-sub find_registered_namespace {
+sub find_registered_ancestors {
   my ($class, $namespace) = @_;
 
-  # replace the prefix for unregistered types
-  while ($namespace =~ m/^Glib::Object::_Unregistered::\w+/) {
+  my @ancestors = ($namespace);
+  {
     no strict 'refs';
     my @parents = @{$namespace . '::ISA'};
-    $namespace = $parents[-1];
+    foreach my $parent (@parents) {
+      push @ancestors, __PACKAGE__->find_registered_ancestors($parent);
+    }
   }
 
-  return $namespace;
+  my @registered_ancestors =
+    grep { !m/^Glib::Object::_Unregistered::/ } @ancestors;
+
+  return @registered_ancestors;
 }
 
 package Glib::IO;
@@ -249,20 +254,54 @@ sub AUTOLOAD {
 
   # 'namespace::method' or just 'method'
   if ($symbol =~ m/(?:(.+)::)?(.+)/) {
-    my $namespace = $1;
-    my $method = $2;
-
-    if (defined $namespace) {
-      $namespace = Glib::Object::_Introspection->find_registered_namespace (
-        $namespace);
+    my $symbol_namespace = $1;
+    my $symbol_method = $2;
+
+    # FIXME: we are effectively reimplementing method resolution here.
+    # consider ditching the AUTOLOAD clutch in favor of just installing sub
+    # stubs in the correct places for all methods and functions.
+    my @namespace_candidates = ();
+    if (defined $symbol_namespace) {
+      @namespace_candidates =
+        Glib::Object::_Introspection->find_registered_ancestors (
+          $symbol_namespace);
 
       # strip off the normal prefix
-      $namespace =~ s/^${PACKAGE}(?:::)?//;
-      $namespace = undef if $namespace eq '';
+      foreach my $namespace (@namespace_candidates) {
+        # alter the array in-place
+        $namespace =~ s/^${PACKAGE}(?:::)?//;
+        $namespace = undef if $namespace eq '';
+      }
+    }
+
+    if (! namespace_candidates) {
+      @namespace_candidates = (undef);
+    }
+
+    # warn "namespace candidates for $symbol: (@namespace_candidates)\n";
+
+    my @errors;
+    my @results;
+    foreach my $namespace (@namespace_candidates) {
+      @results = eval {
+        Glib::Object::_Introspection->invoke(
+          $BASENAME, $namespace, $symbol_method, @args); };
+      if ($@) {
+        if ($ ->isa ('Glib::Error')) {
+          croak $@;
+        }
+        push @errors, $@;
+      } else {
+        @errors = ();
+        last;
+      }
+    }
+
+    if (! results && @errors) {
+      croak "Invalid invocation of $symbol:\n  ", join "\n  ", @errors;
     }
 
-    return Glib::Object::_Introspection->invoke(
-      $BASENAME, $namespace, $method, @args);
+    return wantarray ? @results : $results[0];
   }
 
   croak "Invalid invocation: Cannot handle $symbol";



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]