overrides_tracker 0.1.9 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/Gemfile +12 -3
- data/README.md +15 -0
- data/Rakefile +3 -3
- data/bin/console +3 -3
- data/bin/overrides_tracker +39 -21
- data/lib/overrides_tracker/api.rb +47 -19
- data/lib/overrides_tracker/comparer.rb +309 -75
- data/lib/overrides_tracker/file_observer.rb +1 -1
- data/lib/overrides_tracker/methods_collector.rb +114 -83
- data/lib/overrides_tracker/string_colorizer.rb +3 -5
- data/lib/overrides_tracker/util.rb +22 -25
- data/lib/overrides_tracker/version.rb +1 -1
- data/lib/overrides_tracker.rb +17 -38
- data/overrides_tracker.gemspec +19 -19
- data/spec/overrides_tracker_spec.rb +1 -5
- data/spec/spec_helper.rb +21 -5
- metadata +16 -2
@@ -1,115 +1,349 @@
|
|
1
1
|
class OverridesTracker::Comparer
|
2
2
|
DO_BASE_DIR = File.join(Dir.pwd, "/overrides_tracker")
|
3
3
|
|
4
|
-
def self.
|
5
|
-
all_methods_collections = {}
|
6
|
-
unified_methods_collections = {}
|
7
|
-
report_files = Dir.entries(DO_BASE_DIR) - [".", ".."]
|
8
|
-
report_files.each do |file_name|
|
9
|
-
if file_name[-4..-1] == '.otf'
|
10
|
-
all_methods_collections[file_name] = {}
|
11
|
-
method_collection = OverridesTracker::MethodsCollector.instance.load_from_file(file_name)
|
12
|
-
all_methods_collections[file_name] = method_collection
|
13
|
-
unified_methods_collections = unified_methods_collections.deep_merge(method_collection)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
4
|
+
def self.compare_builds(unified_methods_collections, all_methods_collections, working_directories, bundle_directories)
|
17
5
|
same_source_count = 0
|
18
6
|
errored_source_count = 0
|
19
7
|
method_not_available_count = 0
|
20
8
|
method_not_override_count = 0
|
21
9
|
source_changed_count = 0
|
22
|
-
|
23
10
|
methods_count = 0
|
24
11
|
classes_count = 0
|
25
12
|
|
26
|
-
|
13
|
+
results = []
|
14
|
+
added_method_results = []
|
27
15
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
16
|
+
numbers = {}
|
17
|
+
numbers[:overrides] = {}
|
18
|
+
numbers[:overrides][:source_changed_count] = 0
|
19
|
+
numbers[:overrides][:override_changed_count] = 0
|
20
|
+
numbers[:overrides][:method_not_available_count] = 0
|
21
|
+
numbers[:overrides][:method_not_override_count] = 0
|
22
|
+
numbers[:overrides][:total] = 0
|
23
|
+
|
24
|
+
numbers[:added_methods] = {}
|
25
|
+
numbers[:added_methods][:source_changed_count] = 0
|
26
|
+
numbers[:added_methods][:override_changed_count] = 0
|
27
|
+
numbers[:added_methods][:method_not_available_count] = 0
|
28
|
+
numbers[:added_methods][:method_not_override_count] = 0
|
29
|
+
numbers[:added_methods][:total] = 0
|
30
|
+
numbers[:total] = {}
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
|
33
|
+
unified_methods_collections.each do |unified_class_name, unified_class_hash|
|
34
|
+
if unified_class_hash['instance_methods']&.any? || unified_class_hash['singleton_methods']&.any?
|
35
|
+
['instance_methods', 'singleton_methods'].each do |method_type|
|
36
|
+
unified_class_hash[method_type]&.each do |unified_method_name, unified_method_hash|
|
37
37
|
same_source_every_where = true
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
all_methods_collections.each do |build_id, all_methods_hash|
|
40
|
+
if all_methods_hash[unified_class_name].nil? ||
|
41
|
+
all_methods_hash[unified_class_name][method_type].nil? ||
|
42
|
+
all_methods_hash[unified_class_name][method_type][unified_method_name].nil? ||
|
43
|
+
all_methods_hash[unified_class_name][method_type][unified_method_name]['sha'] != unified_method_hash['sha'] ||
|
44
|
+
all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_sha'] != unified_method_hash['overriding_sha']
|
42
45
|
same_source_every_where = false
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
49
|
+
method_result_hash = {class_name: unified_class_name, method_name: unified_method_name, builds: {}, method_type: method_type, changes_detected: false}
|
50
|
+
|
46
51
|
if same_source_every_where
|
47
|
-
|
48
|
-
same_source_count += 1
|
52
|
+
results << method_result_hash
|
49
53
|
else
|
50
|
-
|
54
|
+
method_result_hash[:changes_detected] = true
|
55
|
+
method_result_hash[:builds] ||= {}
|
56
|
+
|
57
|
+
is_source_changed_flag = false
|
58
|
+
is_override_changed_flag = false
|
59
|
+
all_methods_collections.each do |build_id, all_methods_hash|
|
60
|
+
|
61
|
+
method_result_hash[:builds][build_id] ||= {}
|
62
|
+
|
63
|
+
if all_methods_hash[unified_class_name].nil?
|
51
64
|
|
52
|
-
|
65
|
+
method_result_hash[:builds][build_id] = {result: 'method_not_available'}
|
66
|
+
numbers[:overrides][:method_not_available_count] +=1
|
67
|
+
|
68
|
+
elsif all_methods_hash[unified_class_name][method_type].nil?
|
69
|
+
if all_methods_hash[unified_class_name]["added_#{method_type}"]
|
70
|
+
if all_methods_hash[unified_class_name]["added_#{method_type}"][unified_method_name]
|
71
|
+
method_result_hash[:builds][build_id] = {result: 'method_not_override', data: all_methods_hash[unified_class_name]["added_#{method_type}"][unified_method_name]}
|
72
|
+
numbers[:overrides][:method_not_override_count] +=1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
elsif !all_methods_hash[unified_class_name][method_type][unified_method_name].nil?
|
76
|
+
if all_methods_hash[unified_class_name][method_type][unified_method_name]['sha'] != unified_method_hash['sha']
|
77
|
+
method_result_hash[:builds][build_id] = {result: 'source_has_changed'}
|
78
|
+
method_result_hash[:builds][build_id][:original_body] = all_methods_hash[unified_class_name][method_type][unified_method_name]['body']
|
79
|
+
method_result_hash[:builds][build_id][:original_sha] = all_methods_hash[unified_class_name][method_type][unified_method_name]['sha']
|
80
|
+
method_result_hash[:builds][build_id][:original_location] = all_methods_hash[unified_class_name][method_type][unified_method_name]['location']
|
81
|
+
method_result_hash[:builds][build_id][:overriding_body] = all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_body']
|
82
|
+
method_result_hash[:builds][build_id][:overriding_location] = all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_location']
|
83
|
+
method_result_hash[:builds][build_id][:overriding_sha] = all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_sha']
|
84
|
+
method_result_hash[:builds][build_id][:is_part_of_app] = all_methods_hash[unified_class_name][method_type][unified_method_name]['is_part_of_app'] || all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_is_part_of_app']
|
85
|
+
mask_path(method_result_hash[:builds][build_id], working_directories[build_id], bundle_directories[build_id])
|
86
|
+
|
87
|
+
numbers[:overrides][:source_changed_count] += 1
|
88
|
+
is_source_changed_flag = true
|
89
|
+
is_override_changed_flag = false
|
90
|
+
else
|
91
|
+
method_result_hash[:builds][build_id] = {result: 'override_has_changed'}
|
92
|
+
method_result_hash[:builds][build_id][:original_body] = all_methods_hash[unified_class_name][method_type][unified_method_name]['body']
|
93
|
+
method_result_hash[:builds][build_id][:original_sha] = all_methods_hash[unified_class_name][method_type][unified_method_name]['sha']
|
94
|
+
method_result_hash[:builds][build_id][:original_location] = all_methods_hash[unified_class_name][method_type][unified_method_name]['location']
|
95
|
+
method_result_hash[:builds][build_id][:overriding_body] = all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_body']
|
96
|
+
method_result_hash[:builds][build_id][:overriding_location] = all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_location']
|
97
|
+
method_result_hash[:builds][build_id][:overriding_sha] = all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_sha']
|
98
|
+
method_result_hash[:builds][build_id][:is_part_of_app] = all_methods_hash[unified_class_name][method_type][unified_method_name]['is_part_of_app'] || all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_is_part_of_app']
|
99
|
+
|
100
|
+
mask_path(method_result_hash[:builds][build_id], working_directories[build_id], bundle_directories[build_id])
|
101
|
+
|
102
|
+
numbers[:overrides][:override_changed_count] += 1
|
103
|
+
is_override_changed_flag = true
|
104
|
+
end
|
105
|
+
else
|
106
|
+
method_result_hash[:builds][build_id] = {result: 'method_not_available'}
|
107
|
+
numbers[:overrides][:method_not_available_count] +=1
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
if is_source_changed_flag
|
112
|
+
line_differerence_array = []
|
113
|
+
all_methods_collections.each do |build_id, all_methods_hash|
|
114
|
+
|
115
|
+
line_differerence_array << method_result_hash[:builds][build_id][:original_body].split(/\n/)
|
116
|
+
|
117
|
+
if method_result_hash[:builds][build_id][:result] == 'override_has_changed'
|
118
|
+
numbers[:overrides][:override_changed_count] -= 1
|
119
|
+
numbers[:overrides][:source_changed_count] += 1
|
120
|
+
end
|
121
|
+
method_result_hash[:builds][build_id][:result] = 'source_has_changed'
|
122
|
+
end
|
123
|
+
|
124
|
+
max_length = line_differerence_array.map(&:length).max
|
125
|
+
transposed_array = line_differerence_array.map{|e| e.values_at(0...max_length)}.transpose
|
126
|
+
method_result_hash[:mark_lines] = transposed_array.map.with_index{|val, index| val.uniq.size > 1 ? index : nil}.compact
|
127
|
+
is_override_changed_flag = false
|
128
|
+
end
|
129
|
+
|
130
|
+
if is_override_changed_flag
|
131
|
+
line_differerence_array = []
|
132
|
+
begin
|
133
|
+
|
134
|
+
all_methods_collections.each do |build_id, all_methods_hash|
|
135
|
+
line_differerence_array << method_result_hash[:builds][build_id][:overriding_body].split(/\n/)
|
136
|
+
end
|
137
|
+
|
138
|
+
max_length = line_differerence_array.map(&:length).max
|
139
|
+
transposed_array = line_differerence_array.map{|e| e.values_at(0...max_length)}.transpose
|
140
|
+
method_result_hash[:overriding_mark_lines] = transposed_array.map.with_index{|val, index| val.uniq.size > 1 ? index : nil}.compact
|
141
|
+
rescue => exception
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
method_result_hash[:is_part_of_app] = method_result_hash[:builds].select{|bu, bu_val| bu_val[:is_part_of_app] }.any?
|
148
|
+
|
149
|
+
results << method_result_hash
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
if unified_class_hash['added_instance_methods']&.any? || unified_class_hash['added_singleton_methods']&.any?
|
157
|
+
|
158
|
+
['added_instance_methods', 'added_singleton_methods'].each do |method_type|
|
159
|
+
unified_class_hash[method_type]&.each do |unified_method_name, unified_method_hash|
|
160
|
+
|
161
|
+
same_source_every_where = true
|
162
|
+
|
163
|
+
is_added_source_has_changed_flag = false
|
164
|
+
|
165
|
+
all_methods_collections.each do |build_id, all_methods_hash|
|
166
|
+
unless (all_methods_hash[unified_class_name] != nil) && (all_methods_hash[unified_class_name][method_type] != nil) && (all_methods_hash[unified_class_name][method_type][unified_method_name] != nil ) && (all_methods_hash[unified_class_name][method_type][unified_method_name]['sha'] == unified_method_hash['sha'])
|
167
|
+
same_source_every_where = false
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
method_result_hash = {class_name: unified_class_name, method_name: unified_method_name, builds: {}, method_type: method_type, changes_detected: false}
|
172
|
+
|
173
|
+
if same_source_every_where
|
174
|
+
added_method_results << method_result_hash
|
175
|
+
else
|
176
|
+
method_result_hash[:changes_detected] = true
|
177
|
+
method_result_hash[:builds] ||= {}
|
53
178
|
|
54
|
-
all_methods_collections.each do |
|
55
|
-
|
56
|
-
|
179
|
+
all_methods_collections.each do |build_id, all_methods_hash|
|
180
|
+
|
181
|
+
method_result_hash[:builds][build_id] ||= {}
|
57
182
|
|
58
|
-
if all_methods_hash[unified_class_name].nil?
|
59
|
-
|
60
|
-
method_not_available_count +=1
|
183
|
+
if all_methods_hash[unified_class_name].nil?
|
184
|
+
method_result_hash[:builds][build_id] = {result: 'added_method_not_available'}
|
185
|
+
numbers[:added_methods][:method_not_available_count] +=1
|
186
|
+
elsif all_methods_hash[unified_class_name][method_type].nil?
|
187
|
+
method_result_hash[:builds][build_id] = {result: 'added_method_not_available'}
|
188
|
+
numbers[:added_methods][:method_not_available_count] +=1
|
61
189
|
elsif !all_methods_hash[unified_class_name][method_type][unified_method_name].nil?
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
source_changed_count +=1
|
76
|
-
elsif !all_methods_hash[unified_class_name]["added_#{method_type}"][unified_method_name].nil?
|
77
|
-
puts "#{unified_class_name}##{unified_method_name}: method is not an override"
|
78
|
-
method_not_override_count +=1
|
79
|
-
|
80
|
-
puts ""
|
81
|
-
puts "Code:".bold
|
82
|
-
puts "#{all_methods_hash[unified_class_name]["added_#{method_type}"][unified_method_name]['body']}"
|
83
|
-
puts ""
|
84
|
-
# puts "#{all_methods_hash[unified_class_name]["added_#{method_type}"][unified_method_name]['location'][0]}:#{all_methods_hash[unified_class_name][method_type][unified_method_name]['location'][1]}".italic
|
85
|
-
|
86
|
-
elsif all_methods_hash[unified_class_name]["added_#{method_type}"][unified_method_name].nil?
|
87
|
-
puts "#{unified_class_name}##{unified_method_name}: method is not in codebase"
|
88
|
-
method_not_available_count +=1
|
190
|
+
method_result_hash[:builds][build_id] = {result: 'added_source_has_changed'}
|
191
|
+
method_result_hash[:builds][build_id][:original_body] = all_methods_hash[unified_class_name][method_type][unified_method_name]['body']
|
192
|
+
method_result_hash[:builds][build_id][:original_location] = all_methods_hash[unified_class_name][method_type][unified_method_name]['location']
|
193
|
+
method_result_hash[:builds][build_id][:is_part_of_app] = all_methods_hash[unified_class_name][method_type][unified_method_name]['is_part_of_app'] || all_methods_hash[unified_class_name][method_type][unified_method_name]['overriding_is_part_of_app']
|
194
|
+
|
195
|
+
mask_path(method_result_hash[:builds][build_id], working_directories[build_id], bundle_directories[build_id])
|
196
|
+
|
197
|
+
numbers[:added_methods][:source_changed_count] += 1
|
198
|
+
is_added_source_has_changed_flag = true
|
199
|
+
elsif all_methods_hash[unified_class_name][method_type][unified_method_name].nil?
|
200
|
+
method_result_hash[:builds][build_id] = {result: 'added_method_not_available'}
|
201
|
+
numbers[:added_methods][:method_not_available_count] +=1
|
89
202
|
else
|
90
|
-
|
203
|
+
method_result_hash[:builds][build_id] = {result: 'error'}
|
91
204
|
end
|
92
|
-
puts ""
|
93
|
-
|
94
205
|
end
|
95
|
-
|
206
|
+
|
207
|
+
if is_added_source_has_changed_flag
|
208
|
+
begin
|
209
|
+
|
210
|
+
line_differerence_array = []
|
211
|
+
all_methods_collections.each do |build_id, all_methods_hash|
|
212
|
+
line_differerence_array << method_result_hash[:builds][build_id][:original_body].split(/\n/)
|
213
|
+
end
|
214
|
+
|
215
|
+
max_length = line_differerence_array.map(&:length).max
|
216
|
+
transposed_array = line_differerence_array.map{|e| e.values_at(0...max_length)}.transpose
|
217
|
+
method_result_hash[:mark_added_method_lines] = transposed_array.map.with_index{|val, index| val.uniq.size > 1 ? index : nil}.compact
|
218
|
+
rescue
|
219
|
+
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
method_result_hash[:is_part_of_app] = method_result_hash[:builds].select{|bu, bu_val| bu_val[:is_part_of_app] }.any?
|
224
|
+
added_method_results << method_result_hash
|
225
|
+
|
96
226
|
end
|
97
227
|
end
|
98
|
-
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
numbers[:overrides][:total] = numbers[:overrides][:method_not_override_count] + numbers[:overrides][:method_not_available_count] + numbers[:overrides][:source_changed_count] + numbers[:overrides][:override_changed_count]
|
233
|
+
numbers[:added_methods][:total] = numbers[:added_methods][:method_not_available_count] + numbers[:added_methods][:source_changed_count]
|
234
|
+
numbers[:total] = numbers[:overrides][:total] + numbers[:added_methods][:total]
|
235
|
+
|
236
|
+
{results: {override_results: results, added_method_results: added_method_results}, numbers: numbers}
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.mask_path(build_hash, working_directory, bundle_directory)
|
240
|
+
if build_hash[:original_location]
|
241
|
+
build_hash[:original_location][0].gsub!(working_directory, 'APP_PATH')
|
242
|
+
build_hash[:original_location][0].gsub!(bundle_directory, 'BUNDLE_PATH')
|
243
|
+
end
|
244
|
+
|
245
|
+
if build_hash[:overriding_location]
|
246
|
+
build_hash[:overriding_location][0].gsub!(working_directory, 'APP_PATH')
|
247
|
+
build_hash[:overriding_location][0].gsub!(bundle_directory, 'BUNDLE_PATH')
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.compare
|
252
|
+
all_methods_collections = {}
|
253
|
+
unified_methods_collections = {}
|
254
|
+
working_directories = {}
|
255
|
+
bundle_directories = {}
|
256
|
+
|
257
|
+
all_methods_collections = {}
|
258
|
+
unified_methods_collections = {}
|
259
|
+
report_files = Dir.entries(DO_BASE_DIR) - [".", ".."]
|
260
|
+
report_files.each do |file_name|
|
261
|
+
if file_name[-4..-1] == '.otf'
|
262
|
+
all_methods_collections[file_name] = {}
|
263
|
+
result_file_data = OverridesTracker::MethodsCollector.instance.load_from_file(file_name)
|
264
|
+
result_file_data.deep_stringify_keys!
|
265
|
+
methods_collection = result_file_data['methods_collection']
|
266
|
+
all_methods_collections[file_name] = methods_collection
|
267
|
+
working_directories[file_name] = result_file_data['working_directory']
|
268
|
+
bundle_directories[file_name] = result_file_data['bundle_path']
|
269
|
+
unified_methods_collections = unified_methods_collections.deep_merge(methods_collection)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
comparison = compare_builds(unified_methods_collections, all_methods_collections, working_directories, bundle_directories)
|
274
|
+
methods_count = 0
|
275
|
+
|
276
|
+
comparison[:results].each do |result_type, result_array|
|
277
|
+
result_array.each do |method_hash|
|
278
|
+
if method_hash[:builds] != {}
|
279
|
+
methods_count += 1
|
280
|
+
puts ""
|
281
|
+
puts "==========================================================================================="
|
282
|
+
puts ""
|
283
|
+
if result_type == :override_results
|
284
|
+
puts "#{methods_count}) Override: #{method_hash[:class_name]}##{method_hash[:method_name]}".bold
|
285
|
+
else
|
286
|
+
puts "#{methods_count}) Added Method: #{method_hash[:class_name]}##{method_hash[:method_name]}".bold
|
287
|
+
end
|
288
|
+
|
289
|
+
method_hash[:builds].each do |build_id, build_result|
|
290
|
+
puts ''
|
291
|
+
puts "..........................................................................................."
|
292
|
+
puts ''
|
293
|
+
puts build_id
|
294
|
+
if build_result[:result] == 'source_has_changed'
|
295
|
+
puts ""
|
296
|
+
elsif build_result[:result] == 'method_not_override'
|
297
|
+
puts "Method not override".italic.yellow
|
298
|
+
elsif build_result[:result] == 'method_not_available'
|
299
|
+
puts "Method not available".italic.yellow
|
300
|
+
elsif build_result[:result] == 'added_method_not_available'
|
301
|
+
puts "Added method not available".italic.yellow
|
302
|
+
elsif build_result[:result] == 'added_source_has_changed'
|
303
|
+
puts ''
|
304
|
+
end
|
305
|
+
|
306
|
+
|
307
|
+
unless build_result[:original_body].nil?
|
308
|
+
puts "-------------------------------------------------------------------------------------------".pink
|
309
|
+
puts ''
|
310
|
+
puts 'Original:'.italic
|
311
|
+
puts ''
|
312
|
+
puts "#{build_result[:original_body]}".pink
|
313
|
+
puts ''
|
314
|
+
puts "in #{build_result[:original_location][0]}:#{build_result[:original_location][1]}".italic
|
315
|
+
end
|
316
|
+
puts ''
|
317
|
+
puts ''
|
318
|
+
unless build_result[:overriding_body].nil?
|
319
|
+
puts "-------------------------------------------------------------------------------------------".blue
|
320
|
+
puts ''
|
321
|
+
puts 'Override:'.italic
|
322
|
+
puts ''
|
323
|
+
puts "#{build_result[:overriding_body]}".blue
|
324
|
+
puts ''
|
325
|
+
puts "in: #{build_result[:overriding_location][0]}:#{build_result[:overriding_location][1]}".italic
|
326
|
+
end
|
327
|
+
|
328
|
+
puts ''
|
329
|
+
puts ''
|
330
|
+
end
|
331
|
+
end
|
99
332
|
end
|
100
333
|
end
|
101
334
|
|
335
|
+
|
102
336
|
puts ""
|
103
337
|
puts "==========================================================================================="
|
104
338
|
puts ""
|
105
339
|
puts "Summary:".bold
|
106
|
-
puts "
|
107
|
-
puts "#{
|
108
|
-
puts "#{
|
109
|
-
puts "
|
110
|
-
|
111
|
-
|
112
|
-
puts "#{source_changed_count} source method bodies have changed"
|
340
|
+
puts ""
|
341
|
+
puts "Investigated methods: #{comparison[:numbers][:total]/2}"
|
342
|
+
puts "Diffences on overrides: #{comparison[:numbers][:overrides][:total]/2}"
|
343
|
+
puts "Diffences on added methods: #{comparison[:numbers][:added_methods][:total]/2}"
|
344
|
+
|
345
|
+
comparison
|
113
346
|
end
|
347
|
+
|
114
348
|
end
|
115
349
|
|