File Coverage

blib/lib/Devel/MAT/Tool/Object/Pad/_Commands.pm
Criterion Covered Total %
statement 69 70 98.5
branch 12 16 75.0
condition 7 8 87.5
subroutine 15 15 100.0
pod n/a
total 103 109 94.5


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2022 -- leonerd@leonerd.org.uk
5              
6 2     2   1657 use v5.14;
  2         7  
7 2     2   11 use warnings;
  2         4  
  2         135  
8              
9             package # hide
10             Devel::MAT::Tool::Object::Pad::classes;
11 2     2   10 use base qw( Devel::MAT::Tool );
  2         7  
  2         238  
12              
13 2     2   11 use constant CMD => "classes";
  2         4  
  2         142  
14 2     2   9 use constant CMD_DESC => "Display a list of the Object::Pad classes";
  2         4  
  2         118  
15              
16 2     2   10 use List::UtilsBy qw( sort_by );
  2         4  
  2         707  
17              
18             sub run
19             {
20 1     1   18934 my $self = shift;
21              
22 1         8 my $df = $self->df;
23              
24 1         16 my $OPtool = $self->pmat->load_tool( "Object::Pad" );
25              
26 1     5   28 my @classes = sort_by { $_->objectpad_name } values %{ $OPtool->classes_by_name };
  5         104  
  1         7  
27              
28             Devel::MAT::Tool::more->paginate( sub {
29 1     1   37 my ( $count ) = @_;
30 1   66     13 while( $count and @classes ) {
31 5         773 my $class = shift @classes;
32              
33 5 100       42 Devel::MAT::Cmd->printf( "%s %s at %s\n",
34             Devel::MAT::Cmd->format_note( $class->objectpad_type ? "role" : "class" ),
35             Devel::MAT::Cmd->format_symbol( $class->objectpad_name ),
36             Devel::MAT::Cmd->format_sv( $class ),
37             );
38             }
39              
40 1         158 return !!@classes;
41 1         56 } );
42             }
43              
44             package # hide
45             Devel::MAT::Tool::Object::Pad::fields;
46 2     2   14 use base qw( Devel::MAT::Tool );
  2         3  
  2         216  
47              
48 2     2   11 use constant CMD => "fields";
  2         4  
  2         123  
49 2     2   10 use constant CMD_DESC => "Display the fields of an Object::Pad instance";
  2         3  
  2         94  
50              
51 2     2   10 use constant CMD_ARGS_SV => 1;
  2         3  
  2         1484  
52              
53             sub run
54             {
55 4     4   8423 my $self = shift;
56 4         11 my ( $sv ) = @_;
57              
58 4 50       28 if( $sv->type eq "REF" ) {
59 0         0 $sv = $sv->rv;
60             }
61              
62 4 50       18 my $package = $sv->blessed or
63             die "SV is not a blessed object instance\n";
64              
65 4 50       101 my $class = $package->objectpad_class or
66             die $package->stashname . " is not an Object::Pad class\n";
67              
68 4 50       71 my $fieldav = $self->df->sv_at( $sv->{objectpad_fields_at} ) or
69             die "SV has no Object::Pad fields AV";
70              
71 4         85 Devel::MAT::Cmd->printf( "The field AV %s\n",
72             Devel::MAT::Cmd->format_sv( $fieldav ) );
73              
74 4         380 my @rows;
75 4         20 $self->_walk_fields_for_class( $class, undef, $fieldav, \@rows );
76              
77 4         116 Devel::MAT::Cmd->print_table( \@rows,
78             headings => [ "Ix", "Field", "Value" ],
79             );
80             }
81              
82             sub _walk_fields_for_class
83             {
84 6     6   31 my $self = shift;
85 6         17 my ( $classmeta, $nameprefix, $fieldav, $rows, $offset ) = @_;
86 6   100     34 $offset //= 0;
87              
88 6         19 my $is_class = $classmeta->objectpad_type == 0;
89              
90 6 100 100     26 if( $is_class and my $superclass = $classmeta->objectpad_superclass ) {
91 1         22 $self->_walk_fields_for_class( $superclass, $superclass->objectpad_name, $fieldav, $rows );
92             }
93              
94 6         98 foreach my $fieldmeta ( $classmeta->objectpad_direct_fields ) {
95 10         764 my $name = $fieldmeta->objectpad_name;
96 10         187 my $fieldix = $fieldmeta->objectpad_fieldix + $offset;
97              
98 10         41 my $value = $fieldav->elem( $fieldix );
99              
100             # non-scalar fields are stored as REFs
101 10 100       229 if( $name !~ m/^\$/ ) {
102             # TODO: Complain if this isn't a REF
103 4         17 $value = $value->rv;
104             }
105              
106             push @$rows, [
107             $fieldix,
108 10         98 Devel::MAT::Cmd->format_note( join( "/", grep { defined } $nameprefix, $name ), 1 ),
  20         118  
109             Devel::MAT::Cmd->format_sv_with_value( $value ),
110             ];
111             }
112              
113 6 100       986 if( $is_class ) {
114 5         20 foreach my $embedding ( $classmeta->objectpad_direct_roles ) {
115 1         47 my $rolemeta = $embedding->objectpad_role;
116              
117 1         22 $self->_walk_fields_for_class( $rolemeta, $rolemeta->objectpad_name, $fieldav, $rows, $embedding->objectpad_offset );
118             }
119             }
120             }
121              
122             0x55AA;