8 use List::MoreUtils 'any';
10 use Scalar::Util 'blessed';
11 use Test::Requires 'PadWalker';
13 sub doesnt_close_over_meta {
14 local $Test::Builder::Level = $Test::Builder::Level + 1;
16 my ($pkg, $name) = Class::MOP::get_code_info($code);
17 my $closed_over = PadWalker::closed_over($code);
18 ok(!(any { ref eq 'REF' && blessed($$_) && $$_->isa('Class::MOP::Object') }
19 values %$closed_over),
20 "${pkg}::${name} doesn't close over any metaobjects");
23 sub class_doesnt_close_over_meta {
24 local $Test::Builder::Level = $Test::Builder::Level + 1;
26 my $stash = Package::Stash->new($class);
28 doesnt_close_over_meta($_)
29 for map { $stash->get_package_symbol('&' . $_) }
31 $stash->list_all_package_symbols('CODE');
36 package BasicAccessors;
41 clearer => 'clear_foo',
42 predicate => 'has_foo',
58 package MethodModifiers::Base;
65 sub quuux_base { inner() };
71 package MethodModifiers;
73 extends 'MethodModifiers::Base';
79 before foo => sub { };
81 around baz => sub { };
83 before foo_base => sub { };
84 after bar_base => sub { };
85 around baz_base => sub { };
86 override quux_base => sub { super() };
87 augment quuux_base => sub { inner() };
93 package ConstructorDestructor;
103 default => sub { [] },
108 builder => '_build_build',
117 has def_ref_lazy => (
119 default => sub { [] },
125 builder => '_build_build_lazy',
129 sub _build_build { '' }
130 sub _build_build_lazy { '' }
133 sub BUILDARGS { shift->SUPER::BUILDARGS(@_) }
140 package FancyAccessors;
142 use Moose::Util::TypeConstraints;
144 subtype 'Coerced', as 'Str', where { /a-z/ };
145 coerce 'Coerced', from 'Str', via { lc };
149 isa => 'FancyAccessors',
151 initializer => sub { $_[2]->($_[1]) },
158 trigger => sub { 'foo' },
164 isa => 'ArrayRef[Int]',
167 documentation => "it's a baz",
171 no Moose::Util::TypeConstraints;
175 package NativeTraits;
181 default => sub { [] },
183 array_count => 'count',
184 array_elements => 'elements',
185 array_is_empty => 'is_empty',
186 array_push => 'push',
187 array_push_curried => [ push => 42, 84 ],
188 array_unshift => 'unshift',
189 array_unshift_curried => [ unshift => 42, 84 ],
191 array_shift => 'shift',
193 array_get_curried => [ get => 1 ],
195 array_set_curried_1 => [ set => 1 ],
196 array_set_curried_2 => [ set => ( 1, 98 ) ],
197 array_accessor => 'accessor',
198 array_accessor_curried_1 => [ accessor => 1 ],
199 array_accessor_curried_2 => [ accessor => ( 1, 90 ) ],
200 array_clear => 'clear',
201 array_delete => 'delete',
202 array_delete_curried => [ delete => 1 ],
203 array_insert => 'insert',
204 array_insert_curried => [ insert => ( 1, 101 ) ],
205 array_splice => 'splice',
206 array_splice_curried_1 => [ splice => 1 ],
207 array_splice_curried_2 => [ splice => 1, 2 ],
208 array_splice_curried_all => [ splice => 1, 2, ( 3, 4, 5 ) ],
209 array_sort => 'sort',
210 array_sort_curried =>
211 [ sort => ( sub { $_[1] <=> $_[0] } ) ],
212 array_sort_in_place => 'sort_in_place',
213 array_sort_in_place_curried =>
214 [ sort_in_place => ( sub { $_[1] <=> $_[0] } ) ],
216 array_map_curried => [ map => ( sub { $_ + 1 } ) ],
217 array_grep => 'grep',
218 array_grep_curried => [ grep => ( sub { $_ < 5 } ) ],
219 array_first => 'first',
220 array_first_curried => [ first => ( sub { $_ % 2 } ) ],
221 array_join => 'join',
222 array_join_curried => [ join => '-' ],
223 array_shuffle => 'shuffle',
224 array_uniq => 'uniq',
225 array_reduce => 'reduce',
226 array_reduce_curried =>
227 [ reduce => ( sub { $_[0] * $_[1] } ) ],
228 array_natatime => 'natatime',
229 array_natatime_curried => [ natatime => 2 ],
238 bool_illuminate => 'set',
239 bool_darken => 'unset',
240 bool_flip_switch => 'toggle',
241 bool_is_dark => 'not',
248 default => sub { sub { } },
250 code_execute => 'execute',
251 code_execute_method => 'execute_method',
256 traits => ['Counter'],
260 inc_counter => 'inc',
261 inc_counter_2 => [ inc => 2 ],
262 dec_counter => 'dec',
263 dec_counter_2 => [ dec => 2 ],
264 reset_counter => 'reset',
265 set_counter => 'set',
266 set_counter_42 => [ set => 42 ],
273 default => sub { {} },
275 hash_option_accessor => 'accessor',
276 hash_quantity => [ accessor => 'quantity' ],
277 hash_clear_options => 'clear',
278 hash_num_options => 'count',
279 hash_delete_option => 'delete',
280 hash_is_defined => 'defined',
281 hash_options_elements => 'elements',
282 hash_has_option => 'exists',
283 hash_get_option => 'get',
284 hash_has_no_options => 'is_empty',
285 hash_key_value => 'kv',
286 hash_set_option => 'set',
291 traits => ['Number'],
297 num_inc => [ add => 1 ],
299 num_cut_in_half => [ div => 2 ],
301 num_odd => [ mod => 2 ],
305 num_dec => [ sub => 1 ],
310 traits => ['String'],
315 string_append => 'append',
316 string_append_curried => [ append => '!' ],
317 string_prepend => 'prepend',
318 string_prepend_curried => [ prepend => '-' ],
319 string_replace => 'replace',
320 string_replace_curried => [ replace => qr/(.)$/, sub { uc $1 } ],
321 string_chop => 'chop',
322 string_chomp => 'chomp',
323 string_clear => 'clear',
324 string_match => 'match',
325 string_match_curried => [ match => qr/\D/ ],
326 string_length => 'length',
327 string_substr => 'substr',
328 string_substr_curried_1 => [ substr => (1) ],
329 string_substr_curried_2 => [ substr => ( 1, 3 ) ],
330 string_substr_curried_3 => [ substr => ( 1, 3, 'ong' ) ],
337 { local $TODO = "we close over all kinds of stuff";
338 class_doesnt_close_over_meta('BasicAccessors');
339 class_doesnt_close_over_meta('MethodModifiers');
340 class_doesnt_close_over_meta('ConstructorDestructor');
341 class_doesnt_close_over_meta('FancyAccessors');
342 class_doesnt_close_over_meta('NativeTraits');