File Coverage

File:blib/lib/App/Test/Generator/Analyzer/Return.pm
Coverage:82.2%

linestmtbrancondsubtimecode
1package App::Test::Generator::Analyzer::Return;
2
3
24
24
24
66822
17
302
use strict;
4
24
24
24
33
42
476
use warnings;
5
24
24
24
42
27
429
use Carp    qw(croak);
6
24
24
24
34
22
4719
use Readonly;
7
8# --------------------------------------------------
9# Evidence weights for each detected return pattern.
10# Higher weights indicate stronger signals that the
11# detected pattern is the primary return behaviour.
12# --------------------------------------------------
13Readonly my $WEIGHT_RETURNS_PROPERTY => 20;
14Readonly my $WEIGHT_RETURNS_SELF     => 15;
15Readonly my $WEIGHT_RETURNS_CONSTANT => 10;
16
17our $VERSION = '0.36';
18
19 - 58
=head1 VERSION

Version 0.36

=head1 DESCRIPTION

Analyses the source code of a method and adds evidence to a
L<App::Test::Generator::Model::Method> object describing what kind of
value the method returns. Evidence is used downstream by
L<App::Test::Generator::Model::Method/resolve_return_type> to determine
the most likely return type.

=head2 new

Construct a new Return analyser.

    my $analyser = App::Test::Generator::Analyzer::Return->new;

=head3 Arguments

None.

=head3 Returns

A blessed hashref.

=head3 API specification

=head4 input

    {}

=head4 output

    {
        type => OBJECT,
        isa  => 'App::Test::Generator::Analyzer::Return',
    }

=cut
59
60sub new {
61
290
101855
        my $class = $_[0];
62
290
334
        return bless {}, $class;
63}
64
65 - 113
=head2 analyze

Scan the source code of a method for return patterns and add weighted
evidence to the method object. Detects three patterns: returning a
property from C<$self>, returning C<$self> itself, and returning a
constant literal value.

    my $analyser = App::Test::Generator::Analyzer::Return->new;
    $analyser->analyze($method);

    my $type = $method->resolve_return_type;

=head3 Arguments

=over 4

=item * C<$method>

An L<App::Test::Generator::Model::Method> object. Evidence is added
to this object in place via C<add_evidence>.

=back

=head3 Returns

Nothing (undef). All results are communicated via side effects on the
C<$method> object.

=head3 Notes

The interface of this analyser differs from
L<App::Test::Generator::Analyzer::ReturnMeta>, which operates on a raw
schema hashref. This analyser operates on a C<Model::Method> object
directly.

=head3 API specification

=head4 input

    {
        self   => { type => OBJECT, isa => 'App::Test::Generator::Analyzer::Return' },
        method => { type => OBJECT, isa => 'App::Test::Generator::Model::Method' },
    }

=head4 output

    { type => UNDEF }

=cut
114
115sub analyze {
116
288
289
        my ($self, $method) = @_;
117
118        # Accept either a Model::Method object or a raw hashref,
119        # since callers in SchemaExtractor pass raw hashrefs
120        my $source = ref($method) && $method->can('source')
121                ? $method->source()
122
288
914
                : ($method->{source} // $method->{body} // '');
123
124        # --------------------------------------------------
125        # Detect: return $self->{property}
126        # Negative lookahead ensures this does not also match
127        # plain return $self (handled separately below)
128        # --------------------------------------------------
129
288
531
        if($source =~ /return\s+\$self->\{(\w+)\}/) {
130
30
62
                $method->add_evidence(
131                        category => 'return',
132                        signal   => 'returns_property',
133                        value    => $1,
134                        weight   => $WEIGHT_RETURNS_PROPERTY,
135                );
136        }
137
138        # --------------------------------------------------
139        # Detect: return $self
140        # Use negative lookahead to avoid matching
141        # return $self->{...} which is a property return
142        # --------------------------------------------------
143
288
490
        if($source =~ /return\s+\$self(?!->)/) {
144
11
25
                $method->add_evidence(
145                        category => 'return',
146                        signal   => 'returns_self',
147                        weight   => $WEIGHT_RETURNS_SELF,
148                );
149        }
150
151        # --------------------------------------------------
152        # Detect: return of a constant literal — quoted string,
153        # numeric literal, or undef. All indicate the method
154        # returns a fixed value rather than a computed state.
155        # --------------------------------------------------
156
288
546
        if($source =~ /return\s+(?:['"\d]|undef\b)/) {
157
155
258
                $method->add_evidence(
158                        category => 'return',
159                        signal   => 'returns_constant',
160                        weight   => $WEIGHT_RETURNS_CONSTANT,
161                );
162        }
163
164
288
305
        return;
165}
166
167 - 175
=head1 LICENCE AND COPYRIGHT

Copyright 2025-2026 Nigel Horne.

Usage is subject to GPL2 licence terms.
If you use it,
please let me know.

=cut
176
1771;