Module: Ace::Review::Molecules::SubjectFilter
- Defined in:
- lib/ace/review/molecules/subject_filter.rb
Overview
Pure module for filtering review subjects based on file patterns.
Provides file pattern matching logic for filtering diff content, file lists, and bundle sections. Uses glob patterns with include/exclude semantics following the standard: include patterns whitelist files, exclude patterns blacklist them.
Constant Summary collapse
- FNMATCH_FLAGS =
File.fnmatch flags for glob pattern matching
File::FNM_PATHNAME | File::FNM_EXTGLOB
Class Method Summary collapse
-
.filter(subject, file_patterns) ⇒ String, Hash
Filter subject content based on file patterns.
-
.filter_bundle_sections(sections, file_patterns) ⇒ Hash
Filter bundle sections based on file patterns.
-
.filter_diff(diff_content, file_patterns) ⇒ String
Filter diff content based on file patterns.
-
.filter_hash(subject, file_patterns) ⇒ Hash
Filter subject hash based on file patterns.
-
.has_patterns?(file_patterns) ⇒ Boolean
Check if file patterns are configured and non-empty.
-
.matches_file?(file_path, file_patterns) ⇒ Boolean
Check if a file path matches the given patterns.
Class Method Details
.filter(subject, file_patterns) ⇒ String, Hash
Filter subject content based on file patterns
Dispatches to appropriate filter method based on subject type. Returns subject unchanged if no patterns configured.
33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/ace/review/molecules/subject_filter.rb', line 33 def self.filter(subject, file_patterns) return subject unless has_patterns?(file_patterns) case subject when String filter_diff(subject, file_patterns) when Hash filter_hash(subject, file_patterns) else subject end end |
.filter_bundle_sections(sections, file_patterns) ⇒ Hash
Filter bundle sections based on file patterns
Recursively filters files arrays within each section.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/ace/review/molecules/subject_filter.rb', line 102 def self.filter_bundle_sections(sections, file_patterns) filtered = {} sections.each do |name, section| section = normalize_keys(section) if section.is_a?(Hash) if section.is_a?(Hash) && section["files"].is_a?(Array) filtered_files = section["files"].select { |f| matches_file?(f.to_s, file_patterns) } next if filtered_files.empty? filtered[name] = section.merge("files" => filtered_files) else filtered[name] = section end end filtered end |
.filter_diff(diff_content, file_patterns) ⇒ String
Filter diff content based on file patterns
Splits diff into per-file chunks, filters by patterns, and rejoins. Uses the destination (b/) path for consistency with renamed files.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/ace/review/molecules/subject_filter.rb', line 54 def self.filter_diff(diff_content, file_patterns) return diff_content unless has_patterns?(file_patterns) # Split diff into file chunks chunks = split_diff_into_chunks(diff_content) # Filter chunks based on file patterns filtered_chunks = chunks.select do |chunk| file_path = extract_file_path_from_chunk(chunk) file_path ? matches_file?(file_path, file_patterns) : true end filtered_chunks.join end |
.filter_hash(subject, file_patterns) ⇒ Hash
Filter subject hash based on file patterns
Filters files arrays and bundle sections within the hash.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/ace/review/molecules/subject_filter.rb', line 76 def self.filter_hash(subject, file_patterns) return subject unless has_patterns?(file_patterns) result = normalize_keys(subject.dup) # Filter files array if present if result["files"].is_a?(Array) result["files"] = result["files"].select { |f| matches_file?(f.to_s, file_patterns) } end # Filter bundle sections if present if result["bundle"].is_a?(Hash) && result["bundle"]["sections"].is_a?(Hash) result["bundle"] = normalize_keys(result["bundle"].dup) result["bundle"]["sections"] = filter_bundle_sections(result["bundle"]["sections"], file_patterns) end result end |
.has_patterns?(file_patterns) ⇒ Boolean
Check if file patterns are configured and non-empty
150 151 152 153 154 155 |
# File 'lib/ace/review/molecules/subject_filter.rb', line 150 def self.has_patterns?(file_patterns) return false unless file_patterns.is_a?(Hash) (file_patterns["include"].is_a?(Array) && file_patterns["include"].any?) || (file_patterns["exclude"].is_a?(Array) && file_patterns["exclude"].any?) end |
.matches_file?(file_path, file_patterns) ⇒ Boolean
Check if a file path matches the given patterns
Include patterns: file must match at least one (if any exist) Exclude patterns: file must not match any
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/ace/review/molecules/subject_filter.rb', line 129 def self.matches_file?(file_path, file_patterns) return true unless has_patterns?(file_patterns) includes = file_patterns["include"] || [] excludes = file_patterns["exclude"] || [] # If include patterns exist, file must match at least one if includes.any? return false unless includes.any? { |pattern| File.fnmatch?(pattern, file_path, FNMATCH_FLAGS) } end # File must not match any exclude pattern return false if excludes.any? { |pattern| File.fnmatch?(pattern, file_path, FNMATCH_FLAGS) } true end |