File Coverage

blib/lib/App/perlminlint/Object.pm
Criterion Covered Total %
statement 61 89 68.5
branch 12 30 40.0
condition 8 20 40.0
subroutine 13 18 72.2
pod 0 6 0.0
total 94 163 57.6


line stmt bran cond sub pod time code
1             package App::perlminlint::Object; sub MY () {__PACKAGE__}
2 1     1   4 use strict;
  1         1  
  1         30  
3 1     1   3 use warnings FATAL => qw/all/;
  1         1  
  1         26  
4 1     1   4 use Carp;
  1         1  
  1         53  
5              
6             require fields;
7 1     1   3 use parent qw/File::Spec/;
  1         2  
  1         4  
8              
9             our %FIELDS;
10              
11             sub new {
12 0     0 0 0 my MY $self = fields::new(shift);
13 0         0 $self->configure(@_);
14 0         0 $self->after_new;
15 0         0 $self;
16             }
17              
18       0 0   sub after_new {}
19              
20             sub configure {
21 0     0 0 0 (my MY $self) = shift;
22              
23 0 0 0     0 my @args = @_ == 1 && ref $_[0] eq 'HASH' ? %{$_[0]} : @_;
  0         0  
24              
25 0         0 my $fields = _fields_hash($self);
26              
27 0         0 my @task;
28 0         0 while (my ($key, $value) = splice @args, 0, 2) {
29 0 0       0 unless (defined $key) {
30 0         0 croak "Undefined option name for class ".ref($self);
31             }
32 0 0       0 next unless $key =~ m{^[A-Za-z]\w+\z};
33 0 0       0 unless (exists $fields->{$key}) {
34 0         0 croak "Unknown option for class ".ref($self).": ".$key;
35             }
36              
37 0 0       0 if (my $sub = $self->can("onconfigure_$key")) {
38 0         0 push @task, [$sub, $value];
39             } else {
40 0         0 $self->{$key} = $value;
41             }
42             }
43              
44 0         0 $_->[0]->($self, $_->[-1]) for @task;
45              
46 0         0 $self;
47             }
48              
49             sub import {
50 2     2   23 $_[0]->dispatch_import(scalar caller, \@_);
51 2         10 require Exporter;
52 2         88 goto &Exporter::import;
53             }
54              
55             sub dispatch_import {
56 2     2 0 4 my ($myPack, $callpack, $args) = @_;
57              
58             #
59             # To allow falling back to Exporter::import,
60             # We need to keep original $_[0] in $args.
61             # That's why we scan $args->[1]
62             #
63 2   66     14 while (@$args >= 2
      66        
64             and (ref $args->[1] or $args->[1] =~ /^-/)) {
65 2         10 my $argSpec = splice @$args, 1, 1;
66 2         2 my ($pragma, @args) = do {
67 2 100       5 if (ref $argSpec) {
68 1         7 @$argSpec
69             } else {
70 1 50       4 ($argSpec =~ s/^-//
71             ? ($argSpec => 1)
72             : $argSpec);
73             }
74             };
75              
76 2 50       16 if (my $sub = $myPack->can("declare_$pragma")) {
77 2         4 $sub->($myPack, $callpack, @args);
78             } else {
79 0         0 croak "Unknown pragma '$pragma' in $callpack";
80             }
81             }
82             }
83              
84             sub declare_as_base {
85 1     1 0 1 my ($myPack, $callpack, @fields) = @_;
86              
87             # Special case. -as_base is treated as [as_base => 1];
88 1 50 50     7 if (@fields == 1 and ($fields[0] // '') eq 1) {
      33        
89 1         1 pop @fields;
90             }
91              
92 1         2 $myPack->declare_fields($callpack, @fields);
93              
94 1         2 $myPack->_declare_constant_in($callpack, MY => $callpack, 1);
95             }
96              
97             sub _declare_constant_in {
98 1     1   1 my ($myPack, $callpack, $name, $value, $or_ignore) = @_;
99              
100 1         1 my $my_sym = _globref($callpack, $name);
101 1 50       1 if (*{$my_sym}{CODE}) {
  1         4  
102 1 50       10 return if $or_ignore;
103 0         0 croak "constant ${callpack}::$name is already defined";
104             }
105              
106 0     0   0 *$my_sym = sub () {$value};
  0         0  
107             }
108              
109             sub declare_fields {
110 2     2 0 6 (my MY $self, my ($pack, @fields)) = @_;
111              
112 2   33     2 push @{*{_globref($pack, 'ISA')}}, ref($self) || $self;
  2         2  
  2         3  
113              
114 2         7 my $super = _fields_hash($self);
115 2         2 my $extended = _fields_hash($pack);
116              
117 2         3 foreach my $name (keys %$super) {
118 0         0 $extended->{$name} = $super->{$name}; # XXX: clone?
119             }
120              
121 2         2 foreach my $spec (@fields) {
122 9 50       13 my ($name, @rest) = ref $spec ? @$spec : $spec;
123 9         7 my $has_getter = $name =~ s/^\^//;
124 9         16 $extended->{$name} = \@rest; # XXX: should have better object.
125 9 50       13 if ($has_getter) {
126 0     0   0 *{_globref($pack, $name)} = sub { $_[0]->{$name} };
  0         0  
  0         0  
127             }
128             }
129              
130 2         6 $pack;
131             }
132              
133             sub _fields_hash {
134 4     4   5 my $sym = _fields_symbol(@_);
135 4 100       4 unless (*{$sym}{HASH}) {
  4         8  
136 1         1 *$sym = {};
137             }
138 4         3 *{$sym}{HASH};
  4         4  
139             }
140              
141             sub _fields_symbol {
142 4     4   4 _globref($_[0], 'FIELDS');
143             }
144              
145             sub _globref {
146 7     7   8 my ($thing, $name) = @_;
147 7   33     18 my $class = ref $thing || $thing;
148 1     1   794 no strict 'refs';
  1         1  
  1         355  
149 7 50       4 \*{join("::", $class, defined $name ? $name : ())};
  7         46  
150             }
151              
152             1;
153              
154             __END__