File Coverage

blib/lib/Attribute/Final.pm
Criterion Covered Total %
statement 51 51 100.0
branch 10 10 100.0
condition 3 3 100.0
subroutine 12 12 100.0
pod 0 3 0.0
total 76 79 96.2


line stmt bran cond sub pod time code
1             package Attribute::Final;
2 1     1   37057 use 5.006;
  1         4  
  1         42  
3 1     1   4 use strict;
  1         3  
  1         69  
4 1     1   5 use warnings;
  1         6  
  1         88  
5             our $VERSION = '1.3';
6             our %marked;
7             my @all_packages;
8 1     1   6 use B qw(svref_2object);
  1         2  
  1         114  
9              
10             sub fill_packages {
11 1     1   5 no strict 'refs';
  1         2  
  1         152  
12 179     179 0 259 my $root = shift;
13 179         189 my @subs = grep s/::$//, keys %{$root."::"};
  179         3303  
14 179         462 push @all_packages, $root;
15 179         458 for (@subs) {
16 179 100 100     487 next if $root eq "main" and $_ eq "main"; # Loop
17 178         531 fill_packages($root."::".$_);
18             }
19             }
20              
21             sub check {
22 1     1   4 no strict 'refs';
  1         1  
  1         252  
23 2 100   2 0 1257 fill_packages("main") unless @all_packages;
24 2         8 for my $derived_pack (@all_packages) {
25 210 100       222 next unless @{$derived_pack."::ISA"};
  210         2533  
26 74         137 for my $marked_pack (keys %marked) {
27 74 100       1079 next unless $derived_pack->isa($marked_pack);
28 2         4 for my $meth (@{$marked{$marked_pack}}) {
  2         7  
29 2         3 my $glob_ref = \*{$derived_pack."::".$meth};
  2         10  
30 2 100       3 if (*{$glob_ref}{CODE}) {
  2         12  
31 1         5 my $name = $marked_pack."::".$meth;
32 1         10 my $b = svref_2object($glob_ref);
33 1         17 die "Cannot override final method $name at ".
34             $b->FILE. ", line ".$b->LINE."\n";
35             }
36             }
37             }
38             }
39             }
40              
41 1     1   11 CHECK { Attribute::Final->check() }
42              
43             package UNIVERSAL;
44 1     1   1853 use Attribute::Handlers;
  1         6843  
  1         7  
45             sub final :ATTR(CODE) {
46 1     1 0 6752 my ($pack, $ref) = @_;
47 1         2 push @{$marked{$pack}}, *{$ref}{NAME};
  1         3  
  1         4  
48 1     1   90 }
  1         2  
  1         4  
49              
50             # Preloaded methods go here.
51              
52             1;
53             __END__