@@ -33,15 +33,23 @@ def self.get_reference_offenses(violation_types, git_filesystem)
3333 renamed_files_before = git_filesystem . renamed_files . map { |before_after_file | before_after_file [ :before ] }
3434 renamed_files_after = git_filesystem . renamed_files . map { |before_after_file | before_after_file [ :after ] }
3535
36+ # Build a rename mapping to normalize file paths when comparing violations
37+ rename_mapping = build_rename_mapping ( git_filesystem . renamed_files )
38+
3639 git_filesystem . modified_files . grep ( PACKAGE_TODO_PATTERN ) . each do |modified_package_todo_yml_file |
3740 # We skip over modified files if one of the modified files is a renamed `package_todo.yml` file.
3841 # This allows us to rename packs while ignoring "new violations" in those renamed packs.
3942 next if renamed_files_before . include? ( modified_package_todo_yml_file )
4043
4144 head_commit_violations = BasicReferenceOffense . from ( modified_package_todo_yml_file )
4245 base_commit_violations = get_violations_before_patch_for ( git_filesystem , modified_package_todo_yml_file )
43- added_violations += head_commit_violations - base_commit_violations
44- removed_violations += base_commit_violations - head_commit_violations
46+
47+ # Normalize violations for renames: update old file paths to new file paths
48+ # so that violations referring to renamed files are properly matched
49+ normalized_base_violations = normalize_violations_for_renames ( base_commit_violations , rename_mapping )
50+
51+ added_violations += head_commit_violations - normalized_base_violations
52+ removed_violations += normalized_base_violations - head_commit_violations
4553 end
4654
4755 #
@@ -78,6 +86,40 @@ def self.get_reference_offenses(violation_types, git_filesystem)
7886 [ relevant_added_violations , relevant_removed_violations ]
7987 end
8088
89+ sig do
90+ params (
91+ renamed_files : T ::Array [ { after : String , before : String } ]
92+ ) . returns ( T ::Hash [ String , String ] )
93+ end
94+ def self . build_rename_mapping ( renamed_files )
95+ renamed_files . each_with_object ( { } ) do |rename , mapping |
96+ mapping [ rename [ :before ] ] = rename [ :after ]
97+ end
98+ end
99+
100+ sig do
101+ params (
102+ violations : T ::Array [ BasicReferenceOffense ] ,
103+ rename_mapping : T ::Hash [ String , String ]
104+ ) . returns ( T ::Array [ BasicReferenceOffense ] )
105+ end
106+ def self . normalize_violations_for_renames ( violations , rename_mapping )
107+ violations . map do |violation |
108+ file = rename_mapping [ violation . file ]
109+ next violation unless file
110+
111+ # Create a new violation with the updated file path
112+ BasicReferenceOffense . new (
113+ class_name : violation . class_name ,
114+ file : file ,
115+ to_package_name : violation . to_package_name ,
116+ from_package_name : violation . from_package_name ,
117+ type : violation . type ,
118+ file_location : violation . file_location
119+ )
120+ end
121+ end
122+
81123 sig do
82124 params (
83125 git_filesystem : GitFilesystem ,
0 commit comments