File Coverage

blib/lib/App/Devel/MAT/Explorer/GTK/SVDetail.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.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, 2016 -- leonerd@leonerd.org.uk
5              
6             package App::Devel::MAT::Explorer::GTK::SVDetail;
7              
8 1     1   1148 use strict;
  1         2  
  1         27  
9 1     1   4 use warnings;
  1         1  
  1         29  
10 1     1   3 use feature qw( switch );
  1         1  
  1         86  
11 1     1   506 no if $] >= 5.017011, warnings => 'experimental::smartmatch';
  1         8  
  1         4  
12              
13             our $VERSION = '0.02';
14              
15 1     1   469 use Devel::MAT 0.23; # ->ifileno, ->ofileno on IO SVs
  1         36057  
  1         33  
16              
17 1     1   57 use App::Devel::MAT::Explorer::GTK::Resources qw( get_icon );
  0            
  0            
18             use App::Devel::MAT::Explorer::GTK::Widgets qw( label textarea );
19              
20             use Struct::Dumb qw( -named_constructors );
21             use List::UtilsBy qw( nsort_by );
22              
23             struct SVDetail => [qw( order type title render expand )];
24              
25             my @MORE_DETAILS;
26              
27             sub table_add
28             {
29             my ( $table, $label, $widget, $yoptions, $right ) = @_;
30              
31             my $xoptions = [ "expand", "fill" ];
32             $yoptions //= [ "fill" ];
33             $right //= 3;
34              
35             my ( $next_row ) = $table->get_size;
36              
37             $table->attach( label( $label ), 0, 1, $next_row, $next_row + 1, $xoptions, $yoptions, 0, 3 );
38             $table->attach( $widget, 1, $right, $next_row, $next_row + 1, $xoptions, $yoptions, 0, 3 );
39             }
40              
41             sub display_sv_in_table
42             {
43             my ( $sv, $table ) = @_;
44              
45             # Common things for all widget types;
46             my $type = $sv->type;
47             table_add( $table, "Type" => textarea( $type ), undef, 2 );
48              
49             table_add( $table, "Address" => textarea( sprintf "%#x", $sv->addr ), undef, 2 );
50              
51             table_add( $table, "SvREFCNT" => textarea( $sv->refcnt ), undef, 2 );
52              
53             my $sizestr = $sv->size;
54             if( $sv->size > 1024 ) {
55             $sizestr = bytes2size( $sv->size ) . " ($sizestr)";
56             }
57             table_add( $table, "Size" => textarea( $sizestr ), undef, 2 );
58              
59             table_add( $table, "Description" => textarea( $sv->desc ) );
60              
61             $table->attach(
62             Gtk2::Image->new_from_pixbuf( get_icon( "type-$type", w => 40, h => 40 ) ),
63             2, 3, 1, 5, [], [], 5, 5,
64             );
65              
66             if( my $stash = $sv->blessed ) {
67             table_add( $table, "Blessed", textarea( $stash->stashname ) );
68             }
69              
70             given( $type ) {
71             when([ "GLOB", "CODE", "STASH" ]) {
72             table_add( $table, "Stashname", textarea( $sv->stashname ) ) if defined $sv->stashname;
73             }
74             }
75              
76             given( $type ) {
77             when( "CODE" ) {
78             table_add( $table, "Flags", textarea( join( " ",
79             ( $sv->is_clone ? "CLONE" : () ),
80             ( $sv->is_cloned ? "CLONED" : () ),
81             ( $sv->is_xsub ? "XSUB" : () ),
82             ( $sv->is_weakoutside ? "WEAKOUTSIDE" : () ),
83             ( $sv->is_cvgv_rc ? "CVGV_RC" : () ),
84             ( $sv->is_lexical ? "LEXICAL" : () ) ) ) );
85             table_add( $table, "Oproot", textarea( sprintf "%x (%d)", $sv->oproot, $sv->oproot ) ) if $sv->oproot;
86              
87             # depth only makes sense of PP subs
88             if( $sv->oproot and ( my $depth = $sv->depth ) > -1 ) {
89             table_add( $table, "Depth", textarea( $depth ) );
90             }
91             }
92             when( "SCALAR" ) {
93             table_add( $table, "UV", textarea( $sv->uv ) ) if defined $sv->uv;
94             table_add( $table, "IV", textarea( $sv->iv ) ) if defined $sv->iv;
95             table_add( $table, "NV", textarea( $sv->nv ) ) if defined $sv->nv;
96             if( defined $sv->pv ) {
97             table_add( $table, "PV len", textarea( $sv->pvlen ) );
98             table_add( $table, "PV", my $pvtext = textarea( $sv->qq_pv( 32 ) ) );
99             $pvtext->set_tooltip_text( $sv->qq_pv( 1024 ) );
100             }
101             }
102             when( "REF" ) {
103             table_add( $table, "RV", textarea( $sv->rv->desc . ( $sv->is_weak ? " weakly" : " strongly" ) ) )
104             if defined $sv->rv;
105             }
106             when( "IO" ) {
107             table_add( $table, "Input fileno", textarea( $sv->ifileno ) ) if $sv->ifileno != -1;
108             table_add( $table, "Output fileno", textarea( $sv->ofileno ) ) if $sv->ofileno != -1;
109             }
110             }
111              
112             given( $type ) {
113             when([ "SCALAR", "REF", "ARRAY", "HASH", "STASH", "CODE" ]) {
114             table_add( $table, "Name", textarea( $sv->name ) ) if defined $sv->name;
115             }
116             }
117              
118             given( $type ) {
119             when([ "GLOB", "CODE" ]) {
120             table_add( $table, "Location", textarea( $sv->location ) );
121             }
122             when([ "PAD", "PADNAMES", "PADLIST" ]) {
123             table_add( $table, "CV location", textarea( $sv->padcv->location ) );
124             }
125             }
126              
127             foreach my $extra ( nsort_by { $_->order } @MORE_DETAILS ) {
128             my $data = $extra->render->( $sv );
129             defined $data or next;
130              
131             my $widget;
132             given( $extra->type ) {
133             when( "widget" ) { $widget = $data }
134             when( "text" ) { $widget = textarea( $data ) }
135             when( "icon" ) { $widget = Gtk2::Image->new_from_pixbuf( get_icon( $data ) ) }
136             default { die "Unable to handle SV detail type " . $extra->type }
137             }
138              
139             table_add( $table, $extra->title => $widget, $extra->expand ? [ "expand", "fill" ] : undef )
140             }
141             }
142              
143             my $next_sv_detail_order = 0;
144             sub Devel::MAT::UI::provides_sv_detail
145             {
146             shift;
147             my %args = @_;
148              
149             push @MORE_DETAILS, SVDetail(
150             order => $args{order} // $next_sv_detail_order++,
151             type => $args{type},
152             title => $args{title},
153             render => $args{render},
154             expand => $args{expand},
155             );
156             }
157              
158             0x55AA;