#!perl
our
$VERSION
=
'1.112_001'
;
my
%implied
= (
SUPER
=> 1,
'Readonly::Scalar'
=>
'Readonly'
,
'Readonly::Array'
=>
'Readonly'
,
'Readonly::Hash'
=>
'Readonly'
,
);
my
@pm
;
find(
{
wanted
=>
sub
{
if
(m< [.] pm \z >xms && ! m<svn>xms) {
push
@pm
,
$_
} },
no_chdir
=> 1,
},
'lib'
,
);
plan
tests
=>
scalar
@pm
;
for
my
$file
(
@pm
) {
SKIP:
{
my
$doc
= PPI::Document->new(
$file
) or confess
qq<Failed to parse "$file">
;
my
@incs
= @{
$doc
->find(
'PPI::Statement::Include'
) || []};
my
%deps
=
map
{
$_
->
module
=> 1}
grep
{
$_
->type eq
'use'
||
$_
->type eq
'require'
}
@incs
;
my
%thispkg
=
map
{
$_
->
namespace
=> 1} @{
$doc
->find(
'PPI::Statement::Package'
) || []};
my
@pkgs
= @{
$doc
->find(
'PPI::Token::Word'
)};
my
%failed
;
for
my
$pkg
(
@pkgs
) {
my
$name
=
"$pkg"
;
next
if
$name
!~ m/::/xms;
next
if
$name
=~ m/::_private::/xms;
next
if
$name
=~ m/List::Util::[[:lower:]]+/xms;
my
$prev_sib
=
$pkg
->sprevious_sibling;
next
if
(
$prev_sib
&&
$prev_sib
eq
'sub'
&&
!
$prev_sib
->sprevious_sibling &&
$pkg
->parent->isa(
'PPI::Statement::Sub'
));
my
$token
=
$pkg
->next_sibling;
if
(
$token
=~ m< \A [(] >xms) {
$name
=~ s/::\w+\z//xms;
}
if
( !match(
$name
, \
%deps
, \
%thispkg
) ) {
$failed
{
$name
} = 1;
}
}
my
@failures
=
sort
keys
%failed
;
ok(
@failures
== 0,
"$file has an include statement for each package that it refers to."
)
or
do
{
diag(
"Found dependencies: @{[sort keys %deps]}."
);
diag(
"Missing import of: @failures."
);
};
}
}
sub
match {
my
$pkg
=
shift
;
my
$deps
=
shift
;
my
$thispkg
=
shift
;
return
1
if
$thispkg
->{
$pkg
};
return
1
if
$deps
->{
$pkg
};
$pkg
=
$implied
{
$pkg
};
return
0
if
!
defined
$pkg
;
return
1
if
'1'
eq
$pkg
;
return
match(
$pkg
,
$deps
,
$thispkg
);
}
1;