This file is indexed.

/usr/share/perl5/MooseX/Traits/Pluggable.pm is in libmoosex-traits-pluggable-perl 0.12-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
package MooseX::Traits::Pluggable;
{
  $MooseX::Traits::Pluggable::VERSION = '0.12';
}

use namespace::autoclean;
use Moose::Role;
use Scalar::Util qw/blessed reftype/;
use List::MoreUtils 'uniq';
use Carp;
use Moose::Util qw/find_meta/;
use Class::Load qw();

our $AUTHORITY = 'id:RKITOVER';

# stolen from MX::Object::Pluggable
has _original_class_name => (
  is => 'ro',
  required => 1,
  isa => 'Str',
  default => sub { blessed $_[0] },
);

has '_trait_namespace' => (
  # no accessors or init_arg
  init_arg => undef,
  (Moose->VERSION >= 0.84 ) ? (is => 'bare') : (),
);

has '_traits_behave_like_roles' => (
  init_arg => undef,
  (Moose->VERSION >= 0.84 ) ? (is => 'bare') : (),
);

has _traits => (
  is => 'ro',
  isa => 'ArrayRef[Str]',
  default => sub { [] },
);

has _resolved_traits => (
  is => 'ro',
  isa => 'ArrayRef[ClassName]',
  default => sub { [] },
);

sub _find_trait {
    my ($class, $base, $name) = @_;

    my @search_ns = $class->meta->class_precedence_list;

    for my $ns (@search_ns) {
        my $full = "${ns}::${base}::${name}";
        return $full if eval { Class::Load::load_class($full) };
    }

    croak "Could not find a class for trait: $name";
}

my $config_val = sub {
    my ($class, $attr, @args) = @_;

    my $val;

    if ($class->can($attr)) {
        $val = $class->$attr(@args);
    }
    else {
        my $attr_inst = find_meta($class)->find_attribute_by_name($attr);
        if($attr_inst->has_default) {
            $val = $attr_inst->default;
            if (ref($val) && reftype($val) eq 'CODE') {
                $val = $class->$val(@args);
            }
        }
    }

    return $val;
};

sub _transform_trait {
    my ($class, $name) = @_;

    my $base = $config_val->($class, '_trait_namespace', $name);

    return $name unless $base;
    return $1 if $name =~ /^[+](.+)$/;

    $base = [ $base ] if !ref($base) || reftype($base) ne 'ARRAY';

    for my $ns (@$base) {
        if ($ns =~ /^\+(.*)/) {
            my $trait = eval { $class->_find_trait($1, $name) };
            return $trait if defined $trait;
        }

        my $trait = join '::', $ns, $name;
        return $trait if eval { Class::Load::load_class($trait) };
    }

    croak "Could not find a class for trait: $name";
}

sub _resolve_traits {
    my ($class, @traits) = @_;

    return map {
        my $transformed = $class->_transform_trait($_);
        Class::Load::load_class($transformed);
        $transformed;
    } @traits;
}

sub new_with_traits {
    my $class = shift;
    $class->_build_instance_with_traits($class, @_);
}

my $remove_role_methods_conflicting_with_class = sub {
    my ($meta, $orig_class, $resolved_traits) = @_;

    my %class_methods;
    @class_methods{ $orig_class->meta->get_method_list } = ();
    
    delete $class_methods{meta};

    my %trait_methods;
    foreach my $trait (@$resolved_traits) {
        @trait_methods{ $trait->meta->get_method_list } = ();
    }

    delete $trait_methods{meta};

    foreach my $class_method (keys %class_methods) {
        $meta->remove_method($class_method) if exists $trait_methods{$class_method};
    }
};

sub _build_instance_with_traits {
    my ($this_class, $class) = (shift, shift);
    my ($hashref, %args, @others) = 0;
    if (ref($_[-1]) eq 'HASH') {
        %args    = %{ +pop };
        @others  = @_;
        $hashref = 1;
    } else {
        %args    = @_;
    }

    $args{_original_class_name} = $class;

    if (my $traits = delete $args{traits}) {
        my @traits = ref($traits) ? @$traits : ($traits);

        if (@traits) {
            $args{_traits} = \@traits;
            my @resolved_traits = $this_class->_resolve_traits(@traits);
            $args{_resolved_traits} = \@resolved_traits;

            my $meta = $class->meta->create_anon_class(
                superclasses => [ $class->meta->name ],
                roles        => \@resolved_traits,
                cache        => 1,
            );

            # Method attributes in inherited roles may have turned metaclass
            # to lies. CatalystX::Component::Traits related special move
            # to deal with this here.
            $meta = find_meta($meta->name);

            $meta->add_method('meta' => sub { $meta });
            my $orig_class = $class;
            $class = $meta->name;

            if ($config_val->($orig_class, '_traits_behave_like_roles')) {
                $remove_role_methods_conflicting_with_class->($meta, $orig_class, \@resolved_traits);
            }
        }
    }

    my $constructor = $class->meta->constructor_name;
    confess "$class does not have a constructor defined via the MOP?"
      if !$constructor;

    return $class->$constructor($hashref ? (@others, \%args) : %args);
}

sub apply_traits {
    my ($self, $traits, $rebless_params) = @_;

    my @traits = ref($traits) ? @$traits : ($traits);

    if (@traits) {
        my @resolved_traits = $self->_resolve_traits(@traits);

        $rebless_params ||= {};

        $rebless_params->{_traits} = [ uniq @{ $self->_traits }, @traits ];
        $rebless_params->{_resolved_traits} = [
            uniq @{ $self->_resolved_traits }, @resolved_traits
        ];

        for my $trait (@resolved_traits){
            $trait->meta->apply($self, rebless_params => $rebless_params);
        }

        my $orig_class = $self->_original_class_name;

        if ($config_val->($orig_class, '_traits_behave_like_roles')) {
            $remove_role_methods_conflicting_with_class->($self->meta, $orig_class, \@resolved_traits);
        }
    }
}

no Moose::Role;

1;

__END__

=head1 NAME

MooseX::Traits::Pluggable - trait loading and resolution for Moose

=head1 DESCRIPTION

See L<MooseX::Traits> for usage information.

Use C<new_with_traits> to construct an object with a list of traits and
C<apply_traits> to apply traits to an instance.

Adds support for class precedence search for traits and some extra attributes,
described below.

=head1 TRAIT SEARCH

If the value of L<MooseX::Traits/_trait_namespace> starts with a C<+> the
namespace will be considered relative to the C<class_precedence_list> (ie.
C<@ISA>) of the original class.

Example:

  package Class1
  use Moose;

  package Class1::Trait::Foo;
  use Moose::Role;
  has 'bar' => (
      is       => 'ro',
      isa      => 'Str',
      required => 1,
  );

  package Class2;
  use parent 'Class1';
  with 'MooseX::Traits';
  has '+_trait_namespace' => (default => '+Trait');
  has '+_traits_behave_like_roles' => (default => 1);

  package Class2::Trait::Bar;
  use Moose::Role;
  has 'baz' => (
      is       => 'ro',
      isa      => 'Str',
      required => 1,
  );

  package main;
  my $instance = Class2->new_with_traits(
      traits => ['Foo', 'Bar'],
      bar => 'baz',
      baz => 'quux',
  );

  $instance->does('Class1::Trait::Foo'); # true
  $instance->does('Class2::Trait::Bar'); # true

=head1 NAMESPACE ARRAYS

You can search multiple namespaces for traits, for example:

  has '+_trait_namespace' => (
      default => sub { [qw/+Trait +Role ExtraNS::Trait/] }
  );

Will search in the C<class_precedence_list> for C<::Trait::TheTrait>
and C<::Role::TheTrait> and then for C<ExtraNS::Trait::TheTrait>.

=head1 CORRECT ROLE BEHAVIOR

By default, a method from a role will override a class method, this however is
not the behavior one expects when applying a L<Moose> role using the normal
methods.

If you want the behavior to be consistent with L<Moose> L<roles|Moose::Role>,
then use this configuration attribute in your class:

  has '+_traits_behave_like_roles' => (default => 1);

This may or may not become the default in the future, for now you have to ask
for it for backward compatibility reasons.

=head1 EXTRA ATTRIBUTES

=head2 _original_class_name

When traits are applied to your class or instance, you get an anonymous class
back whose name will be not the same as your original class. So C<ref $self>
will not be C<Class>, but C<< $self->_original_class_name >> will be.

=head2 _traits

List of the (unresolved) traits applied to the instance.

=head2 _resolved_traits

List of traits applied to the instance resolved to full package names.

=head1 SEE ALSO

L<MooseX::Traits>, L<MooseX::Object::Pluggable>, L<CatalystX::Component::Traits>

=head1 BUGS

Please report any bugs or feature requests to C<bug-moosex-traits-pluggable at
rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=MooseX-Traits-Pluggable>.  I
will be notified, and then you'll automatically be notified of progress on your
bug as I make changes.

=head1 AUTHOR

Rafael Kitover C<< <rkitover@cpan.org> >>

=head1 CONTRIBUTORS

Tomas Doran, C<< <bobtfish@bobtfish.net> >>
Fitz Elliott, C<< <fitz.elliott@gmail.com> >>
Andreas Marienborg, C<< <andreas.marienborg@gmail.com> >>
Alexander Hartmaier, C<< <abraxxa@cpan.org> >>

=head1 COPYRIGHT & LICENSE

Copyright (c) 2014 by the aforementioned L</AUTHOR> and L</CONTRIBUTORS>.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.