xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Harness/lib/TAP/Parser/ResultFactory.pm (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1package TAP::Parser::ResultFactory;
2
3use strict;
4use vars qw($VERSION @ISA %CLASS_FOR);
5
6use TAP::Object                  ();
7use TAP::Parser::Result::Bailout ();
8use TAP::Parser::Result::Comment ();
9use TAP::Parser::Result::Plan    ();
10use TAP::Parser::Result::Pragma  ();
11use TAP::Parser::Result::Test    ();
12use TAP::Parser::Result::Unknown ();
13use TAP::Parser::Result::Version ();
14use TAP::Parser::Result::YAML    ();
15
16@ISA = 'TAP::Object';
17
18##############################################################################
19
20=head1 NAME
21
22TAP::Parser::ResultFactory - Factory for creating TAP::Parser output objects
23
24=head1 SYNOPSIS
25
26  use TAP::Parser::ResultFactory;
27  my $token   = {...};
28  my $factory = TAP::Parser::ResultFactory->new;
29  my $result  = $factory->make_result( $token );
30
31=head1 VERSION
32
33Version 3.26
34
35=cut
36
37$VERSION = '3.26';
38
39=head2 DESCRIPTION
40
41This is a simple factory class which returns a L<TAP::Parser::Result> subclass
42representing the current bit of test data from TAP (usually a single line).
43It is used primarily by L<TAP::Parser::Grammar>.  Unless you're subclassing,
44you probably won't need to use this module directly.
45
46=head2 METHODS
47
48=head2 Class Methods
49
50=head3 C<new>
51
52Creates a new factory class.
53I<Note:> You currently don't need to instantiate a factory in order to use it.
54
55=head3 C<make_result>
56
57Returns an instance the appropriate class for the test token passed in.
58
59  my $result = TAP::Parser::ResultFactory->make_result($token);
60
61Can also be called as an instance method.
62
63=cut
64
65sub make_result {
66    my ( $proto, $token ) = @_;
67    my $type = $token->{type};
68    return $proto->class_for($type)->new($token);
69}
70
71=head3 C<class_for>
72
73Takes one argument: C<$type>.  Returns the class for this $type, or C<croak>s
74with an error.
75
76=head3 C<register_type>
77
78Takes two arguments: C<$type>, C<$class>
79
80This lets you override an existing type with your own custom type, or register
81a completely new type, eg:
82
83  # create a custom result type:
84  package MyResult;
85  use strict;
86  use vars qw(@ISA);
87  @ISA = 'TAP::Parser::Result';
88
89  # register with the factory:
90  TAP::Parser::ResultFactory->register_type( 'my_type' => __PACKAGE__ );
91
92  # use it:
93  my $r = TAP::Parser::ResultFactory->( { type => 'my_type' } );
94
95Your custom type should then be picked up automatically by the L<TAP::Parser>.
96
97=cut
98
99BEGIN {
100    %CLASS_FOR = (
101        plan    => 'TAP::Parser::Result::Plan',
102        pragma  => 'TAP::Parser::Result::Pragma',
103        test    => 'TAP::Parser::Result::Test',
104        comment => 'TAP::Parser::Result::Comment',
105        bailout => 'TAP::Parser::Result::Bailout',
106        version => 'TAP::Parser::Result::Version',
107        unknown => 'TAP::Parser::Result::Unknown',
108        yaml    => 'TAP::Parser::Result::YAML',
109    );
110}
111
112sub class_for {
113    my ( $class, $type ) = @_;
114
115    # return target class:
116    return $CLASS_FOR{$type} if exists $CLASS_FOR{$type};
117
118    # or complain:
119    require Carp;
120    Carp::croak("Could not determine class for result type '$type'");
121}
122
123sub register_type {
124    my ( $class, $type, $rclass ) = @_;
125
126    # register it blindly, assume they know what they're doing
127    $CLASS_FOR{$type} = $rclass;
128    return $class;
129}
130
1311;
132
133=head1 SUBCLASSING
134
135Please see L<TAP::Parser/SUBCLASSING> for a subclassing overview.
136
137There are a few things to bear in mind when creating your own
138C<ResultFactory>:
139
140=over 4
141
142=item 1
143
144The factory itself is never instantiated (this I<may> change in the future).
145This means that C<_initialize> is never called.
146
147=item 2
148
149C<TAP::Parser::Result-E<gt>new> is never called, $tokens are reblessed.
150This I<will> change in a future version!
151
152=item 3
153
154L<TAP::Parser::Result> subclasses will register themselves with
155L<TAP::Parser::ResultFactory> directly:
156
157  package MyFooResult;
158  TAP::Parser::ResultFactory->register_type( foo => __PACKAGE__ );
159
160Of course, it's up to you to decide whether or not to ignore them.
161
162=back
163
164=head2 Example
165
166  package MyResultFactory;
167
168  use strict;
169  use vars '@ISA';
170
171  use MyResult;
172  use TAP::Parser::ResultFactory;
173
174  @ISA = qw( TAP::Parser::ResultFactory );
175
176  # force all results to be 'MyResult'
177  sub class_for {
178    return 'MyResult';
179  }
180
181  1;
182
183=head1 SEE ALSO
184
185L<TAP::Parser>,
186L<TAP::Parser::Result>,
187L<TAP::Parser::Grammar>
188
189=cut
190