Skip to content

Commit

Permalink
[Fix rubocop#8782] Mark any condition with defined? as an unsafe auto…
Browse files Browse the repository at this point in the history
…correction if it is not parenthesized.

Without parens, `defined?` will apply to the entire ternary instead of its previous argument, which makes this autocorrection incorrect.
  • Loading branch information
dvandersluis committed Oct 8, 2020
1 parent decf0cb commit dd6944c
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,10 @@

## master (unreleased)

### Bug fixes

* [#8782](https://github.com/rubocop-hq/rubocop/issues/8782): Fix incorrect autocorrection for `Style/TernaryParentheses` with `defined?`. ([@dvandersluis][])

## 0.93.0 (2020-10-08)

### New features
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/ternary_parentheses.rb
Expand Up @@ -192,7 +192,7 @@ def below_ternary_precedence?(child)
end

def_node_matcher :method_name, <<~PATTERN
{($:defined? (send nil? _) ...)
{($:defined? _ ...)
(send {_ nil?} $_ _ ...)}
PATTERN

Expand Down
116 changes: 116 additions & 0 deletions spec/rubocop/cop/style/ternary_parentheses_spec.rb
Expand Up @@ -159,6 +159,50 @@
not (bar) ? a : b
RUBY
end

it 'registers an offense for defined? with variable in condition' do
expect_offense(<<~RUBY)
foo = defined?(bar) ? a : b
^^^^^^^^^^^^^^^^^^^^^ Use parentheses for ternary conditions.
RUBY

expect_correction(<<~RUBY)
foo = (defined?(bar)) ? a : b
RUBY
end

it 'registers an offense for defined? with method chain in condition' do
expect_offense(<<~RUBY)
foo = defined?(bar.baz) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^ Use parentheses for ternary conditions.
RUBY

expect_correction(<<~RUBY)
foo = (defined?(bar.baz)) ? a : b
RUBY
end

it 'registers an offense for defined? with class method in condition' do
expect_offense(<<~RUBY)
foo = defined?(Bar.baz) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^ Use parentheses for ternary conditions.
RUBY

expect_correction(<<~RUBY)
foo = (defined?(Bar.baz)) ? a : b
RUBY
end

it 'registers an offense for defined? with nested constant in condition' do
expect_offense(<<~RUBY)
foo = defined?(Bar::BAZ) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^^ Use parentheses for ternary conditions.
RUBY

expect_correction(<<~RUBY)
foo = (defined?(Bar::BAZ)) ? a : b
RUBY
end
end

context 'with an assignment condition' do
Expand Down Expand Up @@ -327,6 +371,42 @@

expect_no_corrections
end

it 'registers an offense for defined with variable in condition' do
expect_offense(<<~RUBY)
foo = (defined? bar) ? a : b
^^^^^^^^^^^^^^^^^^^^^^ Omit parentheses for ternary conditions.
RUBY

expect_no_corrections
end

it 'registers an offense for defined with method chain in condition' do
expect_offense(<<~RUBY)
foo = (defined? bar.baz) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^^ Omit parentheses for ternary conditions.
RUBY

expect_no_corrections
end

it 'registers an offense for defined with class method in condition' do
expect_offense(<<~RUBY)
foo = (defined? Bar.baz) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^^ Omit parentheses for ternary conditions.
RUBY

expect_no_corrections
end

it 'registers an offense for defined with nested constant in condition' do
expect_offense(<<~RUBY)
foo = (defined? Bar::BAZ) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Omit parentheses for ternary conditions.
RUBY

expect_no_corrections
end
end

context 'with an assignment condition' do
Expand Down Expand Up @@ -521,6 +601,42 @@
it 'accepts boolean expression' do
expect_no_offenses('foo = (bar && (baz || bar)) ? a : b')
end

it 'registers an offense for defined with variable in condition' do
expect_offense(<<~RUBY)
foo = (defined? bar) ? a : b
^^^^^^^^^^^^^^^^^^^^^^ Only use parentheses for ternary expressions with complex conditions.
RUBY

expect_no_corrections
end

it 'registers an offense for defined with method chain in condition' do
expect_offense(<<~RUBY)
foo = (defined? bar.baz) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^^ Only use parentheses for ternary expressions with complex conditions.
RUBY

expect_no_corrections
end

it 'registers an offense for defined with class method in condition' do
expect_offense(<<~RUBY)
foo = (defined? Bar.baz) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^^ Only use parentheses for ternary expressions with complex conditions.
RUBY

expect_no_corrections
end

it 'registers an offense for defined with nested constant in condition' do
expect_offense(<<~RUBY)
foo = (defined? Bar::BAZ) ? a : b
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Only use parentheses for ternary expressions with complex conditions.
RUBY

expect_no_corrections
end
end

context 'with an assignment condition' do
Expand Down

0 comments on commit dd6944c

Please sign in to comment.