xref: /openbsd-src/gnu/usr.bin/perl/cpan/Test-Harness/lib/TAP/Parser/SourceHandler.pm (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
1898184e3Ssthenpackage TAP::Parser::SourceHandler;
2898184e3Ssthen
3898184e3Ssthenuse strict;
46fb12b70Safresh1use warnings;
5898184e3Ssthen
6898184e3Ssthenuse TAP::Parser::Iterator ();
76fb12b70Safresh1use base 'TAP::Object';
8898184e3Ssthen
9898184e3Ssthen=head1 NAME
10898184e3Ssthen
11898184e3SsthenTAP::Parser::SourceHandler - Base class for different TAP source handlers
12898184e3Ssthen
13898184e3Ssthen=head1 VERSION
14898184e3Ssthen
15*3d61058aSafresh1Version 3.48
16898184e3Ssthen
17898184e3Ssthen=cut
18898184e3Ssthen
19*3d61058aSafresh1our $VERSION = '3.48';
20898184e3Ssthen
21898184e3Ssthen=head1 SYNOPSIS
22898184e3Ssthen
23898184e3Ssthen  # abstract class - don't use directly!
24898184e3Ssthen  # see TAP::Parser::IteratorFactory for general usage
25898184e3Ssthen
26898184e3Ssthen  # must be sub-classed for use
27898184e3Ssthen  package MySourceHandler;
286fb12b70Safresh1  use base 'TAP::Parser::SourceHandler';
29898184e3Ssthen  sub can_handle    { return $confidence_level }
30898184e3Ssthen  sub make_iterator { return $iterator }
31898184e3Ssthen
32898184e3Ssthen  # see example below for more details
33898184e3Ssthen
34898184e3Ssthen=head1 DESCRIPTION
35898184e3Ssthen
36898184e3SsthenThis is an abstract base class for L<TAP::Parser::Source> handlers / handlers.
37898184e3Ssthen
38898184e3SsthenA C<TAP::Parser::SourceHandler> does whatever is necessary to produce & capture
39898184e3Ssthena stream of TAP from the I<raw> source, and package it up in a
40898184e3SsthenL<TAP::Parser::Iterator> for the parser to consume.
41898184e3Ssthen
42898184e3SsthenC<SourceHandlers> must implement the I<source detection & handling> interface
43898184e3Ssthenused by L<TAP::Parser::IteratorFactory>.  At 2 methods, the interface is pretty
44898184e3Ssthensimple: L</can_handle> and L</make_source>.
45898184e3Ssthen
46898184e3SsthenUnless you're writing a new L<TAP::Parser::SourceHandler>, a plugin, or
47898184e3Ssthensubclassing L<TAP::Parser>, you probably won't need to use this module directly.
48898184e3Ssthen
49898184e3Ssthen=head1 METHODS
50898184e3Ssthen
51898184e3Ssthen=head2 Class Methods
52898184e3Ssthen
53898184e3Ssthen=head3 C<can_handle>
54898184e3Ssthen
55898184e3SsthenI<Abstract method>.
56898184e3Ssthen
57898184e3Ssthen  my $vote = $class->can_handle( $source );
58898184e3Ssthen
59898184e3SsthenC<$source> is a L<TAP::Parser::Source>.
60898184e3Ssthen
61898184e3SsthenReturns a number between C<0> & C<1> reflecting how confidently the raw source
62898184e3Ssthencan be handled.  For example, C<0> means the source cannot handle it, C<0.5>
63898184e3Ssthenmeans it may be able to, and C<1> means it definitely can.  See
64898184e3SsthenL<TAP::Parser::IteratorFactory/detect_source> for details on how this is used.
65898184e3Ssthen
66898184e3Ssthen=cut
67898184e3Ssthen
68898184e3Ssthensub can_handle {
69898184e3Ssthen    my ( $class, $args ) = @_;
70898184e3Ssthen    $class->_croak(
71898184e3Ssthen        "Abstract method 'can_handle' not implemented for $class!");
72898184e3Ssthen    return;
73898184e3Ssthen}
74898184e3Ssthen
75898184e3Ssthen=head3 C<make_iterator>
76898184e3Ssthen
77898184e3SsthenI<Abstract method>.
78898184e3Ssthen
79898184e3Ssthen  my $iterator = $class->make_iterator( $source );
80898184e3Ssthen
81898184e3SsthenC<$source> is a L<TAP::Parser::Source>.
82898184e3Ssthen
83898184e3SsthenReturns a new L<TAP::Parser::Iterator> object for use by the L<TAP::Parser>.
84898184e3SsthenC<croak>s on error.
85898184e3Ssthen
86898184e3Ssthen=cut
87898184e3Ssthen
88898184e3Ssthensub make_iterator {
89898184e3Ssthen    my ( $class, $args ) = @_;
90898184e3Ssthen    $class->_croak(
91898184e3Ssthen        "Abstract method 'make_iterator' not implemented for $class!");
92898184e3Ssthen    return;
93898184e3Ssthen}
94898184e3Ssthen1;
95898184e3Ssthen
96898184e3Ssthen__END__
97898184e3Ssthen
98898184e3Ssthen=head1 SUBCLASSING
99898184e3Ssthen
100898184e3SsthenPlease see L<TAP::Parser/SUBCLASSING> for a subclassing overview, and any
101898184e3Ssthenof the subclasses that ship with this module as an example.  What follows is
102898184e3Ssthena quick overview.
103898184e3Ssthen
104898184e3SsthenStart by familiarizing yourself with L<TAP::Parser::Source> and
105898184e3SsthenL<TAP::Parser::IteratorFactory>.  L<TAP::Parser::SourceHandler::RawTAP> is
1066fb12b70Safresh1the easiest sub-class to use as an example.
107898184e3Ssthen
108898184e3SsthenIt's important to point out that if you want your subclass to be automatically
109898184e3Ssthenused by L<TAP::Parser> you'll have to and make sure it gets loaded somehow.
110898184e3SsthenIf you're using L<prove> you can write an L<App::Prove> plugin.  If you're
111898184e3Ssthenusing L<TAP::Parser> or L<TAP::Harness> directly (e.g. through a custom script,
112898184e3SsthenL<ExtUtils::MakeMaker>, or L<Module::Build>) you can use the C<config> option
113898184e3Ssthenwhich will cause L<TAP::Parser::IteratorFactory/load_sources> to load your
114898184e3Ssthensubclass).
115898184e3Ssthen
116898184e3SsthenDon't forget to register your class with
117898184e3SsthenL<TAP::Parser::IteratorFactory/register_handler>.
118898184e3Ssthen
119898184e3Ssthen=head2 Example
120898184e3Ssthen
121898184e3Ssthen  package MySourceHandler;
122898184e3Ssthen
123898184e3Ssthen  use strict;
124898184e3Ssthen
125898184e3Ssthen  use MySourceHandler; # see TAP::Parser::SourceHandler
126898184e3Ssthen  use TAP::Parser::IteratorFactory;
127898184e3Ssthen
1286fb12b70Safresh1  use base 'TAP::Parser::SourceHandler';
129898184e3Ssthen
130898184e3Ssthen  TAP::Parser::IteratorFactory->register_handler( __PACKAGE__ );
131898184e3Ssthen
132898184e3Ssthen  sub can_handle {
133898184e3Ssthen      my ( $class, $src ) = @_;
134898184e3Ssthen      my $meta   = $src->meta;
135898184e3Ssthen      my $config = $src->config_for( $class );
136898184e3Ssthen
137898184e3Ssthen      if ($config->{accept_all}) {
138898184e3Ssthen          return 1.0;
139898184e3Ssthen      } elsif (my $file = $meta->{file}) {
140898184e3Ssthen          return 0.0 unless $file->{exists};
141898184e3Ssthen          return 1.0 if $file->{lc_ext} eq '.tap';
142898184e3Ssthen          return 0.9 if $file->{shebang} && $file->{shebang} =~ /^#!.+tap/;
143898184e3Ssthen          return 0.5 if $file->{text};
144898184e3Ssthen          return 0.1 if $file->{binary};
145898184e3Ssthen      } elsif ($meta->{scalar}) {
146898184e3Ssthen          return 0.8 if $$raw_source_ref =~ /\d\.\.\d/;
147898184e3Ssthen          return 0.6 if $meta->{has_newlines};
148898184e3Ssthen      } elsif ($meta->{array}) {
149898184e3Ssthen          return 0.8 if $meta->{size} < 5;
150898184e3Ssthen          return 0.6 if $raw_source_ref->[0] =~ /foo/;
151898184e3Ssthen          return 0.5;
152898184e3Ssthen      } elsif ($meta->{hash}) {
153898184e3Ssthen          return 0.6 if $raw_source_ref->{foo};
154898184e3Ssthen          return 0.2;
155898184e3Ssthen      }
156898184e3Ssthen
157898184e3Ssthen      return 0;
158898184e3Ssthen  }
159898184e3Ssthen
160898184e3Ssthen  sub make_iterator {
161898184e3Ssthen      my ($class, $source) = @_;
162898184e3Ssthen      # this is where you manipulate the source and
163898184e3Ssthen      # capture the stream of TAP in an iterator
164898184e3Ssthen      # either pick a TAP::Parser::Iterator::* or write your own...
165898184e3Ssthen      my $iterator = TAP::Parser::Iterator::Array->new([ 'foo', 'bar' ]);
166898184e3Ssthen      return $iterator;
167898184e3Ssthen  }
168898184e3Ssthen
169898184e3Ssthen  1;
170898184e3Ssthen
171898184e3Ssthen=head1 AUTHORS
172898184e3Ssthen
173898184e3SsthenTAPx Developers.
174898184e3Ssthen
175898184e3SsthenSource detection stuff added by Steve Purkis
176898184e3Ssthen
177898184e3Ssthen=head1 SEE ALSO
178898184e3Ssthen
179898184e3SsthenL<TAP::Object>,
180898184e3SsthenL<TAP::Parser>,
181898184e3SsthenL<TAP::Parser::Source>,
182898184e3SsthenL<TAP::Parser::Iterator>,
183898184e3SsthenL<TAP::Parser::IteratorFactory>,
184898184e3SsthenL<TAP::Parser::SourceHandler::Executable>,
185898184e3SsthenL<TAP::Parser::SourceHandler::Perl>,
186898184e3SsthenL<TAP::Parser::SourceHandler::File>,
187898184e3SsthenL<TAP::Parser::SourceHandler::Handle>,
188898184e3SsthenL<TAP::Parser::SourceHandler::RawTAP>
189898184e3Ssthen
190898184e3Ssthen=cut
191898184e3Ssthen
192