New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fixes #9760] Make RangeHelp#range_with_surrounding_space params consistent #10727
Conversation
7963525
to
807e2f5
Compare
807e2f5
to
dfac6a9
Compare
First, breaking changes should be avoided as much as possible. It's better to provide a migration path instead of breaking changes.
Progress to step 1 and 2 with RuboCop 1.x. Progress to step 3 with RuboCop 2.0. |
lib/rubocop/cop/mixin/range_help.rb
Outdated
raise 'Pass range as the first positional argument to ' \ | ||
'`range_with_surrounding_space`. ' \ | ||
'Passing with the `range:` kwarg is not supported.' | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow #10727 (comment)
Below is an example from step 1.
diff:
diff --git a/lib/rubocop/cop/mixin/range_help.rb b/lib/rubocop/cop/mixin/range_help.rb
index edcd0a97d..c43c46471 100644
--- a/lib/rubocop/cop/mixin/range_help.rb
+++ b/lib/rubocop/cop/mixin/range_help.rb
@@ -7,6 +7,7 @@ module RuboCop
private
BYTE_ORDER_MARK = 0xfeff # The Unicode codepoint
+ NOT_GIVEN = Object.new
def source_range(source_buffer, line_number, column, length = 1)
if column.is_a?(Range)
@@ -51,16 +52,15 @@ module RuboCop
Parser::Source::Range.new(buffer, begin_pos, end_pos)
end
- OMITTED = Module.new
- def range_with_surrounding_space(range,
- side: :both,
+ # rubocop:disable Metrics/ParameterLists
+ def range_with_surrounding_space(range_obj = NOT_GIVEN, range: nil, side: :both,
newlines: true, whitespace: false,
continuations: false)
- if range.is_a?(Hash) && range.key?(:range)
- raise 'Pass range as the first positional argument to ' \
- '`range_with_surrounding_space`. ' \
- 'Passing with the `range:` kwarg is not supported.'
- end
+ # Passing `range` keyword argument is soft deprecated. Use range as
+ # the first positional argument to instead.
+ # A deprecation warning will be displayed in the future and it will
+ # be removed in RuboCop 2.0.
+ range = range_obj if range_obj != NOT_GIVEN
buffer = @processed_source.buffer
src = buffer.source
@@ -73,6 +73,7 @@ module RuboCop
end_pos = final_pos(src, end_pos, 1, continuations, newlines, whitespace) if go_right
Parser::Source::Range.new(buffer, begin_pos, end_pos)
end
+ # rubocop:enable Metrics/ParameterLists
def range_by_whole_lines(range, include_final_newline: false)
buffer = @processed_source.buffer
plain code:
# rubocop:disable Metrics/ParameterLists
def range_with_surrounding_space(range_obj = NOT_GIVEN, range: nil, side: :both,
newlines: true, whitespace: false,
continuations: false)
# Passing `range` keyword argument is soft deprecated. Use range as
# the first positional argument to instead.
# A deprecation warning will be displayed in the future and it will
# be removed in RuboCop 2.0.
range = range_obj if range_obj != NOT_GIVEN
buffer = @processed_source.buffer
src = buffer.source
go_left, go_right = directions(side)
begin_pos = range.begin_pos
begin_pos = final_pos(src, begin_pos, -1, continuations, newlines, whitespace) if go_left
end_pos = range.end_pos
end_pos = final_pos(src, end_pos, 1, continuations, newlines, whitespace) if go_right
Parser::Source::Range.new(buffer, begin_pos, end_pos)
end
# rubocop:enable Metrics/ParameterLists
This way would allow third party cops to have a transition period, which would reduce the impact on end users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for the suggestions!
Using a default value for a positional argument should work seamlessly in Ruby 3+.
Do you think there is a good reason to separate steps 1 & 2?
I've sent a PR that adds a deprecation warning, and can be merged at some point when 1.x comes to its last releases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3rd party cop users will always encounter unexpected warnings.
We can suppress this by releasing step 1 without warning, and then 3rd party gem releases with the new positional argument.
At least rubocop org-managed gems like rubocop-(performance, rails, rspec, minitest), and etc will be able to respond between step 1 and step 2 when the warning is displayed.
So, the reason for separating step 1 and step 2 is to make a release to reduce user impact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, my apologies for not figuring this out myself. 👍
I'll take care of a Phase 1 PR and updates to extensions in our namespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixes #9760.
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.md
if the new code introduces user-observable changes. See changelog entry format for details.