Move M::Util::(version|authority|identifier) to M::Meta::Module
[gitmo/Mouse.git] / lib / Mouse / Util.pm
CommitLineData
4093c859 1package Mouse::Util;
2use strict;
3use warnings;
5c12655d 4use base qw/Exporter/;
3a63a2e7 5use Carp qw(confess);
6use B ();
4093c859 7
eae80759 8our @EXPORT_OK = qw(
eae80759 9 get_linear_isa
e2578812 10 apply_all_roles
3a63a2e7 11 get_code_info
eae80759 12);
13our %EXPORT_TAGS = (
14 all => \@EXPORT_OK,
15);
16
42d7df00 17BEGIN {
272a1930 18 my $impl;
bcd39bf4 19 if ($] >= 5.009_005) {
388b8ebd 20 require mro;
272a1930 21 $impl = \&mro::get_linear_isa;
22 } else {
e0396a57 23 my $e = do {
24 local $@;
25 eval { require MRO::Compat };
26 $@;
f172d4e7 27 };
e0396a57 28 if (!$e) {
272a1930 29 $impl = \&mro::get_linear_isa;
30 } else {
31# VVVVV CODE TAKEN FROM MRO::COMPAT VVVVV
e0396a57 32 my $_get_linear_isa_dfs; # this recurses so it isn't pretty
33 $_get_linear_isa_dfs = sub {
272a1930 34 no strict 'refs';
35
36 my $classname = shift;
37
38 my @lin = ($classname);
39 my %stored;
40 foreach my $parent (@{"$classname\::ISA"}) {
e0396a57 41 my $plin = $_get_linear_isa_dfs->($parent);
42 foreach my $p(@$plin) {
43 next if exists $stored{$p};
44 push(@lin, $p);
45 $stored{$p} = 1;
272a1930 46 }
47 }
48 return \@lin;
49 };
50# ^^^^^ CODE TAKEN FROM MRO::COMPAT ^^^^^
e0396a57 51 $impl = $_get_linear_isa_dfs;
eae80759 52 }
53 }
bcd39bf4 54
272a1930 55 no strict 'refs';
56 *{ __PACKAGE__ . '::get_linear_isa'} = $impl;
eae80759 57}
58
3a63a2e7 59{ # taken from Sub::Identify
60 sub get_code_info($) {\r
61 my ($coderef) = @_;\r
62 ref($coderef) or return;\r
23264b5b 63
3a63a2e7 64 my $cv = B::svref_2object($coderef);\r
65 $cv->isa('B::CV') or return;
66
67 my $gv = $cv->GV;\r
23264b5b 68 $gv->isa('B::GV') or return;\r
3a63a2e7 69\r
70 return ($gv->STASH->NAME, $gv->NAME);\r
71 }\r
72}
73
abfdffe0 74# taken from Class/MOP.pm
75{
76 my %cache;
77
78 sub resolve_metaclass_alias {
79 my ( $type, $metaclass_name, %options ) = @_;
80
81 my $cache_key = $type;
82 return $cache{$cache_key}{$metaclass_name}
83 if $cache{$cache_key}{$metaclass_name};
84
85 my $possible_full_name =
86 'Mouse::Meta::'
87 . $type
88 . '::Custom::'
89 . $metaclass_name;
90
91 my $loaded_class =
92 load_first_existing_class( $possible_full_name,
93 $metaclass_name );
94
95 return $cache{$cache_key}{$metaclass_name} =
96 $loaded_class->can('register_implementation')
97 ? $loaded_class->register_implementation
98 : $loaded_class;
99 }
100}
101
102# taken from Class/MOP.pm
103sub _is_valid_class_name {
104 my $class = shift;
105
106 return 0 if ref($class);
107 return 0 unless defined($class);
108 return 0 unless length($class);
109
110 return 1 if $class =~ /^\w+(?:::\w+)*$/;
111
112 return 0;
113}
114
115# taken from Class/MOP.pm
116sub load_first_existing_class {
117 my @classes = @_
118 or return;
119
23264b5b 120 my $found;
121 my %exceptions;
122 for my $class (@classes) {
abfdffe0 123 unless ( _is_valid_class_name($class) ) {
124 my $display = defined($class) ? $class : 'undef';
125 confess "Invalid class name ($display)";
126 }
abfdffe0 127
abfdffe0 128 my $e = _try_load_one_class($class);
129
130 if ($e) {
131 $exceptions{$class} = $e;
132 }
133 else {
134 $found = $class;
135 last;
136 }
137 }
138 return $found if $found;
139
140 confess join(
141 "\n",
142 map {
143 sprintf( "Could not load class (%s) because : %s",
144 $_, $exceptions{$_} )
145 } @classes
146 );
147}
148
149# taken from Class/MOP.pm
150sub _try_load_one_class {
151 my $class = shift;
152
153 return if Mouse::is_class_loaded($class);
154
155 my $file = $class . '.pm';
156 $file =~ s{::}{/}g;
157
158 return do {
159 local $@;
160 eval { require($file) };
161 $@;
162 };
163}
164
2e92bb89 165sub apply_all_roles {
166 my $meta = Mouse::Meta::Class->initialize(shift);
2e92bb89 167
21498b08 168 my @roles;
f6715552 169
170 # Basis of Data::OptList
21498b08 171 my $max = scalar(@_);
172 for (my $i = 0; $i < $max ; $i++) {
173 if ($i + 1 < $max && ref($_[$i + 1])) {
174 push @roles, [ $_[$i++] => $_[$i] ];
175 } else {
176 push @roles, [ $_[$i] => {} ];
177 }
178 }
179
180 foreach my $role_spec (@roles) {
181 Mouse::load_class( $role_spec->[0] );
182 }
183
184 ( $_->[0]->can('meta') && $_->[0]->meta->isa('Mouse::Meta::Role') )
3a63a2e7 185 || confess("You can only consume roles, "
21498b08 186 . $_->[0]
187 . " is not a Moose role")
188 foreach @roles;
189
190 if ( scalar @roles == 1 ) {
191 my ( $role, $params ) = @{ $roles[0] };
192 $role->meta->apply( $meta, ( defined $params ? %$params : () ) );
193 }
194 else {
195 Mouse::Meta::Role->combine_apply($meta, @roles);
196 }
23264b5b 197 return;
2e92bb89 198}
199
4093c859 2001;
201
f38ce2d0 202__END__
203
204=head1 NAME
205
206Mouse::Util - features, with or without their dependencies
207
208=head1 IMPLEMENTATIONS FOR
209
210=head2 L<MRO::Compat>
211
212=head3 get_linear_isa
213
f38ce2d0 214=cut
215