diff --git a/lib/rubocop/cop/type_toolkit/prefer_not_nil.rb b/lib/rubocop/cop/type_toolkit/prefer_not_nil.rb index ff3968b..bd74e1d 100644 --- a/lib/rubocop/cop/type_toolkit/prefer_not_nil.rb +++ b/lib/rubocop/cop/type_toolkit/prefer_not_nil.rb @@ -81,6 +81,7 @@ def requires_parentheses?(argument) return false if argument.begin_type? if argument.is_a?(RuboCop::AST::SendNode) + return bracket_call_requires_parentheses?(argument) if argument.method?(:[]) return true if argument.operator_method? return true if argument.arguments? && !argument.parenthesized_call? end @@ -90,6 +91,12 @@ def requires_parentheses?(argument) KEYWORD_EXPRESSION_TYPES.include?(argument.type) end + + # `foo[bar]` and `foo.[](bar)` can be chained directly, but command-style `foo.[] bar` cannot. + #: (RuboCop::AST::SendNode) -> bool + def bracket_call_requires_parentheses?(argument) + argument.dot? && !argument.parenthesized_call? + end end end end diff --git a/spec/rubocop/cop/type_toolkit/prefer_not_nil_spec.rb b/spec/rubocop/cop/type_toolkit/prefer_not_nil_spec.rb index eb1cfce..ab06258 100644 --- a/spec/rubocop/cop/type_toolkit/prefer_not_nil_spec.rb +++ b/spec/rubocop/cop/type_toolkit/prefer_not_nil_spec.rb @@ -134,6 +134,23 @@ def explicit_super RUBY end + it "parenthesizes bracket method calls only when required" do + assert_offense(<<~RUBY) + bracketed = T.must(foo[bar]).foo + ^^^^^^^^^^^^^^^^ #{MSG} + explicit = T.must(foo.[](bar)).foo + ^^^^^^^^^^^^^^^^^^^ #{MSG} + command = T.must(foo.[] bar).foo + ^^^^^^^^^^^^^^^^^^ #{MSG} + RUBY + + assert_correction(<<~RUBY) + bracketed = foo[bar].not_nil!.foo + explicit = foo.[](bar).not_nil!.foo + command = (foo.[] bar).not_nil!.foo + RUBY + end + it "preserves comments in multiline calls" do assert_offense(<<~RUBY) value = T.must(