40 / 40 lines covered (100.0%)
1unit module BDD::Behave::Watch::SmartSelector;23our class Selector {4 has IO::Path $.lib-root is required;5 has Mu $.spec-test = / 'spec.raku' $ /;67 method select-specs(@changes, @all-specs --> List) {8 my @selected;9 my $changed-source = False;1011 for @changes -> $change {12 next if $change.kind eq 'removed';13 my $path = $change.path;14 if $path.basename ~~ $.spec-test {15 my $abs = $path.absolute;16 @selected.push: $abs if @all-specs.first({ $_.IO.absolute eq $abs }).defined;17 } else {18 $changed-source = True;19 for self!specs-mentioning($path, @all-specs) -> $spec {20 @selected.push: $spec;21 }22 }23 }2425 if $changed-source && !@selected.elems {26 return @all-specs.map(*.IO.absolute).List;27 }2829 @selected.unique.List;30 }3132 method !specs-mentioning(IO::Path $source, @specs --> List) {33 my @terms = self.derive-terms($source);34 return ().List unless @terms.elems;3536 my @hits;37 for @specs -> $spec {38 my $path = $spec.IO;39 next unless $path.e;40 my $content = $path.slurp;41 @hits.push: $path.absolute if @terms.first({ $content.contains($_) }).defined;42 }43 @hits.List;44 }4546 method derive-terms(IO::Path $source --> List) {47 my @terms;4849 my $base = $source.basename;50 $base ~~ s/ \. <[a..zA..Z]>+ $ //;51 @terms.push: $base if $base.chars;5253 my $rel-str;54 if $!lib-root.defined && $!lib-root.e {55 my $abs = $source.absolute;56 my $root-abs = $!lib-root.absolute;57 if $abs.starts-with($root-abs ~ '/') {58 $rel-str = $abs.substr(($root-abs ~ '/').chars);59 }60 }6162 if $rel-str.defined {63 my @segs = $rel-str.split('/').grep(*.chars);64 if @segs.elems {65 @segs[*-1] ~~ s/ \. <[a..zA..Z]>+ $ //;66 @terms.push: @segs.join('::') if @segs.elems >= 2;67 for 1 .. @segs.elems - 2 -> $i {68 @terms.push: @segs[$i .. *].join('::');69 }70 }71 }7273 @terms.unique.grep(*.chars).List;74 }75}