Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
87448b2
Add configuration for only posting warnings to added/modified lines
Phillita Mar 28, 2024
fb99588
Allow warnings to be caught within a range
Phillita Apr 1, 2024
7e82368
Update README.md
Phillita Apr 1, 2024
4eff31f
End code example
Phillita Apr 1, 2024
550a64f
Add messaging for indirect offenses
Phillita Apr 18, 2024
5a4ea52
Exctract suggestion into new class to help with ruby critic.
Phillita Apr 18, 2024
c261633
Remove some linter warnings. Add support folder to rspec
Phillita Jun 18, 2024
3bc66f4
Add a documentation url to messages
Phillita Jun 18, 2024
c852517
fix deprecated method warnings with Rubocop 1.65+
ramil350 Aug 20, 2024
5d9f1c2
update README and gemspec
ashkulz Jan 11, 2025
9b36cd3
add Ruby 3.3 and 3.4 to the CI matrix
ashkulz Jan 11, 2025
539096f
setup Dependabot and Trusted Publishing workflow
ashkulz Jan 11, 2025
61eb5ad
bump version to 0.11.6
ashkulz Jan 11, 2025
3feb4c1
push_gem: fix repository name
ashkulz Jan 11, 2025
1fdafa8
Merge branch 'master' into comments-for-changed-lines-only
Phillita Jan 11, 2025
84a6a83
Remove byebug
Phillita Jan 13, 2025
8d65883
Remove rubocop from the gemspec.
Phillita Jan 13, 2025
9660c94
Reverted rubocop in the gemfile and moved it back to the gemspec
Phillita Jan 13, 2025
91556f7
Add base64 to the gemfile
Phillita Jan 13, 2025
449593d
Revert Gemfile/Gemspec gem changes
Phillita Jan 15, 2025
c08baaf
Move the string contants inline and remove unused.
Phillita Jan 15, 2025
db6e18a
Use the built in documentation_url from rubocop
Phillita Jan 16, 2025
a57b702
Merge offense_suggestion into offense_line
Phillita Jan 16, 2025
2b59c14
Remove the require offense_suggestion
Phillita Jan 16, 2025
46b828f
Update checks to remove anything below rubocop 0.90.0
Phillita Jan 20, 2025
d5948ec
Remove gemspec rubocop changes
Phillita Jan 20, 2025
82ccbfb
Remove readme section for old rubocop versions
Phillita Jan 20, 2025
d2d0bf6
Add ruby 2.3 back to the CI checks for the min rubocop version
Phillita Jan 20, 2025
17ec00d
Remove unneeded comments from the offense line
Phillita Jan 20, 2025
173d4e1
Bump up the required ruby version to 2.4
Phillita Jan 21, 2025
9ed868c
CI checks updated for ruby 2.3 removal
Phillita Jan 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 12 additions & 16 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,30 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4']
rubocop: ['0.63.1', '0.81.0', '0.84.0', '0.85.0', '0.86.0', '0.87.0', '< 1.0', '1.0.0', '1.29.1', '1.30.0', '1.38.0', '< 2.0']
ruby: ['2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4']
rubocop: ['0.90.0', '< 1.0', '1.0.0', '1.29.1', '1.30.0', '1.38.0', '< 2.0']
include:
- ruby: '2.3'
rubocop: '0.63.1'
- ruby: '2.3'
rubocop: '0.81.0'
exclude:
- ruby: '2.4'
rubocop: '1.29.1'
rubocop: '0.90.0'
- ruby: '2.4'
rubocop: '1.30.0'
rubocop: '< 1.0'
- ruby: '2.4'
rubocop: '1.38.0'
rubocop: '1.0.0'
- ruby: '2.4'
rubocop: '< 2.0'
- ruby: '2.5'
rubocop: '0.90.0'
- ruby: '2.5'
rubocop: '1.29.1'
rubocop: '< 1.0'
- ruby: '2.5'
rubocop: '1.30.0'
rubocop: '1.0.0'
- ruby: '2.5'
rubocop: '1.38.0'
rubocop: '< 2.0'
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: use specific rubocop version
run: echo "gem 'rubocop', '${{ matrix.rubocop }}'" > Gemfile.local
- name: use specific rubocop-ast version (if required)
if: matrix.rubocop == '0.84.0' || matrix.rubocop == '0.85.0'
run: echo "gem 'rubocop-ast', '< 0.7.0'" >> Gemfile.local
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
Expand Down
44 changes: 33 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
Pronto runner for [RuboCop](https://github.com/bbatsov/rubocop), ruby code
analyzer. [What is Pronto?](https://github.com/prontolabs/pronto)

- [Configuration](#configuration)
- [Usage](#usage)
- [Suggestions](#suggestions)
- [Only patched lines](#only-patched-lines)

## Configuration

Configuring RuboCop via `.rubocop.yml` will work just fine with
Expand All @@ -26,6 +31,12 @@ rubocop:

# Enable suggestions
suggestions: true

# Only report warnings on added/modified lines of code
# You can provide a number for a range to catch warnings on lines that were not modified
only_patched_lines:
enabled: false # default
range: 0 # default
```

## Suggestions
Expand All @@ -39,16 +50,27 @@ For example:

![GitHub screenshot with suggestion](https://user-images.githubusercontent.com/132/50402757-1bd75b80-0799-11e9-809f-8b8a23ed33f6.png)

## RuboCop versions
## Only patched lines

If you need to use RuboCop v0.84.0 or v0.85.x, you'll need to ensure that
you've also need to add `gem 'rubocop-ast', '< 0.7.0'` to your Gemfile as
these were the first versions to use rubocop-ast, and unfortunately the
dependency was loose enough that rubocop-ast versions >= 0.7.0 were allowed,
which causes `require 'rubocop'` to fail with
```
NoMethodError:
undefined method `join' for #<Set: {:==, :===, :!=, :<=, :>=, :>, :<}>
in rubocop-0.84.0/lib/rubocop/cop/style/redundant_conditional.rb:57:in `<class:RedundantConditional>'
When `only_patched_lines` is enabled, Rubocop warnings that start outside of the patched code will be ignored.
For example, if you add a method to a class with too many lines, the warning at the class level will not apply.

This can be useful for legacy applications with a lot of RuboCop warnings, where you want to focus on the new code.

When increasing the range, you will also catch warnings on lines that were not modified but are within the range of the modified lines.

For example, if you set `range: 1`, you will catch warnings starting before the patched lines, but only if they are within 1 line.

```ruby
# With `only_patched_lines` enabled and a default range of 1, the Metrics/ClassLength warning is not included in the results.
# However, when `range` is increased to 10, now Metrics/ClassLength will be included alongside the Metrics/MethodLength warning for the `too_long` method.
class TooLong
def just_fine
"I'm doing just fine, how about you?"
end

def too_long
# Pretend I am a new method that's 32 lines long.
end
end
```
This is due to https://github.com/rubocop-hq/rubocop-ast/issues/22
107 changes: 61 additions & 46 deletions lib/pronto/rubocop/offense_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,83 +26,98 @@ def processed_source
end

def message_text
return offense.message unless suggestion_text
return "#{indirect_message}#{offense_message}" unless suggestable?

"#{offense.message}\n\n```suggestion\n#{suggestion_text}```"
"#{offense_message}\n\n#{indirect_suggestion}#{suggestion_text}"
end

def suggestion_text
return unless patch_cop.runner.pronto_rubocop_config['suggestions']
return if corrections_count.zero?
return if corrector.nil? # possible after optimisation in https://github.com/rubocop/rubocop/pull/11264
return if differing_lines_count != corrections_count
return unless suggestable?

@suggestion_text ||= corrected_lines[offense.line - 1]
"```#{code_type}\n#{corrected_lines[offense.line - 1]}```"
end

def suggestable?
# `corrector.nil?`` possible after optimisation in https://github.com/rubocop/rubocop/pull/11264
patch_cop.runner.pronto_rubocop_config.fetch('suggestions', false) &&
(!corrections_count.zero? && !corrector.nil? && differing_lines_count == corrections_count)
end

def code_type
indirect_offense? ? 'ruby' : 'suggestion'
end

def offense_message
if documentation_url
offense.message.gsub(
offense.cop_name, "[#{offense.cop_name}](#{documentation_url})"
)
else
offense.message
end
end

def indirect_offense?
offense.location.first_line != line.new_lineno
end

def indirect_message
"Offense generated for line #{offense.location.first_line}:\n\n" if indirect_offense?
end

def indirect_suggestion
"Suggestion for line #{offense.location.first_line}:\n\n" if indirect_offense?
end

def corrected_lines
@corrected_lines ||= corrector.rewrite.lines
end

def differing_lines_count
original_lines.each_with_index.count do |line, index|
line != corrected_lines[index]
end
original_lines.each_with_index.count { |line, index| line != corrected_lines[index] }
end

def original_lines
processed_source.lines.join("\n").lines
end

if ::RuboCop::Cop::Team.respond_to?(:mobilize) && ::RuboCop::Cop::Team.public_method_defined?(:investigate)
# rubocop >= 0.87.0 has both mobilize and public investigate method
MOBILIZE = :mobilize
# rubocop 1.30.0 renamed from auto_correct to autocorrect
AUTOCORRECT = Gem::Version.new(::RuboCop::Version::STRING) >= Gem::Version.new("1.30.0") ? :autocorrect : :auto_correct

def report
@report ||= autocorrect_team.investigate(processed_source).cop_reports.first
# rubocop 1.30.0 renamed from auto_correct to autocorrect
AUTOCORRECT =
if Gem::Version.new(::RuboCop::Version::STRING) >= Gem::Version.new('1.30.0')
:autocorrect
else
:auto_correct
end

def corrector
report.corrector
end
def report
@report ||= autocorrect_team.investigate(processed_source).cop_reports.first
end

def corrections_count
# Some lines may contain more than one offense
report.offenses.map(&:line).uniq.size
end
else
# rubocop 0.85.x and 0.86.0 have mobilize, older versions don't
MOBILIZE = ::RuboCop::Cop::Team.respond_to?(:mobilize) ? :mobilize : :new
AUTOCORRECT = :auto_correct

def corrector
@corrector ||= begin
autocorrect_team.inspect_file(processed_source)
corrector = RuboCop::Cop::Corrector.new(processed_source.buffer)
corrector.corrections.concat(autocorrect_team.cops.first.corrections)
corrector
end
end
def corrector
report.corrector
end

def corrections_count
@corrections_count ||= corrector.corrections.count
end
def corrections_count
# Some lines may contain more than one offense
report.offenses.map(&:line).uniq.size
end

def autocorrect_team
@autocorrect_team ||=
::RuboCop::Cop::Team.send(MOBILIZE,
::RuboCop::Cop::Registry.new([cop_class]),
patch_cop.rubocop_config,
**{ AUTOCORRECT => true, stdin: true })
@autocorrect_team ||= ::RuboCop::Cop::Team.mobilize(
::RuboCop::Cop::Registry.new([cop_class]),
patch_cop.rubocop_config,
**{ AUTOCORRECT => true, stdin: true }
)
end

def cop_class
patch_cop.registry.find_by_cop_name(offense.cop_name)
end

def documentation_url
cop_class&.documentation_url
end

def level
severities.fetch(offense.severity.name)
end
Expand Down
19 changes: 17 additions & 2 deletions lib/pronto/rubocop/patch_cop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,11 @@ def offenses
end

def offense_includes?(offense, line_number)
offense_range = (offense.location.first_line..offense.location.last_line)
offense_range.include?(line_number)
if only_patched_lines?
(offense.location.first_line..offense.location.first_line + only_patched_lines_range).include?(line_number)
else
(offense.location.first_line..offense.location.last_line).include?(line_number)
end
end

def team
Expand All @@ -106,6 +109,18 @@ def first_relevant_message(patch, offense)

OffenseLine.new(self, offense, offending_line).message
end

def only_patched_lines
runner.pronto_rubocop_config.fetch('only_patched_lines', {})
end

def only_patched_lines?
@only_patched_lines ||= only_patched_lines.fetch('enabled', false)
end

def only_patched_lines_range
@only_patched_lines_range ||= only_patched_lines.fetch('range', 0)
end
end
end
end
4 changes: 2 additions & 2 deletions pronto-rubocop.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Gem::Specification.new do |s|
s.summary = 'Pronto runner for Rubocop, ruby code analyzer'

s.licenses = ['MIT']
s.required_ruby_version = '>= 2.3.0'
s.required_ruby_version = '>= 2.4.0'

s.files = `git ls-files`.split($RS).reject do |file|
file =~ %r{^(?:
Expand All @@ -32,7 +32,7 @@ Gem::Specification.new do |s|
s.require_paths = ['lib']

s.add_runtime_dependency('pronto', '~> 0.11.0')
s.add_runtime_dependency('rubocop', '>= 0.63.1', '< 2.0')
s.add_runtime_dependency('rubocop', '>= 0.90.0', '< 2.0')
s.add_development_dependency('base64', '~> 0.1.2')
s.add_development_dependency('rake', '~> 12.0')
s.add_development_dependency('rspec', '~> 3.4')
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/test.git/git/COMMIT_EDITMSG
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Two offenses and unsuggestable offense
Update with indirect offense
Empty file.
1 change: 1 addition & 0 deletions spec/fixtures/test.git/git/ORIG_HEAD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1bfe9ff1072c01aefe4004e7a99789e34ed8f9db
Binary file modified spec/fixtures/test.git/git/index
Binary file not shown.
2 changes: 2 additions & 0 deletions spec/fixtures/test.git/git/logs/HEAD
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ fcf76dc1596f8db6dd43f240a804c9346d0039f1 ac7e278914d5f4da3950142d416ac128cb63fb9
ac7e278914d5f4da3950142d416ac128cb63fb98 c3536be8315eef1030975d4954b87f23865db86b Sunny Ripert <sunny@sunfox.org> 1540939111 +0100 commit: Offense
c3536be8315eef1030975d4954b87f23865db86b a1095e78c5733f4a4df3862561bb52117b9f09f1 Sunny Ripert <sunny@sunfox.org> 1557921651 +0200 commit: Two offenses
a1095e78c5733f4a4df3862561bb52117b9f09f1 348c6ed6673e746c6f40e8a167b0bfe1193ff6e6 Sunny Ripert <sunny@sunfox.org> 1557923263 +0200 commit: Two offenses and unsuggestable offense
348c6ed6673e746c6f40e8a167b0bfe1193ff6e6 76a8537d7fcafc96ffa68929f41dcc53b0010d86 Tayler Phillips <tphillips@infotech.com> 1713448302 -0400 commit: New test method
76a8537d7fcafc96ffa68929f41dcc53b0010d86 901e9f5e845f63093df063c6523411c36ea27164 Tayler Phillips <tphillips@infotech.com> 1713448333 -0400 commit: Update with indirect offense
2 changes: 2 additions & 0 deletions spec/fixtures/test.git/git/logs/refs/heads/master
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ fcf76dc1596f8db6dd43f240a804c9346d0039f1 ac7e278914d5f4da3950142d416ac128cb63fb9
ac7e278914d5f4da3950142d416ac128cb63fb98 c3536be8315eef1030975d4954b87f23865db86b Sunny Ripert <sunny@sunfox.org> 1540939111 +0100 commit: Offense
c3536be8315eef1030975d4954b87f23865db86b a1095e78c5733f4a4df3862561bb52117b9f09f1 Sunny Ripert <sunny@sunfox.org> 1557921651 +0200 commit: Two offenses
a1095e78c5733f4a4df3862561bb52117b9f09f1 348c6ed6673e746c6f40e8a167b0bfe1193ff6e6 Sunny Ripert <sunny@sunfox.org> 1557923263 +0200 commit: Two offenses and unsuggestable offense
348c6ed6673e746c6f40e8a167b0bfe1193ff6e6 76a8537d7fcafc96ffa68929f41dcc53b0010d86 Tayler Phillips <tphillips@infotech.com> 1713448302 -0400 commit: New test method
76a8537d7fcafc96ffa68929f41dcc53b0010d86 901e9f5e845f63093df063c6523411c36ea27164 Tayler Phillips <tphillips@infotech.com> 1713448333 -0400 commit: Update with indirect offense
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xmϻ�0 P�|ŕ���� �QK\��K��Ɇ �%ߣ����#����1��R�,iO�g�4�+$-d��̸˭lp4Ar�o�WtY��"��h�3g~��j6��}�j�445�N�.������la]6
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xe�=�0 `��I ]i� �\�=j� �BR%���7dK~���1���m��J�P�˜�>�Le�WpYɘGjŝ*�d3@� ܲ�rh,+Wt�]˔��/Z���{j5�545�4�58�ND�����XZ
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x��Mj�0���)�Z��X�R�����yX`[FQ�}T� ��f>&�}/��ſ��_Btb�b�����^^���|�p&0��䆣��� b��I�`�z9����� 9*��kmt���nkٶr>����U�i�Hu�$�s�f�w=�j��i��껶��9n�r��g���x@=�QT�
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x��;!E�Y�ۀ�� �ckg���Ȑ������K�
�NNrn.�m���O��N�� -��HK *�D2� �3�sʳ�7*���4�`�q&����ZG+8O"J�H���6x��J�K^׼p��﹤� � ��������3ל�a��>��7أ��;Ԕ�ta_�P{
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x��Kj�0��)� �X?B��Er�V� l�h4 �}�� �{T��{�`}|��,j-�}%��=%�`s)�Q1�V��,Չ�� 1`�.�(�B9�`H�fYL%�hmtMA�c�}��l<�sm���;���7?�!}2�o��w0ѸeI�9xՋ����y��o���dx��B;jL�wV�XzU�
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
x]Ͽ
� ��f��G�s��I�A�j�s��S!���>_n8}[�7�n�2�����<;�K�9��P��Og��͕�r �-�QJpo^�p�BK���S(�&
3�o~�D�
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
xe���0 `�{�\(�W_���(���V.>=�L94i��m�х��=a���$��7��݀�J=ܐ���Ν�8�ټ�^�f�,��d-�ު}�ޒ'u��o����[������V�E�UB'AW;�,��
 ]-
Binary file not shown.
2 changes: 1 addition & 1 deletion spec/fixtures/test.git/git/refs/heads/master
Original file line number Diff line number Diff line change
@@ -1 +1 @@
348c6ed6673e746c6f40e8a167b0bfe1193ff6e6
901e9f5e845f63093df063c6523411c36ea27164
14 changes: 14 additions & 0 deletions spec/fixtures/test.git/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,17 @@ def zoo
def goo
"gar"
end

def hoo
arr = []
arr << 'test1'
arr << 'test2'
arr << 'test3'
arr << 'test4'
arr << 'test5'
arr << 'test6'
arr << 'test7'
arr << 'test8'
arr << 'test9'
arr << 'test10'
end
Loading