App-Test-Generator
view release on metacpan or search on metacpan
lib/App/Test/Generator/SchemaExtractor.pm view on Meta::CPAN
#
# Notes: Only fires when output type is
# not yet set or is 'unknown'. Does not
# override explicitly set types.
# --------------------------------------------------
sub _enhance_boolean_detection {
my ($self, $output, $pod, $code, $method_name) = @_;
my $boolean_score = 0; # Track evidence for boolean return
return unless !$output->{type} || $output->{type} eq 'unknown';
# Look for stronger boolean indicators
if ($pod && !$output->{type}) {
# Common boolean return patterns in POD
if ($pod =~ /returns?\s+(true|false|true|false|1|0)\s+(?:on|for|upon)\s+(success|failure|error|valid|invalid)/i) {
$boolean_score += 30;
$self->_log(' OUTPUT: Strong boolean indicator in POD (+30)');
}
# Check for method names that suggest boolean returns
if ($pod =~ /(?:method|sub)\s+(\w+)/) {
my $inferred_method_name = $1;
if ($inferred_method_name =~ /^(is_|has_|can_|should_|contains_|exists_)/) {
$boolean_score += 20;
$self->_log(" OUTPUT: Inferred method name '$inferred_method_name' suggests boolean return (+20)");
}
}
}
# Analyze code for boolean patterns
if ($code) {
# Count boolean return idioms
my $true_returns = () = $code =~ /return\s+1\s*;/g;
my $false_returns = () = $code =~ /return\s+0\s*;/g;
if ($true_returns + $false_returns >= 2) {
$boolean_score += 40;
$self->_log(' OUTPUT: Multiple 1/0 returns suggest boolean (+40)');
} elsif ($true_returns + $false_returns == 1) {
$boolean_score += 10;
$self->_log(' OUTPUT: Single 1/0 return (+10)');
}
# Ternary operators that return booleans
if ($code =~ /return\s+(?:\w+\s*[!=]=\s*\w+|\w+\s*>\s*\w+|\w+\s*<\s*\w+)\s*\?\s*(?:1|0)\s*:\s*(?:1|0)/) {
$boolean_score += 25;
$self->_log(' OUTPUT: Ternary with 1/0 suggests boolean (+25)');
}
# Check for common boolean method patterns
if ($code =~ /return\s+[!\$\@\%]/) {
# Returns negation or existence check
$boolean_score += 15;
$self->_log(' OUTPUT: Returns negation/existence check (+15)');
}
}
# Check method name for boolean indicators
if ($method_name) {
if ($method_name =~ /^(is_|has_|can_|should_|contains_|exists_|check_|verify_|validate_)/) {
$boolean_score += 25;
$self->_log(" OUTPUT: Method name '$method_name' suggests boolean return (+25)");
}
if ($method_name =~ /_ok$/) {
$boolean_score += 30;
$self->_log(" OUTPUT: Method name '$method_name' ends with '_ok' (+30)");
}
}
# Apply boolean type if we have strong evidence
# Override weak type assignments (like 'array' from false positive)
if($boolean_score >= $BOOLEAN_SCORE_THRESHOLD) {
if (!$output->{type} || $output->{type} eq 'scalar' || $output->{type} eq 'array' || $output->{type} eq 'undef') {
my $old_type = $output->{type} || 'none';
$output->{type} = 'boolean';
$self->_log(" OUTPUT: Boolean score $boolean_score >= $BOOLEAN_SCORE_THRESHOLD, setting type to boolean (was: $old_type)");
}
}
}
# --------------------------------------------------
# _detect_list_context
#
# Purpose: Detect methods that return different
# values depending on calling context
# via wantarray, and methods that
# return explicit lists.
#
# Entry: $output - output hashref (modified
# in place).
# $code - method body source string.
#
# Exit: Returns nothing. Modifies $output
# in place, setting _context_aware,
# _list_context, _scalar_context,
# _list_return, and/or type keys.
#
# Side effects: Logs detections to stdout when
# verbose is set.
# --------------------------------------------------
sub _detect_list_context {
my ($self, $output, $code) = @_;
return unless $code;
# Check for wantarray usage
if ($code =~ /wantarray/) {
$output->{_context_aware} = 1;
$self->_log(' OUTPUT: Method uses wantarray - context sensitive');
# Debug: show what we're matching against
if ($code =~ /(wantarray[^;]+;)/s) {
$self->_log(" DEBUG wantarray line: $1");
}
if ($code =~ /wantarray\s*\?\s*\(([^)]+)\)\s*:\s*([^;]+)/s) {
# Pattern 1: wantarray ? (list, items) : scalar_value (with parens)
my ($list_return, $scalar_return) = ($1, $2);
$self->_log(" DEBUG list (with parens): [$list_return], scalar: [$scalar_return]");
$output->{_list_context} = $self->_infer_type_from_expression($list_return);
( run in 0.573 second using v1.01-cache-2.11-cpan-e1769b4cff6 )