Class: AbcSizeVisualizer::AbcSizeCalculator

Inherits:
Object
  • Object
show all
Includes:
RuboCop::Cop::Metrics::Utils::IteratingBlock, RuboCop::Cop::Metrics::Utils::RepeatedAttributeDiscount, RuboCop::Cop::Metrics::Utils::RepeatedCsendDiscount
Defined in:
lib/abc_size_visualizer/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.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node) ⇒ AbcSizeCalculator

Returns a new instance of AbcSizeCalculator.



36
37
38
39
40
41
42
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 36

def initialize(node)
  @assignment = IntegerOnLocation.new
  @branch = IntegerOnLocation.new
  @condition = IntegerOnLocation.new
  @node = node
  reset_repeated_csend
end

Instance Attribute Details

#assignmentObject (readonly)

Returns the value of attribute assignment.



34
35
36
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 34

def assignment
  @assignment
end

#branchObject (readonly)

Returns the value of attribute branch.



34
35
36
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 34

def branch
  @branch
end

#conditionObject (readonly)

Returns the value of attribute condition.



34
35
36
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 34

def condition
  @condition
end

Class Method Details

.calculate(node, discount_repeated_attributes: false) ⇒ Object



25
26
27
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 25

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

Instance Method Details

#abc_by_line_numObject



44
45
46
47
48
49
50
51
52
53
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 44

def 
  @abc_by_line_num ||= [@assignment, @branch, @condition].map(&:line_nums).flatten.map do |line_num|
    [
      line_num,
      {assignment: @assignment, branch: @branch, condition: @condition}.transform_values do
        _1.value_at(line_num:) || 0
      end
    ]
  end.to_h
end

#calculateObject



55
56
57
58
59
60
61
62
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 55

def calculate
  visit_depth_last(@node) { |child| calculate_node(child) }

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

#else_branch?(node) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 78

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

#evaluate_branch_nodes(node) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 64

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

#evaluate_condition_node(node) ⇒ Object



73
74
75
76
# File 'lib/abc_size_visualizer/abc_size_calculator.rb', line 73

def evaluate_condition_node(node)
  @condition.add(node, 1) if else_branch?(node)
  @condition.add(node, 1)
end