line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
# ABSTRACT: MooseX::Extended roles |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
use strict; |
5
|
6
|
|
|
6
|
|
15032
|
use warnings; |
|
6
|
|
|
|
|
38
|
|
|
6
|
|
|
|
|
174
|
|
6
|
6
|
|
|
6
|
|
29
|
use Moose::Exporter; |
|
6
|
|
|
|
|
8
|
|
|
6
|
|
|
|
|
136
|
|
7
|
6
|
|
|
6
|
|
528
|
use MooseX::Extended::Core qw( |
|
6
|
|
|
|
|
7360
|
|
|
6
|
|
|
|
|
44
|
|
8
|
6
|
|
|
|
|
413
|
field |
9
|
|
|
|
|
|
|
param |
10
|
|
|
|
|
|
|
_debug |
11
|
|
|
|
|
|
|
_assert_import_list_is_valid |
12
|
|
|
|
|
|
|
_enabled_features |
13
|
|
|
|
|
|
|
_disabled_warnings |
14
|
|
|
|
|
|
|
_our_import |
15
|
|
|
|
|
|
|
_our_init_meta |
16
|
|
|
|
|
|
|
); |
17
|
6
|
|
|
6
|
|
284
|
use MooseX::Role::WarnOnConflict (); |
|
6
|
|
|
|
|
12
|
|
18
|
6
|
|
|
6
|
|
2747
|
use Moose::Role; |
|
6
|
|
|
|
|
479183
|
|
|
6
|
|
|
|
|
198
|
|
19
|
6
|
|
|
6
|
|
41
|
use Moose::Meta::Role; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
41
|
|
20
|
6
|
|
|
6
|
|
28084
|
use namespace::autoclean (); |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
207
|
|
21
|
6
|
|
|
6
|
|
706
|
use Import::Into; |
|
6
|
|
|
|
|
8205
|
|
|
6
|
|
|
|
|
141
|
|
22
|
6
|
|
|
6
|
|
31
|
use true; |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
146
|
|
23
|
6
|
|
|
6
|
|
1605
|
use feature _enabled_features(); |
|
6
|
|
|
|
|
17252
|
|
|
6
|
|
|
|
|
32
|
|
24
|
6
|
|
|
6
|
|
5991
|
no warnings _disabled_warnings(); |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
29
|
|
25
|
6
|
|
|
6
|
|
35
|
|
|
6
|
|
|
|
|
13
|
|
|
6
|
|
|
|
|
21
|
|
26
|
|
|
|
|
|
|
our $VERSION = '0.33'; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Should this be in the metaclass? It feels like it should, but |
29
|
|
|
|
|
|
|
# the MOP really doesn't support these edge cases. |
30
|
|
|
|
|
|
|
my %CONFIG_FOR; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my ( $class, %args ) = @_; |
33
|
|
|
|
|
|
|
my @caller = caller(0); |
34
|
24
|
|
|
24
|
|
41816
|
$args{_import_type} = 'role'; |
35
|
24
|
|
|
|
|
115
|
$args{_caller_eval} = ( $caller[1] =~ /^\(eval/ ); |
36
|
24
|
|
|
|
|
151
|
my $target_class = _assert_import_list_is_valid( $class, \%args ); |
37
|
24
|
|
|
|
|
72
|
my @with_meta = grep { not $args{excludes}{$_} } qw(field param); |
38
|
24
|
|
|
|
|
82
|
if (@with_meta) { |
39
|
23
|
|
|
|
|
42
|
@with_meta = ( with_meta => [@with_meta] ); |
|
46
|
|
|
|
|
106
|
|
40
|
23
|
50
|
|
|
|
53
|
} |
41
|
23
|
|
|
|
|
54
|
my ( $import, undef, undef ) = Moose::Exporter->setup_import_methods( |
42
|
|
|
|
|
|
|
@with_meta, |
43
|
23
|
|
|
|
|
79
|
); |
44
|
|
|
|
|
|
|
_our_import( $class, $import, $target_class ); |
45
|
|
|
|
|
|
|
} |
46
|
23
|
|
|
|
|
10317
|
|
47
|
|
|
|
|
|
|
my $for_class = $params{for_class}; |
48
|
|
|
|
|
|
|
_our_init_meta( $class, \&_apply_default_features, %params ); |
49
|
23
|
|
|
23
|
0
|
1504
|
return $for_class->meta; |
|
23
|
|
|
|
|
34
|
|
|
23
|
|
|
|
|
57
|
|
|
23
|
|
|
|
|
26
|
|
50
|
23
|
|
|
|
|
32
|
} |
51
|
23
|
|
|
|
|
86
|
|
52
|
23
|
|
|
|
|
285
|
|
53
|
|
|
|
|
|
|
if ( my $types = $config->{types} ) { |
54
|
|
|
|
|
|
|
_debug("$for_class: importing types '@$types'"); |
55
|
23
|
|
|
23
|
|
24
|
MooseX::Extended::Types->import::into( $for_class, @$types ); |
|
23
|
|
|
|
|
30
|
|
|
23
|
|
|
|
|
29
|
|
|
23
|
|
|
|
|
25
|
|
|
23
|
|
|
|
|
25
|
|
56
|
|
|
|
|
|
|
} |
57
|
23
|
100
|
|
|
|
46
|
|
58
|
2
|
|
|
|
|
10
|
Carp->import::into($for_class) unless $config->{excludes}{carp}; |
59
|
2
|
|
|
|
|
18
|
namespace::autoclean->import::into($for_class) unless $config->{excludes}{autoclean}; |
60
|
|
|
|
|
|
|
true->import unless $config->{excludes}{true} || $config->{_caller_eval}; # https://github.com/Ovid/moosex-extended/pull/34 |
61
|
|
|
|
|
|
|
MooseX::Role::WarnOnConflict->import::into($for_class) unless $config->{excludes}{WarnOnConflict}; |
62
|
23
|
50
|
|
|
|
9190
|
|
63
|
23
|
50
|
|
|
|
5044
|
feature->import( _enabled_features() ); |
64
|
23
|
100
|
66
|
|
|
4360
|
warnings->unimport(_disabled_warnings); |
65
|
23
|
100
|
|
|
|
3978
|
|
66
|
|
|
|
|
|
|
Moose::Role->init_meta( ## |
67
|
23
|
|
|
|
|
116202
|
%$params, ## |
68
|
23
|
|
|
|
|
136
|
metaclass => 'Moose::Meta::Role' |
69
|
|
|
|
|
|
|
); |
70
|
23
|
|
|
|
|
108
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
1; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=pod |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=encoding UTF-8 |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=head1 NAME |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
MooseX::Extended::Role - MooseX::Extended roles |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head1 VERSION |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
version 0.33 |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=head1 SYNOPSIS |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
package Not::Corinna::Role::Created { |
90
|
|
|
|
|
|
|
use MooseX::Extended::Role types => ['PositiveInt']; |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
field created => ( isa => PositiveInt, default => sub { time } ); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Similar to L<MooseX::Extended>, providing almost everything that module provides. |
96
|
|
|
|
|
|
|
However, for obvious reasons, it does not include L<MooseX::StrictConstructor> |
97
|
|
|
|
|
|
|
or make your class immutable, or set the C3 mro. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Note that there is no need to add a C<1> at the end of the role. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head1 CONFIGURATION |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
You may pass an import list to L<MooseX::Extended::Role>. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
use MooseX::Extended::Role |
106
|
|
|
|
|
|
|
excludes => [qw/WarnOnConflict carp/], # I don't want these features |
107
|
|
|
|
|
|
|
types => [qw/compile PositiveInt HashRef/]; # I want these type tools |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head2 C<types> |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Allows you to import any types provided by L<MooseX::Extended::Types>. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
This: |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
use MooseX::Extended::Role types => [qw/compile PositiveInt HashRef/]; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Is identical to this: |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
use MooseX::Extended::Role; |
120
|
|
|
|
|
|
|
use MooseX::Extended::Types qw( compile PositiveInt HashRef ); |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=head2 C<excludes> |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
You may find some features to be annoying, or even cause potential bugs (e.g., |
125
|
|
|
|
|
|
|
if you have a `croak` method, our importing of C<Carp::croak> will be a |
126
|
|
|
|
|
|
|
problem. You can exclude the following: |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=over 4 |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=item * C<WarnOnConflict> |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
use MooseX::Extended::Role excludes => ['WarnOnConflict']; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
Excluding this removes the C<MooseX::Role::WarnOnConflict> role. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item * C<autoclean> |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
use MooseX::Extended::Role excludes => ['autoclean']; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Excluding this will no longer import C<namespace::autoclean>. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item * C<carp> |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
use MooseX::Extended::Role excludes => ['carp']; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Excluding this will no longer import C<Carp::croak> and C<Carp::carp>. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item * C<true> |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
use MooseX::Extended::Role excludes => ['true']; |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Excluding this will require your module to end in a true value. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item * C<param> |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
use MooseX::Extended::Role excludes => ['param']; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
Excluding this will make the C<param> function unavailable. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=item * C<field> |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
use MooseX::Extended::Role excludes => ['field']; |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Excluding this will make the C<field> function unavailable. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=back |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head2 C<includes> |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Some experimental features are useful, but might not be quite what you want. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
use MooseX::Extended::Role includes => [qw/multi/]; |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
multi sub foo ($self, $x) { ... } |
175
|
|
|
|
|
|
|
multi sub foo ($self, $x, $y ) { ... } |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
See L<MooseX::Extended::Manual::Includes> for more information. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 IDENTICAL METHOD NAMES IN CLASSES AND ROLES |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
In L<Moose> if a class defines a method of the name as the method of a role |
182
|
|
|
|
|
|
|
it's consuming, the role's method is I<silently> discarded. With |
183
|
|
|
|
|
|
|
L<MooseX::Extended::Role>, you get a warning. This makes maintenance easier |
184
|
|
|
|
|
|
|
when to prevent you from accidentally overriding a method. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
For example: |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
package My::Role { |
189
|
|
|
|
|
|
|
use MooseX::Extended::Role; |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub name {'Ovid'} |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
package My::Class { |
195
|
|
|
|
|
|
|
use MooseX::Extended; |
196
|
|
|
|
|
|
|
with 'My::Role'; |
197
|
|
|
|
|
|
|
sub name {'Bob'} |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
The above code will still run, but you'll get a very verbose warning: |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
The class My::Class has implicitly overridden the method (name) from |
203
|
|
|
|
|
|
|
role My::Role. If this is intentional, please exclude the method from |
204
|
|
|
|
|
|
|
composition to silence this warning (see Moose::Cookbook::Roles::Recipe2) |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
To silence the warning, just be explicit about your intent: |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
package My::Class { |
209
|
|
|
|
|
|
|
use MooseX::Extended; |
210
|
|
|
|
|
|
|
with 'My::Role' => { -excludes => ['name'] }; |
211
|
|
|
|
|
|
|
sub name {'Bob'} |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Alternately, you can exclude this feature. We don't recommend this, but it |
215
|
|
|
|
|
|
|
might be useful if you're refactoring a legacy Moose system. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
use MooseX::Extended::Role excludes => [qw/WarnOnConflict/]; |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=head1 ATTRIBUTE SHORTCUTS |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
C<param> and C<field> in roles allow the same L<attribute |
222
|
|
|
|
|
|
|
shortcuts|MooseX::Extended::Manual::Shortcuts> as L<MooseX::Extended>. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=head1 BUGS AND LIMITATIONS |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
If the MooseX::Extended::Role is loaded via I<stringy> eval, C<true> is not |
227
|
|
|
|
|
|
|
loaded, This is because there were intermittant errors (maybe 1 out of 5 |
228
|
|
|
|
|
|
|
times) being thrown. Removing this feature under stringy eval solves this. See |
229
|
|
|
|
|
|
|
L<this github ticket for more |
230
|
|
|
|
|
|
|
infomration|https://github.com/Ovid/moosex-extended/pull/34>. |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=head1 REDUCING BOILERPLATE |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
Let's say you've settled on the following feature set: |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
use MooseX::Extended::Role |
237
|
|
|
|
|
|
|
excludes => [qw/WarnOnConflict carp/], |
238
|
|
|
|
|
|
|
includes => [qw/multi/]; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
And you keep typing that over and over. We've removed a lot of boilerplate, |
241
|
|
|
|
|
|
|
but we've added different boilerplate. Instead, just create |
242
|
|
|
|
|
|
|
C<My::Custom::Moose::Role> and C<use My::Custom::Moose::Role;>. See |
243
|
|
|
|
|
|
|
L<MooseX::Extended::Role::Custom> for details. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=head1 AUTHOR |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
Curtis "Ovid" Poe <curtis.poe@gmail.com> |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
This software is Copyright (c) 2022 by Curtis "Ovid" Poe. |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
This is free software, licensed under: |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
The Artistic License 2.0 (GPL Compatible) |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=cut |