File Coverage

blib/lib/Devel/MAT/Tool/Object/Pad/_Commands.pm
Criterion Covered Total %
statement 72 73 98.6
branch 12 16 75.0
condition 7 8 87.5
subroutine 16 16 100.0
pod n/a
total 107 113 94.6


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