Class: SimpleCov::Formatter::AIFormatter::MarkdownBuilder::DeficitGrouper

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/simplecov-ai/markdown_builder/deficit_grouper.rb

Overview

Groups missed lines and branches into DeficitGroup objects based on AST semantic boundaries.

Constant Summary collapse

FALLBACK_LINE_NAME =

Fallback identifier format for unassociated lines

T.let('Line %d', String)
FALLBACK_BRANCH_NAME =

Fallback identifier format for unassociated branches

T.let('Lines %d-%d', String)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nodes) ⇒ DeficitGrouper

Returns a new instance of DeficitGrouper.



21
22
23
24
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 21

def initialize(nodes)
  @nodes = nodes
  @node_deficits = T.let({}, T::Hash[String, DeficitGroup])
end

Instance Attribute Details

#node_deficitsObject (readonly)

Returns the value of attribute node_deficits.



18
19
20
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 18

def node_deficits
  @node_deficits
end

Class Method Details

.build(file, nodes) ⇒ Object



30
31
32
33
34
35
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 30

def self.build(file, nodes)
  grouper = new(nodes)
  grouper.group_missed_lines(file)
  grouper.group_missed_branches(file)
  grouper.sort_deficits
end

Instance Method Details

#add_missed_branch(branch) ⇒ Object



77
78
79
80
81
82
83
84
85
86
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 77

def add_missed_branch(branch)
  start_line = branch.start_line
  end_line = branch.end_line
  matched_node = @nodes.reverse.find do |node|
    start_line >= node.start_line && end_line <= node.end_line
  end
  node_name = matched_node ? matched_node.name : format(FALLBACK_BRANCH_NAME, start_line, end_line)
  @node_deficits[node_name] ||= DeficitGroup.new(semantic_node: matched_node)
  T.must(@node_deficits[node_name]).branches << branch
end

#add_missed_line(line) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 59

def add_missed_line(line)
  line_num = line.line_number
  matched_node = @nodes.reverse.find { |node| line_num.between?(node.start_line, node.end_line) }
  node_name = matched_node ? matched_node.name : format(FALLBACK_LINE_NAME, line_num)
  @node_deficits[node_name] ||= DeficitGroup.new(semantic_node: matched_node)
  T.must(@node_deficits[node_name]).lines << line
end

#group_missed_branches(file) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 68

def group_missed_branches(file)
  return unless file.respond_to?(:branches) && file.branches.any?

  file.missed_branches.each do |branch|
    add_missed_branch(branch)
  end
end

#group_missed_lines(file) ⇒ Object



52
53
54
55
56
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 52

def group_missed_lines(file)
  file.missed_lines.each do |line|
    add_missed_line(line)
  end
end

#sort_deficitsObject



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/simplecov-ai/markdown_builder/deficit_grouper.rb', line 38

def sort_deficits
  T.let(
    @node_deficits.sort_by do |node_name, deficit_group|
      if (semantic_node = deficit_group.semantic_node)
        semantic_node.start_line
      else
        node_name.match(/\d+/)&.to_s&.to_i || Float::INFINITY
      end
    end.to_h,
    T::Hash[String, DeficitGroup]
  )
end