-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Expected behavior
RuboCop should autocorrect a nested if -> unless -> if structure into a single if statement with combined conditions, converting unless to ! as needed.
if foo
unless bar
^^^^^^ Consider merging nested conditions into outer `if` conditions.
if baz
^^ Consider merging nested conditions into outer `unless` conditions.
do_something
end
end
end
Should be autocorrected to:
if foo && !bar && baz
do_something
end
Actual behavior
Although the autocorrection works correctly as expected, the following clobbering error is output:
An error occurred while Style/SoleNestedConditional cop was inspecting /app/app/forms/sample_form.rb:1:1.
Parser::Source::TreeRewriter detected clobbering
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter.rb:427:in `trigger_policy'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter.rb:414:in `enforce_policy'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:234:in `call'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:234:in `swallow'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:98:in `with'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:125:in `place_in_hierarchy'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:107:in `do_combine'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:118:in `place_in_hierarchy'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:132:in `block in combine_children'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:131:in `each'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:131:in `inject'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:131:in `combine_children'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:222:in `merge'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:105:in `do_combine'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter/action.rb:31:in `combine'
/app/vendor/bundle/ruby/3.2.0/gems/parser-3.3.8.0/lib/parser/source/tree_rewriter.rb:143:in `merge!'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/base.rb:374:in `apply_correction'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/base.rb:453:in `attempt_correction'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/base.rb:434:in `use_corrector'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/base.rb:428:in `correct'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/base.rb:210:in `add_offense'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/style/sole_nested_conditional.rb:67:in `on_if'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:107:in `public_send'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:107:in `block (2 levels) in trigger_responding_cops'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:171:in `with_cop_error_handling'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:106:in `block in trigger_responding_cops'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:105:in `each'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:105:in `trigger_responding_cops'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:69:in `on_if'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:164:in `on_if'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_if'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `block in on_dstr'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `each'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `on_dstr'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_begin'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:164:in `on_if'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_if'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `block in on_dstr'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `each'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `on_dstr'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_begin'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:163:in `on_def'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_def'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `block in on_dstr'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `each'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:146:in `on_dstr'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_begin'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:163:in `on_class'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_class'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:147:in `on_while'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:71:in `on_module'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-ast-1.45.0/lib/rubocop/ast/traversal.rb:20:in `walk'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/commissioner.rb:87:in `investigate'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/team.rb:174:in `investigate_partial'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cop/team.rb:101:in `investigate'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:349:in `block in inspect_file'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:348:in `each'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:348:in `flat_map'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:348:in `inspect_file'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:291:in `block in do_inspection_loop'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:325:in `block in iterate_until_no_changes'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:318:in `loop'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:318:in `iterate_until_no_changes'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:287:in `do_inspection_loop'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:168:in `block in file_offenses'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:193:in `file_offense_cache'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:167:in `file_offenses'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:158:in `process_file'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:139:in `block in each_inspected_file'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:138:in `each'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:138:in `reduce'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:138:in `each_inspected_file'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:124:in `inspect_files'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/runner.rb:77:in `run'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli/command/execute_runner.rb:26:in `block in execute_runner'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli/command/execute_runner.rb:52:in `with_redirect'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli/command/execute_runner.rb:25:in `execute_runner'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli/command/execute_runner.rb:17:in `run'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli/command.rb:11:in `run'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli/environment.rb:18:in `run'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli.rb:122:in `run_command'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli.rb:129:in `execute_runners'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli.rb:51:in `block in run'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli.rb:81:in `profile_if_needed'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/lib/rubocop/cli.rb:43:in `run'
/app/vendor/bundle/ruby/3.2.0/gems/rubocop-1.69.2/exe/rubocop:19:in `<top (required)>'
/app/vendor/bundle/ruby/3.2.0/bin/rubocop:25:in `load'
/app/vendor/bundle/ruby/3.2.0/bin/rubocop:25:in `<top (required)>'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/cli/exec.rb:58:in `load'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/cli/exec.rb:58:in `kernel_load'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/cli/exec.rb:23:in `run'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/cli.rb:492:in `exec'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/cli.rb:34:in `dispatch'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/cli.rb:28:in `start'
/usr/local/bundle/gems/bundler-2.4.16/exe/bundle:37:in `block in <top (required)>'
/usr/local/bundle/gems/bundler-2.4.16/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/usr/local/bundle/gems/bundler-2.4.16/exe/bundle:29:in `<top (required)>'
/usr/local/bundle/bin/bundle:25:in `load'
/usr/local/bundle/bin/bundle:25:in `<main>'
W
Steps to reproduce the problem
This issue occurs with three-level nested conditionals structured as if -> unless -> if.(It does not occur with three nested if statements.)
if foo
unless bar
if baz
do_something
end
end
end
RuboCop version
Include the output of rubocop -V
or bundle exec rubocop -V
if using Bundler.
If you see extension cop versions (e.g. rubocop-performance
, rubocop-rspec
, and others)
output by rubocop -V
, include them as well. Here's an example:
/app # bundle exec rubocop -V
1.69.2 (using Parser 3.3.8.0, rubocop-ast 1.45.0, analyzing as Ruby 3.2, running on ruby 3.2.2) [aarch64-linux-musl]
- rubocop-performance 1.23.1
- rubocop-rails 2.27.0
- rubocop-rspec 3.3.0
I investigated the error.
The Style/SoleNestedConditional cop converts unless statements into if ! form before attempting to merge them.
Correction A: tries to combine the outer if and the middle unless.
Correction B: Attempts to combine the middle unless with the inner if. This also tries to modify the same range.
Both corrections attempt to modify the same code range that includes the middle unless keyword and its condition, resulting in conflicting changes.
May I try to fix this error?.