From d5c7f35eb79e2e3275a2d6376cb4a1bc5a8b8265 Mon Sep 17 00:00:00 2001 From: Eric Mueller Date: Mon, 5 Dec 2022 17:10:32 -0500 Subject: [PATCH 1/2] update PatchCop to support spanning errors We want to keep an error if it _includes_ any lines in a given patch. We also want only the first such line, since it likely includes more than one (this singularism was implicit before, because each line was only passed through once) --- lib/pronto/rubocop/patch_cop.rb | 16 +++++++++++++--- spec/pronto/rubocop/patch_cop_spec.rb | 11 ++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/pronto/rubocop/patch_cop.rb b/lib/pronto/rubocop/patch_cop.rb index 27e8c62..ba54224 100644 --- a/lib/pronto/rubocop/patch_cop.rb +++ b/lib/pronto/rubocop/patch_cop.rb @@ -14,10 +14,15 @@ def messages return [] unless valid? offenses.flat_map do |offense| - patch + offending_line = patch .added_lines - .select { |line| line.new_lineno == offense.line } - .map { |line| OffenseLine.new(self, offense, line).message } + .detect { |line| offense_includes?(offense, line.new_lineno) } + + if offending_line + [OffenseLine.new(self, offense, offending_line).message] + else + [] + end end end @@ -66,6 +71,11 @@ def offenses .reject(&:disabled?) end + def offense_includes?(offense, line_number) + offense_range = (offense.location.first_line..offense.location.last_line) + offense_range.include?(line_number) + end + def team @team ||= if ::RuboCop::Cop::Team.respond_to?(:mobilize) diff --git a/spec/pronto/rubocop/patch_cop_spec.rb b/spec/pronto/rubocop/patch_cop_spec.rb index 841f59c..0cbf83a 100644 --- a/spec/pronto/rubocop/patch_cop_spec.rb +++ b/spec/pronto/rubocop/patch_cop_spec.rb @@ -12,7 +12,8 @@ let(:ast) { double :ast, each_node: nil } let(:processed_source) { double :processed_source, ast: ast } let(:team) { double :team, inspect_file: [offense] } - let(:offense) { double :offense, disabled?: false, line: 42 } + let(:offense_location) { double :location, first_line: 42, last_line: 43 } + let(:offense) { double :offense, disabled?: false, location: offense_location } let(:offense_line) { double :offense_line, message: 'Err' } before do @@ -31,5 +32,13 @@ it do expect(patch_cop.messages).to eq(['Err']) end + + context 'when there is an error including the patch, but not starting inside it' do + let(:offense_location) { double :location, first_line: 40, last_line: 43 } + + it do + expect(patch_cop.messages).to eq(['Err']) + end + end end end From 84061649a1ae7088e949e81fec437aba37b2bf2c Mon Sep 17 00:00:00 2001 From: Eric Mueller Date: Mon, 16 Jan 2023 07:29:49 -0500 Subject: [PATCH 2/2] factor out some private methods to simplify the original flat_map logic --- lib/pronto/rubocop/patch_cop.rb | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/pronto/rubocop/patch_cop.rb b/lib/pronto/rubocop/patch_cop.rb index 484540c..6655d39 100644 --- a/lib/pronto/rubocop/patch_cop.rb +++ b/lib/pronto/rubocop/patch_cop.rb @@ -13,17 +13,9 @@ def initialize(patch, runner) def messages return [] unless valid? - offenses.flat_map do |offense| - offending_line = patch - .added_lines - .detect { |line| offense_includes?(offense, line.new_lineno) } - - if offending_line - [OffenseLine.new(self, offense, offending_line).message] - else - [] - end - end + offenses + .map { |offense| first_relevant_message(patch, offense) } + .compact end def processed_source @@ -86,6 +78,19 @@ def team ::RuboCop::Cop::Team.new(registry, rubocop_config) end end + + def first_relevant_line(patch, offense) + patch.added_lines.detect do |line| + offense_includes?(offense, line.new_lineno) + end + end + + def first_relevant_message(patch, offense) + offending_line = first_relevant_line(patch, offense) + return nil unless offending_line + + OffenseLine.new(self, offense, offending_line).message + end end end end