package Dist::Zilla::Role::Rinci::CheckDefinesMeta;

our $DATE = '2015-09-22'; # DATE
our $VERSION = '0.02'; # VERSION

use 5.010001;
use Moose::Role;

sub check_dist_defines_rinci_meta {
    no strict 'refs';

    my $self = shift;

    # cache result
    state $res;
    return $res if defined $res;

    $res = 0;

    {
        my $files = $self->zilla->find_files(':InstallModules');
        local @INC = ("lib", @INC);
        for my $file (@$files) {
            my $name = $file->name;
            $name =~ s!\Alib/!!;
            require $name;
            my $pkg = $name; $pkg =~ s/\.pm\z//; $pkg =~ s!/!::!g;
            if (keys %{"$pkg\::SPEC"}) {
                $self->log_debug(["Found that %%%s\::SPEC contains stuffs",
                                  $pkg]);
                $res = 1;
                goto DONE;
            }
        }
    }

    {
        require File::Temp;
        require PPI::Document;
        my $files = $self->zilla->find_files(':ExecFiles');
        for my $file (@$files) {
            my $path;
            if ($file->isa("Dist::Zilla::File::OnDisk")) {
                $path = $file->name;
            } else {
                my ($temp_fh, $temp_path) = tempfile();
                print $temp_fh $file->content;
                $path = $temp_path;
            }
            my $doc = PPI::Document->new($path);
            for my $node ($doc->children) {
                next unless $node->isa("PPI::Statement");
                my @chld = $node->children;
                next unless @chld;
                next unless $chld[0]->isa("PPI::Token::Symbol") &&
                    $chld[0]->content =~ /\A\$(main::)?SPEC\z/;
                my $i = 1;
                while ($i < @chld) {
                    last unless $chld[$i]->isa("PPI::Token::Whitespace");
                    $i++;
                }
                next unless $i < @chld;
                next unless $chld[$i]->isa("PPI::Structure::Subscript") &&
                    $chld[$i]->content =~ /\A\{/;
                $i++;
                while ($i < @chld) {
                    last unless $chld[$i]->isa("PPI::Token::Whitespace");
                    $i++;
                }
                next unless $i < @chld;
                next unless $chld[$i]->isa("PPI::Token::Operator") &&
                    $chld[$i]->content eq '=';
                $self->log_debug(
                    ['Found that %s contains assignment to $SPEC{...}',
                     $file->name]);
                $res = 1;
                goto DONE;
            }
        }
    }

  DONE:
    $res;
}

no Moose::Role;
1;
# ABSTRACT: Role to check if dist defines Rinci metadata

__END__

=pod

=encoding UTF-8

=head1 NAME

Dist::Zilla::Role::Rinci::CheckDefinesMeta - Role to check if dist defines Rinci metadata

=head1 VERSION

This document describes version 0.02 of Dist::Zilla::Role::Rinci::CheckDefinesMeta (from Perl distribution Dist-Zilla-Role-Rinci-CheckDefinesMeta), released on 2015-09-22.

=head1 METHODS

=head2 $obj->check_dist_defines_rinci_meta => bool

Will return true if dist defines Rinci metadata. Currently this is done via the
following: 1) load all the module files and check whether C<%SPEC> in the
corresponding package contains stuffs; 2) analyze all the scripts using L<PPI>
and try to find any assignment like C<< $SPEC{something} = { ... } >> (this
might miss some stuffs).

=head1 SEE ALSO

L<Rinci>

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/Dist-Zilla-Role-Rinci-CheckDefinesMeta>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-Dist-Zilla-Role-Rinci-CheckDefinesMeta>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Role-Rinci-CheckDefinesMeta>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
