desegregate roles and classes. that was dumb
Guillermo Roditi [Sun, 24 Feb 2008 03:25:30 +0000 (03:25 +0000)]
lib/MooseX/AutoDoc.pm
t/100-class.t
t/101-class.t
t/102-class.t
t/103-class.t
t/104-class.t
t/105-class.t
t/200-role.t
t/201-role.t
t/202-role.t

index 20d1264..0526a79 100644 (file)
@@ -70,152 +70,90 @@ sub _build_license_text {
 }
 
 #make the actual POD
-sub generate_pod_for_role {
-  my ($self, $role, $view_args) = @_;
+sub generate_pod_for {
+  my ($self, $package, $view_args) = @_;
 
-  carp("${role} is already loaded. This will cause inacurate output.".
-       "if ${role} is the consumer of any roles.")
-    if Class::MOP::is_class_loaded( $role );
+  carp("${package} is already loaded. This will cause inacurate output.".
+       "if ${package} is the consumer of any roles.")
+    if Class::MOP::is_class_loaded( $package );
 
-  my $spec = $self->role_info($role);
+  my $spec = $self->package_info($package);
+  my $key = $package->meta->isa("Moose::Meta::Role") ? 'role' : 'class';
   my $vars = {
-              role    => $spec,
+              $key    => $spec,
               license => $self->license_text,
               authors => $self->has_authors ? $self->authors : [],
              };
-  return $self->view->render_role($vars, $view_args);
+  my $render = "render_${key}";
+  return $self->view->$render($vars, $view_args);
 }
 
-#make the actual POD
-sub generate_pod_for_class {
-  my ($self, $class, $view_args) = @_;
-
-  carp("${class} is already loaded. This will cause inacurate output.".
-       "if ${class} is the consumer of any roles.")
-    if Class::MOP::is_class_loaded( $class );
-
-  my $spec = $self->class_info($class);
-  my $vars = {
-              class   => $spec,
-              license => $self->license_text,
-              authors => $self->has_authors ? $self->authors : [],
-             };
-
-  return $self->view->render_class($vars, $view_args);
-}
-
-
 # *_info methods
-sub _role_info {
-  my ($self, $role) = @_;
-
-  my (@roles_to_apply, $rmeta, $original_apply);
-  {    #intercept role application so we can accurately generate
-       #method and attribute information for the parent class.
-       #this is fragile, but there is not better way that i am aware of
-
-    $rmeta = Moose::Meta::Role->meta;
-    $rmeta->make_mutable if $rmeta->is_immutable;
-    $original_apply = $rmeta->get_method("apply")->body;
-    $rmeta->remove_method("apply");
-    $rmeta->add_method("apply", sub{push(@roles_to_apply, [@_])});
-
-    eval { Class::MOP::load_class($role); };
-    confess "Failed to load class ${role} $@" if $@;
-  }
-
-  my $meta =  $role->meta;
-  my $anon = Moose::Meta::Class->create_anon_class;
-  $original_apply->($meta, $anon);
-
-  my @attributes = map{ $anon->get_attribute($_) } sort $anon->get_attribute_list;
-
-  my @methods =
-    grep{ ! exists $self->ignored_method_metaclasses->{$_->meta->name} }
-      map { $anon->get_method($_) }
-        grep { $_ ne 'meta' }    #it wasnt getting filtered on the anon class..
-          sort $anon->get_method_list;
-  my @method_specs     = map{ $self->_method_info($_)        } @methods;
-  my @attribute_specs  = map{ $self->_attribute_info($_)     } @attributes;
-
-  { #fix Moose::Meta::Role and apply the roles that were delayed
-    $rmeta->remove_method("apply");
-    $rmeta->add_method("apply", $original_apply);
-    $rmeta->make_immutable;
-    shift(@$_)->apply(@$_) for @roles_to_apply;
-  }
-
-  my @roles =
-    sort{ $a->name cmp $b->name }
-      map { $_->isa("Moose::Meta::Role::Composite") ? @{$_->get_roles} : $_ }
-        @{ $meta->get_roles };
-
-  my @role_specs = map{ $self->_consumed_role_info($_) } @roles;
-
-  my $spec = {
-              name         => $meta->name,
-              roles        => \ @role_specs,
-              methods      => \ @method_specs,
-              attributes   => \ @attribute_specs,
-             };
-
-  return $spec;
-}
-
-
-sub _class_info {
-  my ($self, $class) = @_;
-
-  my (@roles_to_apply, $rmeta, $original_apply);
-  {    #intercept role application so we can accurately generate
-       #method and attribute information for the parent class.
-       #this is fragile, but there is not better way that i am aware of
-
-    $rmeta = Moose::Meta::Role->meta;
-    $rmeta->make_mutable if $rmeta->is_immutable;
-    $original_apply = $rmeta->get_method("apply")->body;
-    $rmeta->remove_method("apply");
-    $rmeta->add_method("apply", sub{push(@roles_to_apply, [@_])});
-
-    eval { Class::MOP::load_class($class); };
-    confess "Failed to load class ${class} $@" if $@;
+sub _package_info {
+  my($self, $package) = @_;
+
+  #intercept role application so we can accurately generate
+  #method and attribute information for the parent class.
+  #this is fragile, but there is not better way that i am aware of
+  my $rmeta = Moose::Meta::Role->meta;
+  $rmeta->make_mutable if $rmeta->is_immutable;
+  my $original_apply = $rmeta->get_method("apply")->body;
+  $rmeta->remove_method("apply");
+  my @roles_to_apply;
+  $rmeta->add_method("apply", sub{push(@roles_to_apply, [@_])});
+  #load the package with the hacked Moose::Meta::Role
+  eval { Class::MOP::load_class($package); };
+  confess "Failed to load package ${package} $@" if $@;
+
+  #get on with analyzing the  package
+  my $meta = $package->meta;
+  my $spec = {};
+  my ($class, $is_role);
+  if($package->meta->isa('Moose::Meta::Role')){
+    $is_role = 1;
+    # we need to apply the role to a class to be able to properly introspect it
+    $class = Moose::Meta::Class->create_anon_class;
+    $original_apply->($meta, $class);
+  } else {
+    #roles don't have superclasses ...
+    $class = $meta;
+    my @superclasses = map{ $_->meta }
+      grep { $_ ne 'Moose::Object' } $meta->superclasses;
+    my @superclass_specs = map{ $self->_superclass_info($_) } @superclasses;
+    $spec->{superclasses} = \@superclass_specs;
   }
 
-  my $meta = $class->meta;
-
-  my @attributes   = map{ $meta->get_attribute($_) } sort $meta->get_attribute_list;
-  my @superclasses = map{ $_->meta }
-    grep { $_ ne 'Moose::Object' } $meta->superclasses;
-
-  my @methods =
+  #these two are common to both roles and classes
+  my @attributes = map{ $class->get_attribute($_) } sort $class->get_attribute_list;
+  my @methods    =
     grep{ ! exists $self->ignored_method_metaclasses->{$_->meta->name} }
-      map { $meta->get_method($_) }
-        grep { $_ ne 'meta' }    #it wasnt getting filtered on the anon class..
-          sort $meta->get_method_list;
-
-  my @method_specs     = map{ $self->_method_info($_)        } @methods;
-  my @attribute_specs  = map{ $self->_attribute_info($_)     } @attributes;
-  my @superclass_specs = map{ $self->_superclass_info($_)    } @superclasses;
-
-  { #fix Moose::Meta::Role and apply the roles that were delayed
-    $rmeta->remove_method("apply");
-    $rmeta->add_method("apply", $original_apply);
-    $rmeta->make_immutable;
-    shift(@$_)->apply(@$_) for @roles_to_apply;
-  }
-
+      map { $class->get_method($_) }
+        grep { $_ ne 'meta' } sort $class->get_method_list;
+
+  my @method_specs     = map{ $self->_method_info($_)    } @methods;
+  my @attribute_specs  = map{ $self->_attribute_info($_) } @attributes;
+
+  #fix Moose::Meta::Role and apply the roles that were delayed
+  $rmeta->remove_method("apply");
+  $rmeta->add_method("apply", $original_apply);
+  $rmeta->make_immutable;
+  #we apply roles to be able to figure out which ones we are using although I
+  #could just cycle through $_->[0] for @roles_to_apply;
+  shift(@$_)->apply(@$_) for @roles_to_apply;
+
+  #Moose::Meta::Role and Class have different methods to get consumed roles..
+  #make sure we break up composite roles as well to get better names and nicer
+  #linking to packages.
   my @roles = sort{ $a->name cmp $b->name }
-    map { $_->isa("Moose::Meta::Role::Composite") ? @{$_->get_roles} : $_ }
-      @{ $meta->roles };
+    map { $_->isa("Moose::Meta::Role::Composite") ? @{ $_->get_roles } : $_ }
+      @{ $is_role ? $meta->get_roles : $meta->roles };
   my @role_specs = map{ $self->_consumed_role_info($_) } @roles;
 
-  my $spec = {
-              name         => $meta->name,
-              roles        => \ @role_specs,
-              methods      => \ @method_specs,
-              attributes   => \ @attribute_specs,
-              superclasses => \ @superclass_specs,
-             };
+  #fill up the spec
+  $spec->{name}       = $meta->name;
+  $spec->{roles}      = \ @role_specs;
+  $spec->{methods}    = \ @method_specs;
+  $spec->{attributes} = \ @attribute_specs;
 
   return $spec;
 }
@@ -317,7 +255,7 @@ __END__;
 
 =head1 NAME
 
-MooseX::AutoDoc - Automatically generate documentation for Moose-based classes
+MooseX::AutoDoc - Automatically generate documentation for Moose-based packages
 
 =head1 SYNOPSYS
 
@@ -334,22 +272,24 @@ MooseX::AutoDoc - Automatically generate documentation for Moose-based classes
         ],
       );
 
-    my $class_pod = $autodoc->generate_pod_for_class("MyClass");
-    my $role_pod  = $autodoc->generate_pod_for_role("MyRole");
+    my $class_pod = $autodoc->generate_pod_for("MyClass");
+    my $role_pod  = $autodoc->generate_pod_for("MyRole");
 
 =head1 DESCRIPTION
 
 MooseX::AutoDoc allows you to automatically generate POD documentation from
-your Moose based objects by introspecting them and creating a
+your Moose based objects by introspecting them and creating a POD skeleton
+with extra information where it can be infered through the MOP.
 
 =head1 NOTICE REGARDING ROLE CONSUMPTION
 
 To accurantely detect which methods and attributes are part of the class / role
-being examined and which are part of a consumed role the
-L</"generate_pod_for_role"> and  L</"generate_pod_for_class"> methods need to
-delay role consumption. If your role or class has been loaded prior to calling
-these methods you run a risk of recieving inacurate data and a warning will be
-emitted.
+being examined and which are part of a consumed role the L</"generate_pod_for">
+method need to delay role consumption. If your role or class has been loaded
+prior to calling these methods you run a risk of recieving inacurate data and
+a warning will be emitted. This is due to the fact that once a role is applied
+there is no way to tell which attributes and methods came from the class and
+which came from the role.
 
 =head1 ATTRIBUTES
 
@@ -459,39 +399,28 @@ names and attempting to load and instantiate a class of the same name.
 Instantiate a new object. Please refer to L</"ATTRIBUTES"> for a list of valid
 key options.
 
-=head2 generate_pod_for_class $class_name, $view_args
+=head2 generate_pod_for $package_name, $view_args
 
-Returns a string containing the Pod for the class. To make sure the data is
-accurate please make sure the class has not been loaded prior to this step.
+Returns a string containing the Pod for the package. To make sure the data is
+accurate please make sure the package has not been loaded prior to this step.
 for more info see L</"NOTICE REGARDING ROLE CONSUMPTION">
 
-=head2 generate_pod_for_role $role_name, $view_args
-
-Returns a string containing the Pod for the role.To make sure the data is
-accurate please make sure the role has not been loaded prior to this step.
-for more info see L</"NOTICE REGARDING ROLE CONSUMPTION">
-
-=head2 _class_info $class_name
-
-Will return a hashref representing the documentation components of the class
-with the keys C<name>, C<superclasses>, C<attributes>, C<methods> and,
-C<attributes>; the latter four representing array refs of the hashrefs returned
-by L</"_superclass_info">, L</"_attribute_info">, L</"_method_info">, and
-L</"_consumed_role_info">
-
-=head2 _role_info $role_name
+=head2 _package_info $package_name
 
-Will return a hashref representing the documentation components of the role
-with the keys C<name>, C<attributes>, C<methods> and, C<attributes>; the
-latter three representing array refs of the hashrefs returned by
-L</"_attribute_info">, L</"_method_info">, and L</"_consumed_role_info">
+Will return a hashref representing the documentation components of the package
+with the keys C<name>,  C<attributes>, C<methods>, C<attributes> and--if the
+case the package is a class--C<superclasses>; the latter four are array refs
+of the hashrefs returned by L</"_superclass_info">, L</"_attribute_info">,
+L</"_method_info">, and L</"_consumed_role_info"> respectively.
 
 =head2 _attribute_info $attr
 
 Accepts one argument, an attribute metaclass instance.
 Returns a hashref representing the documentation components of the
 attribute with the keys C<name>, C<description>, and C<info>, a hashref
-of additional information.
+of additional information. If you have set the documentation attribute of
+your attributes the documentation text will be appended to the auto-generated
+description.
 
 =head2 _consumed_role_info $role
 
index a92b3e1..7c130c5 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_class_info("AutoDocTest1");
+my $spec = $autodoc->_package_info("AutoDocTest1");
 
 #we already tested this..
 delete $spec->{attributes};
index 80aa998..55c3a4e 100644 (file)
@@ -9,7 +9,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_class_info("AutoDocTest2");
+my $spec = $autodoc->_package_info("AutoDocTest2");
 
 my $target = {
                name => 'AutoDocTest2',
index 62b753f..0b07240 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_class_info("AutoDocTest3");
+my $spec = $autodoc->_package_info("AutoDocTest3");
 
 my $target = {
                name => 'AutoDocTest3',
index 77c65ec..080c5bf 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_class_info("AutoDocTest4");
+my $spec = $autodoc->_package_info("AutoDocTest4");
 
 my $target = {
               name => 'AutoDocTest4',
index 2fb4347..bb5a89e 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_class_info("AutoDocTest5");
+my $spec = $autodoc->_package_info("AutoDocTest5");
 
 my $target = {
               name => 'AutoDocTest5',
index d46da94..ee21f29 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_class_info("AutoDocTest6");
+my $spec = $autodoc->_package_info("AutoDocTest6");
 
 my $target = {
               name => 'AutoDocTest6',
index 98701a0..cc0ca46 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_role_info("AutoDocTest::Role::Role1");
+my $spec = $autodoc->_package_info("AutoDocTest::Role::Role1");
 
 my $target = {
               name => 'AutoDocTest::Role::Role1',
index 4667b9a..50a7bb7 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_role_info("AutoDocTest::Role::Role2");
+my $spec = $autodoc->_package_info("AutoDocTest::Role::Role2");
 
 my $target = {
               name => 'AutoDocTest::Role::Role2',
index e4ab9dc..c921d82 100644 (file)
@@ -8,7 +8,7 @@ use lib "$Bin/lib";
 use Test::More tests => 1;
 
 my $autodoc = MooseX::AutoDoc->new;
-my $spec = $autodoc->_role_info("AutoDocTest::Role::Role3");
+my $spec = $autodoc->_package_info("AutoDocTest::Role::Role3");
 
 my $target = {
               name => 'AutoDocTest::Role::Role3',