Skip to content

Commit 628eca3

Browse files
refactor: pulled out issue sorter into class
1 parent 742267d commit 628eca3

File tree

3 files changed

+78
-74
lines changed

3 files changed

+78
-74
lines changed

lib/codeclimate_diff/issue_sorter.rb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# frozen_string_literal: true
2+
3+
module CodeclimateDiff
4+
class IssueSorter
5+
def self.remove_closest_match_from_list(issue_to_match, list)
6+
# check for exact match first
7+
index = list.index do |issue|
8+
issue["fingerprint"] == issue_to_match["fingerprint"] &&
9+
issue["location"]["lines"]["begin"] == issue_to_match["location"]["lines"]["begin"] &&
10+
issue["description"] == issue_to_match["description"]
11+
end
12+
13+
if index
14+
list.delete_at(index)
15+
return
16+
end
17+
18+
# check for same method name (description often has method name or variable name in it)
19+
index = list.index do |issue|
20+
issue["fingerprint"] == issue_to_match["fingerprint"] &&
21+
issue["description"] == issue_to_match["description"]
22+
end
23+
24+
if index
25+
list.delete_at(index)
26+
return
27+
end
28+
29+
# otherwise just remove the first one
30+
list.pop
31+
end
32+
33+
def self.sort_issues(preexisting_issues, changed_file_issues)
34+
puts "Sorting into :preexisting, :new and :fixed lists..."
35+
36+
result = {}
37+
result[:preexisting] = []
38+
result[:new] = []
39+
result[:fixed] = []
40+
41+
# fingerprints are unique per issue type and file
42+
# so there could be multiple if the same issue shows up multiple times
43+
# plus line numbers and method names could have changed
44+
unique_fingerprints = (preexisting_issues + changed_file_issues).map { |issue| issue["fingerprint"] }.uniq
45+
46+
unique_fingerprints.each do |fingerprint|
47+
baseline_issues = preexisting_issues.filter { |issue| issue["fingerprint"] == fingerprint }
48+
current_issues = changed_file_issues.filter { |issue| issue["fingerprint"] == fingerprint }
49+
50+
if baseline_issues.count == current_issues.count
51+
# current issues are most up to date (line numbers could have changed etc.)
52+
result[:preexisting] += current_issues
53+
elsif current_issues.count < baseline_issues.count
54+
# less issues than there were before
55+
current_issues.each do |issue_to_match|
56+
CodeclimateDiff.remove_closest_match_from_list(issue_to_match, baseline_issues)
57+
end
58+
result[:fixed] += baseline_issues
59+
else
60+
# more issues than there were before
61+
baseline_issues.each do |issue_to_match|
62+
CodeclimateDiff.remove_closest_match_from_list(issue_to_match, current_issues)
63+
end
64+
result[:new] += current_issues
65+
end
66+
end
67+
68+
# do a check to make sure the maths works out
69+
puts "#{preexisting_issues.count} issues in matching files in baseline"
70+
puts "#{changed_file_issues.count} current issues in matching files"
71+
72+
result
73+
end
74+
end
75+
end

lib/codeclimate_diff/result_printer.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,4 @@ def self.print_call_to_action(sorted_issues)
9191
end
9292
end
9393
end
94-
end
94+
end

lib/codeclimate_diff/runner.rb

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
require "colorize"
55
require_relative "./codeclimate_wrapper"
66
require_relative "./result_printer"
7+
require_relative "./issue_sorter"
78

89
module CodeclimateDiff
910
class Runner
10-
11-
1211
def self.calculate_changed_filenames(pattern)
1312
extra_grep_filter = pattern ? " | grep '#{pattern}'" : ""
1413
files_changed = `git diff --name-only main | grep --invert-match spec/ | grep --extended-regexp '.js$|.rb$'#{extra_grep_filter}`
@@ -40,76 +39,6 @@ def self.calculate_preexisting_issues_in_changed_files(changed_filenames)
4039
all_issues.filter { |issue| issue.key?("location") && changed_filenames.include?(issue["location"]["path"]) }
4140
end
4241

43-
def self.remove_closest_match_from_list(issue_to_match, list)
44-
# check for exact match first
45-
index = list.index do |issue|
46-
issue["fingerprint"] == issue_to_match["fingerprint"] &&
47-
issue["location"]["lines"]["begin"] == issue_to_match["location"]["lines"]["begin"] &&
48-
issue["description"] == issue_to_match["description"]
49-
end
50-
51-
if index
52-
list.delete_at(index)
53-
return
54-
end
55-
56-
# check for same method name (description often has method name or variable name in it)
57-
index = list.index do |issue|
58-
issue["fingerprint"] == issue_to_match["fingerprint"] &&
59-
issue["description"] == issue_to_match["description"]
60-
end
61-
62-
if index
63-
list.delete_at(index)
64-
return
65-
end
66-
67-
# otherwise just remove the first one
68-
list.pop
69-
end
70-
71-
def self.sort_issues(preexisting_issues, changed_file_issues)
72-
puts "Sorting into :preexisting, :new and :fixed lists..."
73-
74-
result = {}
75-
result[:preexisting] = []
76-
result[:new] = []
77-
result[:fixed] = []
78-
79-
# fingerprints are unique per issue type and file
80-
# so there could be multiple if the same issue shows up multiple times
81-
# plus line numbers and method names could have changed
82-
unique_fingerprints = (preexisting_issues + changed_file_issues).map { |issue| issue["fingerprint"] }.uniq
83-
84-
unique_fingerprints.each do |fingerprint|
85-
baseline_issues = preexisting_issues.filter { |issue| issue["fingerprint"] == fingerprint }
86-
current_issues = changed_file_issues.filter { |issue| issue["fingerprint"] == fingerprint }
87-
88-
if baseline_issues.count == current_issues.count
89-
# current issues are most up to date (line numbers could have changed etc.)
90-
result[:preexisting] += current_issues
91-
elsif current_issues.count < baseline_issues.count
92-
# less issues than there were before
93-
current_issues.each do |issue_to_match|
94-
CodeclimateDiff.remove_closest_match_from_list(issue_to_match, baseline_issues)
95-
end
96-
result[:fixed] += baseline_issues
97-
else
98-
# more issues than there were before
99-
baseline_issues.each do |issue_to_match|
100-
CodeclimateDiff.remove_closest_match_from_list(issue_to_match, current_issues)
101-
end
102-
result[:new] += current_issues
103-
end
104-
end
105-
106-
# do a check to make sure the maths works out
107-
puts "#{preexisting_issues.count} issues in matching files in baseline"
108-
puts "#{changed_file_issues.count} current issues in matching files"
109-
110-
result
111-
end
112-
11342
def self.generate_baseline
11443
puts "Generating the baseline. Should take about 5 minutes..."
11544
result = CodeclimateWrapper.new.run_codeclimate
@@ -124,7 +53,7 @@ def self.run_diff_on_branch(pattern, show_preexisting: true)
12453

12554
preexisting_issues = calculate_preexisting_issues_in_changed_files(changed_filenames)
12655

127-
sorted_issues = sort_issues(preexisting_issues, changed_file_issues)
56+
sorted_issues = IssueSorter.sort_issues(preexisting_issues, changed_file_issues)
12857

12958
ResultPrinter.print_result(sorted_issues, show_preexisting)
13059
ResultPrinter.print_call_to_action(sorted_issues)

0 commit comments

Comments
 (0)