File Coverage

lib/Devel/ebug/Wx/Publisher.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Devel::ebug::Wx::Publisher;
2              
3 1     1   37265 use strict;
  1         2  
  1         37  
4 1         807 use base qw(Class::Accessor::Fast Class::Publisher
5 1     1   4 Devel::ebug::Wx::Service::Base);
  1         3  
6              
7 1     1   433 use Devel::ebug::Wx::ServiceManager::Holder qw(:noautoload);
  0            
  0            
8              
9             __PACKAGE__->mk_ro_accessors( qw(ebug argv script) );
10             __PACKAGE__->mk_accessors( qw(_line _sub _package _file _running) );
11              
12             use Devel::ebug;
13              
14             sub new {
15             my( $class, $ebug ) = @_;
16             $ebug ||= Devel::ebug->new;
17             my $self = $class->SUPER::new( { ebug => $ebug,
18             _package => '',
19             _line => -1,
20             _sub => '',
21             _file => '',
22             _running => 0,
23             } );
24              
25             return $self;
26             }
27              
28             sub service_name { 'ebug_publisher' }
29              
30             sub DESTROY {
31             my ( $self ) = @_;
32             $self->delete_all_subscribers;
33             }
34              
35             sub can {
36             my( $self, $method ) = @_;
37             return undef if $method eq 'id';
38             my $can = $self->SUPER::can( $method );
39             return $can if $can;
40             return 1 if $self->ebug->can( $method ); # FIXME return coderef
41             }
42              
43             # FIXME: does not scale when additional ebug plugins are loaded
44             # maybe needs another level of plugins :-(
45             my %no_notify =
46             map { $_ => 1 }
47             qw(program line subroutine package filename codeline
48             filenames break_points codelines pad finished
49             is_running);
50              
51             my %must_be_running =
52             map { $_ => 1 }
53             qw(step next run return);
54              
55             our $AUTOLOAD;
56             sub AUTOLOAD {
57             my $self = shift;
58             ( my $sub = $AUTOLOAD ) =~ s/.*:://;
59             return if $must_be_running{$sub} && !$self->is_running;
60             if( wantarray ) {
61             my @res = $self->ebug->$sub( @_ );
62              
63             $self->_notify_basic_changes unless $no_notify{$sub};
64             return @res;
65             } else {
66             my $res = $self->ebug->$sub( @_ );
67              
68             $self->_notify_basic_changes unless $no_notify{$sub};
69             return $res;
70             }
71             }
72              
73             sub is_running {
74             my( $self ) = @_;
75              
76             return $self->argv && !$self->ebug->finished;
77             }
78              
79             sub load_program {
80             my( $self, $argv ) = @_;
81             $self->{argv} = $argv || $self->{argv} || [];
82             $self->{script} = $self->argv->[0];
83             my $filename = join ' ', @{$self->argv};
84              
85             unless ($filename) {
86             $filename = '-e "Interactive ebugging shell"';
87             }
88              
89             $self->ebug->program( $filename );
90             $self->ebug->load;
91             $self->_running( 1 );
92              
93             $self->notify_subscribers( 'load_program',
94             argv => $self->argv,
95             filename => $filename,
96             );
97             $self->_notify_basic_changes;
98             }
99              
100             sub save_program_state {
101             my( $self, $file ) = @_;
102             my $state = $self->ebug->get_state;
103             my $cfg = $self->get_service( 'configuration' )
104             ->get_config( 'ebug_publisher', $file );
105              
106             $cfg->set_serialized_value( 'state', $state );
107             }
108              
109             sub load_program_state {
110             my( $self, $file ) = @_;
111             my $cfg = $self->get_service( 'configuration' )
112             ->get_config( 'ebug_publisher', $file );
113             my $state = $cfg->get_serialized_value( 'state' );
114              
115             $self->set_state( $state ) if $state;
116             $self->notify_subscribers( 'load_program_state' ); # FIXME bad name
117             }
118              
119             sub reload_program {
120             my( $self ) = @_;
121              
122             my $state = $self->ebug->get_state;
123             $self->ebug->load;
124             $self->_running( 1 );
125             $self->ebug->set_state( $state );
126              
127             $self->notify_subscribers( 'load_program',
128             argv => $self->argv,
129             filename => $self->program,
130             );
131             $self->notify_subscribers( 'load_program_state' );
132             $self->_notify_basic_changes;
133             }
134              
135             sub break_point {
136             my( $self, $file, $line, $condition ) = @_;
137             return unless $self->is_running;
138             my $act_line = $self->ebug->break_point( $file, $line, $condition );
139              
140             return unless defined $act_line;
141             $self->notify_subscribers( 'break_point',
142             file => $file,
143             line => $act_line,
144             condition => $condition,
145             );
146             }
147              
148             sub break_point_delete {
149             my( $self, $file, $line ) = @_;
150             return unless $self->is_running;
151             $self->ebug->break_point_delete( $file, $line );
152              
153             $self->notify_subscribers( 'break_point_delete',
154             file => $file,
155             line => $line,
156             );
157             }
158              
159             sub _notify_basic_changes {
160             my( $self ) = @_;
161             my $ebug = $self->ebug;
162              
163             if( $ebug->finished && $self->_running ) {
164             $self->_running( 0 );
165             $self->notify_subscribers( 'finished' );
166             return;
167             }
168              
169             my $file_changed = $self->_file ne $ebug->filename;
170             my $line_changed = $self->_line ne $ebug->line;
171             my $sub_changed = $self->_sub ne $ebug->subroutine;
172             my $pack_changed = $self->_package ne $ebug->package;
173             my $any_changed = $file_changed || $line_changed ||
174             $sub_changed || $pack_changed;
175              
176             # must do it here or we risk infinite recursion
177             $self->_file( $ebug->filename );
178             $self->_line( $ebug->line );
179             $self->_sub( $ebug->subroutine );
180             $self->_package( $ebug->package );
181              
182             $self->notify_subscribers( 'file_changed',
183             old_file => $self->_file,
184             )
185             if $file_changed;
186             $self->notify_subscribers( 'line_changed',
187             old_line => $self->_line,
188             )
189             if $line_changed;
190             $self->notify_subscribers( 'sub_changed',
191             old_sub => $self->_sub,
192             )
193             if $sub_changed;
194             $self->notify_subscribers( 'package_changed',
195             old_package => $self->_package,
196             )
197             if $pack_changed;
198             $self->notify_subscribers( 'state_changed',
199             old_file => $self->_file,
200             old_line => $self->_line,
201             old_sub => $self->_sub,
202             old_package => $self->_package,
203             )
204             if $any_changed;
205             }
206              
207             1;