Commit | Line | Data |
f8881bd9 |
1 | package Devel::SelfStubber; |
2 | require SelfLoader; |
3 | @ISA = qw(SelfLoader); |
73c78b0a |
4 | @EXPORT = 'AUTOLOAD'; |
f8881bd9 |
5 | $JUST_STUBS = 1; |
a1457ef1 |
6 | $VERSION = '1.02'; |
7 | sub Version {$VERSION} |
f8881bd9 |
8 | |
9 | # Use as |
10 | # perl -e 'use Devel::SelfStubber;Devel::SelfStubber->stub(MODULE_NAME,LIB)' |
11 | # (LIB defaults to '.') e.g. |
12 | # perl -e 'use Devel::SelfStubber;Devel::SelfStubber->stub('Math::BigInt')' |
13 | # would print out stubs needed if you added a __DATA__ before the subs. |
14 | # Setting $Devel::SelfStubber::JUST_STUBS to 0 will print out the whole |
15 | # module with the stubs entered just before the __DATA__ |
16 | |
17 | sub _add_to_cache { |
18 | my($self,$fullname,$pack,$lines, $prototype) = @_; |
19 | push(@DATA,@{$lines}); |
20 | if($fullname){push(@STUBS,"sub $fullname $prototype;\n")}; # stubs |
21 | '1;'; |
22 | } |
23 | |
24 | sub _package_defined { |
25 | my($self,$line) = @_; |
26 | push(@DATA,$line); |
27 | } |
28 | |
29 | sub stub { |
30 | my($self,$module,$lib) = @_; |
31 | my($line,$end,$fh,$mod_file,$found_selfloader); |
32 | $lib ||= '.'; |
33 | ($mod_file = $module) =~ s,::,/,g; |
34 | |
35 | $mod_file = "$lib/$mod_file.pm"; |
36 | $fh = "${module}::DATA"; |
37 | |
38 | open($fh,$mod_file) || die "Unable to open $mod_file"; |
40da2db3 |
39 | while(defined ($line = <$fh>) and $line !~ m/^__DATA__/) { |
f8881bd9 |
40 | push(@BEFORE_DATA,$line); |
41 | $line =~ /use\s+SelfLoader/ && $found_selfloader++; |
42 | } |
43 | $line =~ m/^__DATA__/ || die "$mod_file doesn't contain a __DATA__ token"; |
44 | $found_selfloader || |
45 | print 'die "\'use SelfLoader;\' statement NOT FOUND!!\n"',"\n"; |
46 | $self->_load_stubs($module); |
47 | if ( fileno($fh) ) { |
48 | $end = 1; |
40da2db3 |
49 | while(defined($line = <$fh>)) { |
f8881bd9 |
50 | push(@AFTER_DATA,$line); |
51 | } |
52 | } |
53 | unless ($JUST_STUBS) { |
54 | print @BEFORE_DATA; |
55 | } |
56 | print @STUBS; |
57 | unless ($JUST_STUBS) { |
58 | print "1;\n__DATA__\n",@DATA; |
59 | if($end) { print "__END__\n",@AFTER_DATA; } |
60 | } |
61 | } |
62 | |
63 | 1; |
64 | __END__ |
cb1a09d0 |
65 | |
f8881bd9 |
66 | =head1 NAME |
67 | |
68 | Devel::SelfStubber - generate stubs for a SelfLoading module |
69 | |
70 | =head1 SYNOPSIS |
71 | |
72 | To generate just the stubs: |
73 | |
74 | use Devel::SelfStubber; |
75 | Devel::SelfStubber->stub('MODULENAME','MY_LIB_DIR'); |
76 | |
77 | or to generate the whole module with stubs inserted correctly |
78 | |
79 | use Devel::SelfStubber; |
80 | $Devel::SelfStubber::JUST_STUBS=0; |
81 | Devel::SelfStubber->stub('MODULENAME','MY_LIB_DIR'); |
82 | |
83 | MODULENAME is the Perl module name, e.g. Devel::SelfStubber, |
84 | NOT 'Devel/SelfStubber' or 'Devel/SelfStubber.pm'. |
85 | |
86 | MY_LIB_DIR defaults to '.' if not present. |
87 | |
88 | =head1 DESCRIPTION |
89 | |
90 | Devel::SelfStubber prints the stubs you need to put in the module |
91 | before the __DATA__ token (or you can get it to print the entire |
92 | module with stubs correctly placed). The stubs ensure that if |
93 | a method is called, it will get loaded. They are needed specifically |
94 | for inherited autoloaded methods. |
95 | |
96 | This is best explained using the following example: |
97 | |
98 | Assume four classes, A,B,C & D. |
99 | |
100 | A is the root class, B is a subclass of A, C is a subclass of B, |
101 | and D is another subclass of A. |
102 | |
103 | A |
104 | / \ |
105 | B D |
106 | / |
107 | C |
108 | |
109 | If D calls an autoloaded method 'foo' which is defined in class A, |
110 | then the method is loaded into class A, then executed. If C then |
111 | calls method 'foo', and that method was reimplemented in class |
112 | B, but set to be autoloaded, then the lookup mechanism never gets to |
113 | the AUTOLOAD mechanism in B because it first finds the method |
114 | already loaded in A, and so erroneously uses that. If the method |
115 | foo had been stubbed in B, then the lookup mechanism would have |
116 | found the stub, and correctly loaded and used the sub from B. |
117 | |
118 | So, for classes and subclasses to have inheritance correctly |
119 | work with autoloading, you need to ensure stubs are loaded. |
120 | |
121 | The SelfLoader can load stubs automatically at module initialization |
1fef88e7 |
122 | with the statement 'SelfLoader-E<gt>load_stubs()';, but you may wish to |
f8881bd9 |
123 | avoid having the stub loading overhead associated with your |
124 | initialization (though note that the SelfLoader::load_stubs method |
125 | will be called sooner or later - at latest when the first sub |
126 | is being autoloaded). In this case, you can put the sub stubs |
127 | before the __DATA__ token. This can be done manually, but this |
128 | module allows automatic generation of the stubs. |
129 | |
130 | By default it just prints the stubs, but you can set the |
131 | global $Devel::SelfStubber::JUST_STUBS to 0 and it will |
132 | print out the entire module with the stubs positioned correctly. |
133 | |
134 | At the very least, this is useful to see what the SelfLoader |
135 | thinks are stubs - in order to ensure future versions of the |
136 | SelfStubber remain in step with the SelfLoader, the |
137 | SelfStubber actually uses the SelfLoader to determine which |
138 | stubs are needed. |
139 | |
140 | =cut |