File Coverage

blib/lib/Call/Context.pm
Criterion Covered Total %
statement 19 19 100.0
branch 4 4 100.0
condition 2 3 66.6
subroutine 6 6 100.0
pod 1 1 100.0
total 32 33 96.9


line stmt bran cond sub pod time code
1             package Call::Context;
2              
3             =encoding utf-8
4              
5             =head1 NAME
6              
7             Call::Context - Sanity-check calling context
8              
9             =head1 SYNOPSIS
10              
11             use Call::Context;
12              
13             sub gives_a_list {
14              
15             #Will die() if the context is not list.
16             Call::Context::must_be_list();
17              
18             return (1, 2, 3);
19             }
20              
21             gives_a_list(); #die()s: incorrect context (void)
22              
23             my $v = gives_a_list(); #die()s: incorrect context (scalar)
24              
25             my @list = gives_a_list(); #lives
26              
27             =head1 DISCUSSION
28              
29             If your function only expects to return a list, then a call in some other
30             context is, by definition, an error. The problem is that, depending on how
31             the function is written, it may actually do something expected in testing, but
32             then in production act differently.
33              
34             =head1 FUNCTIONS
35              
36             =head2 must_be_list()
37              
38             Cs if the calling function is itself called outside list context.
39             (See the SYNOPSIS for examples.)
40              
41             =head1 EXCEPTIONS
42              
43             This module throws instances of C. C is
44             overloaded to stringify; however, to keep memory usage low, C is not
45             loaded until instantiation.
46              
47             =head1 REPOSITORY
48              
49             https://github.com/FGasper/p5-Call-Context
50              
51             =cut
52              
53 2     2   46222 use strict;
  2         5  
  2         69  
54 2     2   10 use warnings;
  2         4  
  2         501  
55              
56             our $VERSION = 0.02;
57              
58             my $_OVERLOADED_X;
59              
60             sub must_be_list {
61 3 100   3 1 700 return if (caller 1)[5]; #wantarray
62              
63 2   66 1   163 $_OVERLOADED_X ||= eval q{
  1         10  
  1         1  
  1         20  
64             package Call::Context::X;
65             use overload ( q<""> => \\&_spew );
66             1;
67             };
68              
69 2         12 die Call::Context::X->_new();
70             }
71              
72             #----------------------------------------------------------------------
73              
74             package Call::Context::X;
75              
76             #Not to be instantiated except from Call::Context!
77              
78             sub _new {
79 2     2   6 my ($class) = @_;
80              
81 2         17 my ($sub, $ctx) = (caller 2)[3, 5];
82 2         13 my (undef, $cfilename, $cline, $csub) = caller 3;
83              
84 2 100       10 $ctx = defined($ctx) ? 'scalar' : 'void';
85              
86 2         29 return bless \"$sub called in non-list ($ctx) context from $csub (line $cline of $cfilename)", $class;
87             }
88              
89 4     4   821 sub _spew { ${ $_[0] } }
  4         70  
90              
91             1;