Module: SimpleCov::Formatter::AIFormatter::MarkdownBuilder::SnippetFormatter
- Extended by:
- T::Sig
- Included in:
- DeficitFormatter
- Defined in:
- lib/simplecov-ai/markdown_builder/snippet_formatter.rb
Overview
Handles extraction and formatting of source code snippets for the markdown digest.
Constant Summary collapse
- ESTIMATED_CHARS_PER_LINE =
Approximate maximum characters per line for truncation calculation
T.let(80, Integer)
- TRUNCATION_ELLIPSIS =
Suffix added to truncated snippets
T.let('...', String)
- OCCURRENCE_TEMPLATE =
Template for identical snippet occurrences indicator
T.let('(Occurrence %d of %d).', String)
Instance Method Summary collapse
- #build_occurrence_index(node, source_lines) ⇒ Object
- #byte_slice(line_text, start_col, end_col) ⇒ Object
- #calculate_occurrence(line_num, source_lines, node) ⇒ Object
- #extract_branch_text(branch, source_lines, columns) ⇒ Object
- #extract_inline_branch(branch, columns, source_lines) ⇒ Object
- #fetch_snippet_text(line_nums, source_lines) ⇒ Object
- #first_source_line(branch, source_lines) ⇒ Object
- #line_label(start_line, end_line) ⇒ Object
- #occurrence_index(node, source_lines) ⇒ Object
- #truncate_snippet(snippet_text, max_snippet_lines) ⇒ Object
Instance Method Details
#build_occurrence_index(node, source_lines) ⇒ Object
172 173 174 175 176 177 178 179 180 181 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 172 def build_occurrence_index(node, source_lines) index = T.let({}, T::Hash[String, T::Array[Integer]]) (node.start_line..node.end_line).each do |line_number| content = source_lines.at(line_number - 1)&.strip next if content.nil? || content.empty? (index[content] ||= []) << line_number end index end |
#byte_slice(line_text, start_col, end_col) ⇒ Object
42 43 44 45 46 47 48 49 50 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 42 def byte_slice(line_text, start_col, end_col) bytes = line_text.b return nil unless bytes.length >= end_col slice = bytes[start_col...end_col] return '' unless slice slice.force_encoding(line_text.encoding).scrub end |
#calculate_occurrence(line_num, source_lines, node) ⇒ Object
141 142 143 144 145 146 147 148 149 150 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 141 def calculate_occurrence(line_num, source_lines, node) return '' if node.nil? snippet = source_lines.at(line_num - 1).to_s.strip positions = occurrence_index(node, source_lines).fetch(snippet, []) return '' unless positions.size > 1 ordinal = T.must(positions.index(line_num)) + 1 Kernel.format(OCCURRENCE_TEMPLATE, ordinal, positions.size) end |
#extract_branch_text(branch, source_lines, columns) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 79 def extract_branch_text(branch, source_lines, columns) inline_text = extract_inline_branch(branch, columns, source_lines) return inline_text if inline_text fetch_snippet_text((branch.start_line..branch.end_line).to_a, source_lines) end |
#extract_inline_branch(branch, columns, source_lines) ⇒ Object
97 98 99 100 101 102 103 104 105 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 97 def extract_inline_branch(branch, columns, source_lines) return nil unless columns && branch.start_line == branch.end_line line_text = source_lines.at(branch.start_line - 1) return nil unless line_text start_col, end_col = columns byte_slice(line_text, start_col, end_col)&.strip end |
#fetch_snippet_text(line_nums, source_lines) ⇒ Object
25 26 27 28 29 30 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 25 def fetch_snippet_text(line_nums, source_lines) line_nums.select(&:positive?) .filter_map { |line_number| source_lines.at(line_number - 1)&.strip } .reject(&:empty?) .join(' ') end |
#first_source_line(branch, source_lines) ⇒ Object
113 114 115 116 117 118 119 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 113 def first_source_line(branch, source_lines) (branch.start_line..branch.end_line).each do |line_number| text = fetch_snippet_text([line_number], source_lines) return text unless text.empty? end '' end |
#line_label(start_line, end_line) ⇒ Object
127 128 129 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 127 def line_label(start_line, end_line) start_line == end_line ? start_line.to_s : "#{start_line}-#{end_line}" end |
#occurrence_index(node, source_lines) ⇒ Object
160 161 162 163 164 165 166 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 160 def occurrence_index(node, source_lines) cache = (@occurrence_index ||= T.let( {}.compare_by_identity, T.nilable(T::Hash[ASTResolver::SemanticNode, T::Hash[String, T::Array[Integer]]]) )) cache[node] ||= build_occurrence_index(node, source_lines) end |
#truncate_snippet(snippet_text, max_snippet_lines) ⇒ Object
58 59 60 61 62 63 64 65 |
# File 'lib/simplecov-ai/markdown_builder/snippet_formatter.rb', line 58 def truncate_snippet(snippet_text, max_snippet_lines) max_chars = max_snippet_lines * ESTIMATED_CHARS_PER_LINE if snippet_text.length > max_chars "#{snippet_text[0, max_chars]}#{TRUNCATION_ELLIPSIS}" else snippet_text end end |