From d94264514c272d2c4d318fc7460a103f0b9f3203 Mon Sep 17 00:00:00 2001 From: Marc-Andre Lafortune Date: Tue, 28 Jul 2020 00:08:12 -0400 Subject: [PATCH] [Fixes #8276] Metrics/CyclomaticComplexity now discounts repeated uses of &. on same lvar receiver --- CHANGELOG.md | 1 + .../cop/metrics/cyclomatic_complexity.rb | 1 + lib/rubocop/cop/mixin/method_complexity.rb | 7 +++++-- .../cop/style/conditional_assignment.rb | 2 +- lib/rubocop/cop/style/if_inside_else.rb | 2 +- .../cop/metrics/cyclomatic_complexity_spec.rb | 18 ++++++++++++++++-- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac2456ce18c..e7f40938b25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ * [#8350](https://github.com/rubocop-hq/rubocop/pull/8350): Set default max line length to 120 for `Style/MultilineMethodSignature`. ([@koic][]) * [#8338](https://github.com/rubocop-hq/rubocop/pull/8338): **potentially breaking**. Config#for_department now returns only the config specified for that department; the 'Enabled' attribute is no longer calculated. ([@marcandre][]) * [#8037](https://github.com/rubocop-hq/rubocop/pull/8037): **(Breaking)** Cop `Metrics/AbcSize` now counts ||=, &&=, multiple assignments, for, yield, iterating blocks. `&.` now count as conditions too (unless repeated on the same variable). Default bumped from 15 to 16.5. ([@marcandre][]) +* [#8276](https://github.com/rubocop-hq/rubocop/issues/8276): Cop `Metrics/CyclomaticComplexity` not longer counts `&.` when repeated on the same variable. ([@marcandre][]) ## 0.88.0 (2020-07-13) diff --git a/lib/rubocop/cop/metrics/cyclomatic_complexity.rb b/lib/rubocop/cop/metrics/cyclomatic_complexity.rb index 48d1ae1f038..9065c378dc1 100644 --- a/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +++ b/lib/rubocop/cop/metrics/cyclomatic_complexity.rb @@ -42,6 +42,7 @@ class CyclomaticComplexity < Base def complexity_score_for(node) return 0 if iterating_block?(node) == false + return 0 if node.csend_type? && discount_for_repeated_csend?(node) 1 end diff --git a/lib/rubocop/cop/mixin/method_complexity.rb b/lib/rubocop/cop/mixin/method_complexity.rb index b4feca3bf97..c02b4d299e3 100644 --- a/lib/rubocop/cop/mixin/method_complexity.rb +++ b/lib/rubocop/cop/mixin/method_complexity.rb @@ -57,8 +57,11 @@ def check_complexity(node, method_name) end def complexity(body) - body.each_node(*self.class::COUNTED_NODES).reduce(1) do |score, node| - reset_on_lvasgn(node) if node.lvasgn_type? + body.each_node(:lvasgn, *self.class::COUNTED_NODES).reduce(1) do |score, node| + if node.lvasgn_type? + reset_on_lvasgn(node) + next score + end score + complexity_score_for(node) end end diff --git a/lib/rubocop/cop/style/conditional_assignment.rb b/lib/rubocop/cop/style/conditional_assignment.rb index 42e2488a5a0..baa1cf62618 100644 --- a/lib/rubocop/cop/style/conditional_assignment.rb +++ b/lib/rubocop/cop/style/conditional_assignment.rb @@ -67,7 +67,7 @@ def end_with_eq?(sym) private - def expand_elsif(node, elsif_branches = []) # rubocop:todo Metrics/CyclomaticComplexity + def expand_elsif(node, elsif_branches = []) return [] if node.nil? || !node.if_type? || !node.elsif? elsif_branches << node.if_branch diff --git a/lib/rubocop/cop/style/if_inside_else.rb b/lib/rubocop/cop/style/if_inside_else.rb index 419e78a9bdc..1750e860946 100644 --- a/lib/rubocop/cop/style/if_inside_else.rb +++ b/lib/rubocop/cop/style/if_inside_else.rb @@ -61,7 +61,7 @@ module Style class IfInsideElse < Cop MSG = 'Convert `if` nested inside `else` to `elsif`.' - def on_if(node) # rubocop:todo Metrics/CyclomaticComplexity + def on_if(node) return if node.ternary? || node.unless? else_branch = node.else_branch diff --git a/spec/rubocop/cop/metrics/cyclomatic_complexity_spec.rb b/spec/rubocop/cop/metrics/cyclomatic_complexity_spec.rb index 78a2faae411..57ed75c65cf 100644 --- a/spec/rubocop/cop/metrics/cyclomatic_complexity_spec.rb +++ b/spec/rubocop/cop/metrics/cyclomatic_complexity_spec.rb @@ -212,9 +212,23 @@ def method_name it 'registers an offense for &.' do expect_offense(<<~RUBY) def method_name - ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] - foo = nil + ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [3/1] foo&.bar + foo&.bar + end + RUBY + end + + it 'counts repeated &. on same untouched local variable as 1' do + expect_offense(<<~RUBY) + def method_name + ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [3/1] + var = 1 + var&.foo + var&.dont_count_me + var = 2 + var&.bar + var&.dont_count_me_eother end RUBY end