Class: McCabe::Analyzer

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

Constant Summary collapse

BRANCH_TYPES =
[:if, :while, :until, :for, :when, :and, :or]
ENUMERABLE_METHODS =
Enumerable.instance_methods + [:each]

Class Method Summary collapse

Class Method Details

.analyze(ast) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/mccabe/analyzer.rb', line 8

def self.analyze(ast)
  results = {}
  McCabe::Parser.collect_methods(ast).each do |name, method|
    results[name] = {line: method[:line], complexity: complexity(method[:body])}
  end
  results
end

.block_complexity(block_node) ⇒ Object



32
33
34
35
36
# File 'lib/mccabe/analyzer.rb', line 32

def self.block_complexity(block_node)
  sent_method = block_node.children[0]
  sent_method.children.length == 2 &&
    ENUMERABLE_METHODS.include?(sent_method.children[1]) ? 1 : 0
end

.complexity(ast) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/mccabe/analyzer.rb', line 16

def self.complexity(ast)
  nodes, complexity = [ast], 0
  until nodes.empty?
    node = nodes.shift
    if BRANCH_TYPES.include?(node.type)
      complexity += 1
    elsif node.type == :block
      complexity += block_complexity node
    elsif node.type == :send
      complexity += send_complexity node
    end
    nodes += node.children.select { |child| child.is_a? ::Parser::AST::Node }
  end
  complexity
end

.send_complexity(send_node) ⇒ Object



38
39
40
41
42
# File 'lib/mccabe/analyzer.rb', line 38

def self.send_complexity(send_node)
  send_node.children.length >= 3 &&
    send_node.children[2].type == :block_pass &&
    ENUMERABLE_METHODS.include?(send_node.children[1]) ? 1 : 0
end