App-perlimports

 view release on metacpan or  search on metacpan

lib/App/perlimports/ExportInspector.pm  view on Meta::CPAN


    # Specifically for File::chdir, which exports a typeglob, but doesn't
    # implement every possibility.
    for my $key ( keys %hash ) {
        if ( substr( $key, 0, 1 ) eq '*' ) {
            my $thing = substr( $key, 1 );
            for my $sigil ( '&', '$', '@', '%' ) {
                my $symbol_name = $sigil . $pkg . '::' . $thing;
                if ( Symbol::Get::get($symbol_name) ) {
                    $hash{ $sigil . $thing } = $key;
                }
            }
        }
    }

    # Treat Moose type libraries a bit differently. Importing ArrayRef, for
    # instance, also imports is_ArrayRef and to_ArrayRef (if a coercion)
    # exists. So, let's deal with that here.
    if ( $self->is_moose_type_class ) {
        for my $key ( keys %hash ) {
            if ( $key =~ m{^(is_|to_)} ) {
                $hash{$key} = substr( $key, 3 );
            }
        }
    }

    return \%hash;
}

sub _build_implicit {
    my $self = shift;

    my $module_name   = $self->_module_name;
    my $pkg           = $self->_pkg_for_implicit;
    my $use_statement = "use $module_name;";
    my ( $maybe_exports, $fatal_error )
        = $self->_exports_for_include( $pkg, $use_statement );

    no strict 'refs';
    my $aggregated = {
        class_isa      => [ @{ $self->_module_name . '::ISA' } ],
        export         => [ @{ $self->_module_name . '::EXPORT' } ],
        export_fail    => [ @{ $self->_module_name . '::EXPORT_FAIL' } ],
        export_ok      => [ @{ $self->_module_name . '::EXPORT_OK' } ],
        export_tags    => [ @{ $self->_module_name . '::EXPORT_TAGS' } ],
        fatal_error    => $fatal_error,
        _maybe_exports => $maybe_exports,
    };

    return $aggregated;
}

sub _exports_for_include {
    my $self          = shift;
    my $pkg           = shift;
    my $use_statement = shift;

    my $logger = $self->logger;

    # If you're importing Moose into a namespace and following that with an
    # import of namespace::autoclean, you may find that symbols like "after"
    # and "around" are no longer found.
    #
    # We log available symbols inside the BEGIN block in order to defeat
    # namespace::autoclean, which removes symbols from the stash after
    # compilation but before runtime. Thanks to Florian Ragwitz for the tip and
    # the preceding explanation.

    my $to_eval = <<"EOF";
package $pkg;

use Symbol::Get;
$use_statement
our \@__EXPORTABLES;

BEGIN {
    \@__EXPORTABLES = Symbol::Get::get_names();
}
1;
EOF

    $self->logger->debug($to_eval);

    my $logger_cb = sub {
        my $msg   = shift;
        my $level = 'info';

        # Mojo classes tend to throw "Can't locate :all.pm in @INC". This is
        # expected and shouldn't be raised to the warning level.

        if ( $msg =~ qr{Can't locate} && $msg !~ m{\:all\.pm in \@INC} ) {
            $level = 'warning';
        }

        $logger->log(
            level   => $level,
            message => sprintf(
                "Problem trying to eval %s\n%s",
                $pkg,
                $msg,
            ),
        );
    };

    local $SIG{__WARN__} = $logger_cb;

    local $@ = undef;
    ## no critic (BuiltinFunctions::ProhibitStringyEval)
    ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval)
    eval $to_eval;

    if ($@) {
        $logger_cb->($@);
        return undef, $@;
    }
    else {
        $self->_increment_success_counter;
    }

    ## no critic (TestingAndDebugging::ProhibitNoStrict)
    no strict 'refs';
    my @export
        = grep { $_ !~ m{(?:BEGIN|ISA|__EXPORTABLES)} && $_ !~ m{^__ANON__} }
        @{ $pkg . '::__EXPORTABLES' };
    use strict;



( run in 0.539 second using v1.01-cache-2.11-cpan-5735350b133 )