@@ -35,19 +35,19 @@ def self.build_filter(filter_argument)
3535 end
3636
3737 def self . class_for_argument ( filter_argument )
38- case filter_argument
39- when String
40- SimpleCov ::StringFilter
41- when Regexp
42- SimpleCov ::RegexFilter
43- when Array
44- SimpleCov ::ArrayFilter
45- when Proc
46- SimpleCov ::BlockFilter
47- else
48- raise ArgumentError , "You have provided an unrecognized filter type"
49- end
38+ filter_classes_by_argument_type . find { |type , _ | filter_argument . is_a? ( type ) } &.last ||
39+ raise ( ArgumentError , "You have provided an unrecognized filter type" )
40+ end
41+
42+ def self . filter_classes_by_argument_type
43+ @filter_classes_by_argument_type ||= {
44+ String => SimpleCov ::StringFilter ,
45+ Regexp => SimpleCov ::RegexFilter ,
46+ Array => SimpleCov ::ArrayFilter ,
47+ Proc => SimpleCov ::BlockFilter
48+ } . freeze
5049 end
50+ private_class_method :filter_classes_by_argument_type
5151 end
5252
5353 class StringFilter < SimpleCov ::Filter
@@ -63,23 +63,26 @@ def matches?(source_file)
6363 private
6464
6565 def segment_pattern
66- @segment_pattern ||= begin
67- normalized = filter_argument . delete_prefix ( "/" )
68- escaped = Regexp . escape ( normalized )
69- boundary = '(?:\A|/)'
70- if normalized . include? ( "." )
71- # Contains a dot — looks like a filename pattern. Allow substring
72- # match within the last path segment (e.g. "test.rb" matches
73- # "faked_test.rb") while still anchoring to a segment boundary.
74- /#{ boundary } [^\/ ]*#{ escaped } /
75- elsif normalized . end_with? ( "/" )
76- # Trailing slash signals directory-only matching
77- /#{ boundary } #{ escaped } /
78- else
79- # No dot — looks like a directory or path. Require segment-boundary
80- # match so "lib" matches "lib/" but not "library/".
81- /#{ boundary } #{ escaped } (?=[\/ .]|\z )/
82- end
66+ @segment_pattern ||= compute_segment_pattern
67+ end
68+
69+ def compute_segment_pattern
70+ normalized = filter_argument . delete_prefix ( "/" )
71+ escaped = Regexp . escape ( normalized )
72+ boundary = '(?:\A|/)'
73+
74+ if normalized . include? ( "." )
75+ # Filename pattern (e.g. "test.rb" matches "faked_test.rb"): allow
76+ # substring match within the last path segment, anchored to a
77+ # segment boundary.
78+ /#{ boundary } [^\/ ]*#{ escaped } /
79+ elsif normalized . end_with? ( "/" )
80+ # Trailing slash signals directory-only matching.
81+ /#{ boundary } #{ escaped } /
82+ else
83+ # Directory or path: require a segment-boundary match so "lib"
84+ # matches "lib/" but not "library/".
85+ /#{ boundary } #{ escaped } (?=[\/ .]|\z )/
8386 end
8487 end
8588 end
0 commit comments