-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- added php util module which for now can scan file contents to determine the php class type (e.g. interface, enum, class) for a list of files. this enables one to in / exclude certain class types when for instance reducing a git diff
- Loading branch information
Showing
11 changed files
with
348 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package GPH::Util::Php; | ||
|
||
use strict; | ||
use warnings FATAL => 'all'; | ||
|
||
use Cwd; | ||
use Data::Dumper; | ||
|
||
sub new { | ||
my ($proto) = @_; | ||
|
||
return bless { | ||
'types' => {}, | ||
}, $proto; | ||
}; | ||
|
||
sub types { | ||
my ($self, @files) = @_; | ||
my ($fh, $pattern); | ||
|
||
foreach my $file (@files) { | ||
chomp $file; | ||
next unless $file =~ '[/]{0,}([^/]+)\.php$'; | ||
open($fh, '<', getcwd() . '/' . $file) or die "unable to open file $file : $!"; | ||
|
||
$pattern = "[ ]{0,}([^ ]+) " . $1 . "(?:[ :]|\$){1,}"; | ||
|
||
while(<$fh>) { | ||
chomp $_; | ||
next unless $_ =~ $pattern; | ||
my $type = ($1 ne 'enum') ? $1 : $self->resolveEnum(<$fh>); | ||
|
||
$self->{'types'}->{$type} = [] unless exists($self->{'types'}->{$type}); | ||
|
||
push(@{$self->{'types'}->{$type}}, $file); | ||
|
||
last(); | ||
} | ||
|
||
close($fh); | ||
} | ||
|
||
return($self); | ||
}; | ||
|
||
sub resolveEnum { | ||
my ($self, @lines) = @_; | ||
|
||
foreach my $line (@lines) { | ||
return 'method_enum' if $line =~ / function [^ ]{1,}[ ]{0,}\(/; | ||
} | ||
|
||
return 'enum'; | ||
}; | ||
|
||
sub reduce { | ||
my ($self, %args) = @_; | ||
|
||
(exists($args{paths}) and exists($args{excludes})) or die $!; | ||
|
||
$self->types(@{$args{paths}}); | ||
|
||
my %exclude = map{$_ => 1} @{$args{excludes}}; | ||
my @result; | ||
|
||
foreach my $key (keys %{$self->{types}}) { | ||
push(@result, @{$self->{types}->{$key}}) unless defined $exclude{$key}; | ||
} | ||
|
||
return(@result); | ||
}; | ||
|
||
1; | ||
|
||
__END__ | ||
=head1 NAME | ||
GPH::Util::Php - php related util methods | ||
=head1 SYNOPSIS | ||
use GPH::Util::Php; | ||
my $stats = GPH::Util::Php->new(); | ||
$stats->types(<STDIN>); | ||
=head1 METHODS | ||
=over 4 | ||
=item C<< -E<gt>new(%args) >> | ||
the C<new> method returns a php object. | ||
=item C<< -E<gt>types(@paths) >> | ||
scans file content of given php files in C<@paths> and tries to determine their type (e.g. class, interface, trait, enum) | ||
=item C<< -E<gt>resolveEnum(@lines) >> | ||
scans C<< @lines >> for the presence of a method and returns the 'method_enum' type if found, otherwise 'enum' is returned. | ||
this for instance can be particularly useful when creating a filter for infection testing as no mutants can be generated | ||
for a (backed) enum, but they can when the enum contains methods. | ||
=item C<< -E<gt>reduce(%args) >> | ||
the reduce method takes a hash of options, valid option keys include: | ||
=over | ||
=item paths B<(required)> | ||
file paths to scan. must be relative to the path where the script is executed | ||
=item excludes B<(required)> | ||
class type(s) to exclude from the list | ||
=back | ||
calls the C<< -E<gt>types(@paths) >> method with given paths after which it returns an array of paths for files with | ||
different types than the excluded types. | ||
=back | ||
=head1 AUTHOR | ||
the GPH::Util::Php module was written by wicliff wolda <wicliff.wolda@gmail.com> | ||
=head1 COPYRIGHT AND LICENSE | ||
this library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. | ||
=cut |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/usr/bin/perl -w | ||
use strict; | ||
use warnings FATAL => 'all'; | ||
|
||
use File::Basename; | ||
use lib dirname(__FILE__) . '/lib/'; | ||
|
||
use GPH::Util::Php; | ||
use GPH::Gitlab; | ||
|
||
my $owner = $ENV{'DEV_TEAM'} or die "please define owner in DEV_TEAM env var"; | ||
my @excludes = split /,/, ($ENV{'EXCLUDE_PATHS'} || ''); | ||
my $codeonwers = $ENV{'CODEOWNERS'} || './CODEOWNERS'; | ||
my @types = split /,/, ($ENV{'PHP_EXCLUDE_TYPES'} || ''); | ||
|
||
my %config = ( | ||
owner => $owner, | ||
codeowners => $codeonwers, | ||
excludes => \@excludes, | ||
); | ||
|
||
my $gitlab = GPH::Gitlab->new(%config); | ||
my $util = GPH::Util::Php->new(); | ||
|
||
my @paths = $gitlab->intersect(<STDIN>); | ||
|
||
print join(",", $util->reduce((paths => \@paths, excludes => @types))); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
namespace share\Php; | ||
|
||
abstract class Bar | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?php | ||
|
||
final readonly class Foo | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
enum FooEnum: string | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
enum MethodEnum: string | ||
{ | ||
public function colors(): string | ||
{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
interface SomethingInterface | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
trait SomethingTrait | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
text file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
#!/usr/bin/perl | ||
package t::unit::GPH::Util::Php; | ||
|
||
use strict; | ||
use warnings; | ||
|
||
use Test2::V0 -target => 'GPH::Util::Php'; | ||
use Test2::Tools::Spec; | ||
|
||
use Data::Dumper; | ||
|
||
my @paths = qw{t/share/Php/Foo.php t/share/Php/FooEnum.php t/share/Php/MethodEnum.php t/share/Php/SomethingInterface.php t/share/Php/SomethingTrait.php t/share/Php/textfile.txt t/share/Php/Bar.php}; | ||
|
||
describe "class `$CLASS`" => sub { | ||
tests 'it can be instantiated' => sub { | ||
can_ok($CLASS, 'new'); | ||
}; | ||
|
||
tests 'instantation' => sub { | ||
my ($object, $exception, $warnings); | ||
|
||
$exception = dies { | ||
$warnings = warns { | ||
$object = $CLASS->new(); | ||
}; | ||
}; | ||
|
||
is($exception, undef, 'no exception thrown'); | ||
is($warnings, 0, 'no warnings generated'); | ||
|
||
is( | ||
$object, | ||
object { | ||
field types => {}; | ||
end; | ||
}, | ||
'object as expected' | ||
) or diag Dumper($object); | ||
}; | ||
}; | ||
|
||
describe "class `$CLASS` types method" => sub { | ||
tests 'types' => sub { | ||
my ($object, $exception, $warnings); | ||
|
||
$exception = dies { | ||
$warnings = warns { | ||
$object = $CLASS->new(); | ||
$object->types(@paths); | ||
}; | ||
}; | ||
|
||
is($exception, undef, 'no exception thrown'); | ||
is($warnings, 0, 'no warnings generated'); | ||
|
||
is( | ||
$object, | ||
object { | ||
field types => hash { | ||
field interface => array { | ||
item 't/share/Php/SomethingInterface.php'; | ||
end; | ||
}; | ||
field trait => array { | ||
item 't/share/Php/SomethingTrait.php'; | ||
end; | ||
}; | ||
field enum => array { | ||
item 't/share/Php/FooEnum.php'; | ||
end; | ||
}; | ||
field method_enum => array { | ||
item 't/share/Php/MethodEnum.php'; | ||
end; | ||
}; | ||
field class => array { | ||
item 't/share/Php/Foo.php'; | ||
item 't/share/Php/Bar.php'; | ||
end; | ||
}; | ||
}; | ||
end; | ||
}, | ||
'object as expected' | ||
) or diag Dumper($object); | ||
}; | ||
|
||
tests 'die when file not found' => sub { | ||
my $object = $CLASS->new(); | ||
|
||
ok(dies {$object->types(('non/exiting/file.php'))}, 'died with non existing file') or note($@); | ||
ok(lives {$object->types(('t/share/Php/FooEnum.php'))}, 'lives with existing file') or note($@); | ||
}; | ||
}; | ||
|
||
describe "class `$CLASS` reduce method" => sub { | ||
my (@excludes, $excluded, @result, $object, $exception, $warnings); | ||
|
||
case 'exclude enum' => sub { | ||
@excludes = 'enum'; | ||
$excluded = 't/share/Php/FooEnum.php'; | ||
}; | ||
|
||
case 'exclude method_enum' => sub { | ||
@excludes = 'method_enum'; | ||
$excluded = 't/share/Php/MethodEnum.php'; | ||
}; | ||
|
||
case 'exclude class' => sub { | ||
@excludes = 'class'; | ||
$excluded = 't/share/Php/Foo.php'; | ||
}; | ||
|
||
case 'exclude interface' => sub { | ||
@excludes = 'interface'; | ||
$excluded = 't/share/Php/SomethingInterface.php'; | ||
}; | ||
|
||
case 'exclude trait' => sub { | ||
@excludes = 'trait'; | ||
$excluded = 't/share/Php/SomethingTrait.php'; | ||
}; | ||
|
||
tests 'reduce paths' => sub { | ||
$exception = dies { | ||
$warnings = warns { | ||
$object = $CLASS->new(); | ||
@result = $object->reduce((paths => \@paths, excludes => \@excludes)); | ||
}; | ||
}; | ||
|
||
is($exception, undef, 'no exception thrown'); | ||
is($warnings, 0, 'no warnings generated'); | ||
is($excluded, not_in_set(@result), 'excluded file not in set'); | ||
}; | ||
}; | ||
|
||
describe "class `$CLASS` reduce options" => sub { | ||
tests 'reduce method call' => sub { | ||
my @excludes = 'trait'; | ||
my $object = $CLASS->new(); | ||
|
||
ok(dies {$object->reduce((paths => \@paths))}, 'died with missing excludes') or note($@); | ||
ok(dies {$object->reduce((excludes => \@excludes))}, 'died with missing paths') or note($@); | ||
ok(lives {$object->reduce((paths => \@paths, excludes => \@excludes))}, 'lived with paths and excludes defined') or note($@); | ||
}; | ||
}; | ||
|
||
done_testing(); | ||
|