Class: MetricABC

Inherits:
Object
  • Object
show all
Defined in:
lib/metric_abc.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_name) ⇒ MetricABC

Returns a new instance of MetricABC.


7
8
9
10
11
12
13
14
15
16
# File 'lib/metric_abc.rb', line 7

def initialize(file_name)
  File.open(file_name, "r") do |f|
    @ast = Ripper::SexpBuilder.new(f.read).parse
  end  
  return if @ast.empty?
  @complexity = {}
  @nesting = [file_name]
  process_ast(@ast)
  pp @ast if ENV["DEBUG"]
end

Instance Attribute Details

#astObject

Returns the value of attribute ast


5
6
7
# File 'lib/metric_abc.rb', line 5

def ast
  @ast
end

#complexityObject

Returns the value of attribute complexity


5
6
7
# File 'lib/metric_abc.rb', line 5

def complexity
  @complexity
end

Instance Method Details

#calculate_abc(method_node) ⇒ Object


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

def calculate_abc(method_node)
  a = calculate_assignments(method_node)
  b = calculate_branches(method_node)
  c = calculate_conditions(method_node)
  abc = Math.sqrt(a**2 + b**2 + c**2).round
  abc
end

#calculate_assignments(node) ⇒ Object


44
45
46
# File 'lib/metric_abc.rb', line 44

def calculate_assignments(node)
  node.flatten.select{|n| [:assign, :opassign].include?(n)}.size.to_f
end

#calculate_branches(node) ⇒ Object


48
49
50
# File 'lib/metric_abc.rb', line 48

def calculate_branches(node)
  node.flatten.select{|n| [:call, :fcall, :brace_block, :do_block].include?(n)}.size.to_f + 1.0
end

#calculate_conditions(node, sum = 0) ⇒ Object


52
53
54
# File 'lib/metric_abc.rb', line 52

def calculate_conditions(node, sum=0)
  node.flatten.select{|n| [:==, :===, :"<>", :"<=", :">=", :"=~", :>, :<, :else, :"<=>"].include?(n)}.size.to_f 
end

#process_ast(node) ⇒ Object


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/metric_abc.rb', line 18

def process_ast(node)
  backup_nesting = @nesting.clone
   
  if node[0] == :def
    @nesting << node[1][1]
    @complexity[@nesting.join(" > ")] = calculate_abc(node)
  elsif node[0] == :class || node[0] == :module
    if node[1][1][1].is_a? Symbol
      @nesting << node[1][1][1]
    else
      @nesting << node[1][-1][1]
    end
  end  

  node[1..-1].each { |n| process_ast(n) if n } if node.is_a? Array
  @nesting = backup_nesting
end