Class: RuboCop::Cop::Metrics::Utils::AbcSizeCalculator

Inherits:
Object
  • Object
show all
Includes:
IteratingBlock, RepeatedCsendDiscount
Defined in:
lib/rubocop/cop/metrics/utils/abc_size_calculator.rb

Overview

> ABC is .. a software size metric .. computed by counting the number > of assignments, branches and conditions for a section of code. > c2.com/cgi/wiki?AbcMetric

We separate the calculator from the cop so that the calculation, the formula itself, is easier to test.

Constant Summary

Constants included from IteratingBlock

IteratingBlock::KNOWN_ITERATING_METHODS

Class Method Summary collapse

Instance Method Summary collapse

Methods included from RepeatedCsendDiscount

#discount_for_repeated_csend?, #reset_on_lvasgn, #reset_repeated_csend

Methods included from IteratingBlock

#block_method_name, #iterating_block?, #iterating_method?

Constructor Details

#initialize(node) ⇒ AbcSizeCalculator

Returns a new instance of AbcSizeCalculator.


37
38
39
40
41
42
43
# File 'lib/rubocop/cop/metrics/utils/abc_size_calculator.rb', line 37

def initialize(node)
  @assignment = 0
  @branch = 0
  @condition = 0
  @node = node
  reset_repeated_csend
end

Class Method Details

.calculate(node, discount_repeated_attributes: false) ⇒ Object


28
29
30
# File 'lib/rubocop/cop/metrics/utils/abc_size_calculator.rb', line 28

def self.calculate(node, discount_repeated_attributes: false)
  new(node, discount_repeated_attributes: discount_repeated_attributes).calculate
end

Instance Method Details

#calculateObject


45
46
47
48
49
50
51
52
53
54
# File 'lib/rubocop/cop/metrics/utils/abc_size_calculator.rb', line 45

def calculate
  visit_depth_last(@node) do |child|
    calculate_node(child)
  end

  [
    Math.sqrt(@assignment**2 + @branch**2 + @condition**2).round(2),
    "<#{@assignment}, #{@branch}, #{@condition}>"
  ]
end

#else_branch?(node) ⇒ Boolean

Returns:

  • (Boolean)

70
71
72
73
74
# File 'lib/rubocop/cop/metrics/utils/abc_size_calculator.rb', line 70

def else_branch?(node)
  %i[case if].include?(node.type) &&
    node.else? &&
    node.loc.else.is?('else')
end

#evaluate_branch_nodes(node) ⇒ Object


56
57
58
59
60
61
62
63
# File 'lib/rubocop/cop/metrics/utils/abc_size_calculator.rb', line 56

def evaluate_branch_nodes(node)
  if node.comparison_method?
    @condition += 1
  else
    @branch += 1
    @condition += 1 if node.csend_type? && !discount_for_repeated_csend?(node)
  end
end

#evaluate_condition_node(node) ⇒ Object


65
66
67
68
# File 'lib/rubocop/cop/metrics/utils/abc_size_calculator.rb', line 65

def evaluate_condition_node(node)
  @condition += 1 if else_branch?(node)
  @condition += 1
end