Class: Countless::Statistics
- Inherits:
-
Object
- Object
- Countless::Statistics
- Defined in:
- lib/countless/statistics.rb
Overview
The source code statistics displaying handler.
Heavily stolen from: bit.ly/3qpvgfu
Defined Under Namespace
Classes: Calculator
Instance Attribute Summary collapse
-
#dirs ⇒ Object
readonly
Make the extracted information accessible.
-
#statistics ⇒ Object
readonly
Make the extracted information accessible.
-
#total ⇒ Object
readonly
Make the extracted information accessible.
Instance Method Summary collapse
-
#calculate_code ⇒ Integer
Calculate the total lines of code.
-
#calculate_file_statistics(name, files) ⇒ Countless::Statistics::Calculator
Setup a new
Calculatorfor the given directory/pattern in order to extract the individual file statistics and calculate the sub-totals. -
#calculate_statistics ⇒ Hash{String => Hash{Symbol => Mixed}}
Calculate all statistics for the configured directories and pass back a named hash.
-
#calculate_tests ⇒ Integer
Calculate the total lines of testing code.
-
#calculate_total ⇒ Countless::Statistics::Calculator
Calculate the total statistics of all sub-statistics for the configured directories.
-
#code_test_stats_line ⇒ String
Return the final meta statistics line.
-
#initialize(*dirs) ⇒ Countless::Statistics
constructor
Initialize a new source code statistics displaying handler.
-
#to_s ⇒ String
Convert the code statistics to a formatted string buffer.
-
#to_table ⇒ Array<Array<String, Integer>, Symbol>
Convert the code statistics to a processable table structure.
Constructor Details
#initialize(*dirs) ⇒ Countless::Statistics
Initialize a new source code statistics displaying handler. When no configurations are passed in directly, we fallback to the configured statistics directories of the gem.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/countless/statistics.rb', line 17 def initialize(*dirs) base_path = Countless.configuration.base_path # Resolve the given directory configurations to actual files dirs = dirs.presence || Countless.statistic_directories @dirs = dirs.each_with_object([]) do |cur, memo| copy = cur.deep_dup copy[:files] = Array(copy[:files]) if copy[:pattern].is_a? Regexp copy[:files] += Dir[ File.join(copy[:dir] || base_path, '**/*') ].select { |path| File.file?(path) && copy[:pattern].match?(path) } else copy[:files] += Dir[copy[:pattern]] end copy[:files].uniq! memo << copy if copy[:files].present? end @statistics = calculate_statistics @total = calculate_total if @dirs.length > 1 end |
Instance Attribute Details
#dirs ⇒ Object (readonly)
Make the extracted information accessible
9 10 11 |
# File 'lib/countless/statistics.rb', line 9 def dirs @dirs end |
#statistics ⇒ Object (readonly)
Make the extracted information accessible
9 10 11 |
# File 'lib/countless/statistics.rb', line 9 def statistics @statistics end |
#total ⇒ Object (readonly)
Make the extracted information accessible
9 10 11 |
# File 'lib/countless/statistics.rb', line 9 def total @total end |
Instance Method Details
#calculate_code ⇒ Integer
Calculate the total lines of code.
90 91 92 93 |
# File 'lib/countless/statistics.rb', line 90 def calculate_code @statistics.values.reject { |conf| conf[:test] } .map { |conf| conf[:stats].code_lines }.sum end |
#calculate_file_statistics(name, files) ⇒ Countless::Statistics::Calculator
Setup a new Calculator for the given directory/pattern in order to extract the individual file statistics and calculate the sub-totals.
We match the pattern against the individual file name and the relative file path. This allows top-level only matches.
79 80 81 82 83 84 85 |
# File 'lib/countless/statistics.rb', line 79 def calculate_file_statistics(name, files) Calculator.new(name: name).tap do |calc| Cloc.stats(*files).each do |path, stats| calc.add_by_file_path(path, **stats) end end end |
#calculate_statistics ⇒ Hash{String => Hash{Symbol => Mixed}}
Calculate all statistics for the configured directories and pass back a named hash.
58 59 60 61 62 63 64 65 66 |
# File 'lib/countless/statistics.rb', line 58 def calculate_statistics @dirs.to_h do |conf| [ conf[:name], conf.merge(stats: calculate_file_statistics(conf[:name], conf[:files])) ] end end |
#calculate_tests ⇒ Integer
Calculate the total lines of testing code.
98 99 100 101 |
# File 'lib/countless/statistics.rb', line 98 def calculate_tests @statistics.values.select { |conf| conf[:test] } .map { |conf| conf[:stats].code_lines }.sum end |
#calculate_total ⇒ Countless::Statistics::Calculator
Calculate the total statistics of all sub-statistics for the configured directories.
46 47 48 49 50 51 |
# File 'lib/countless/statistics.rb', line 46 def calculate_total calculator = Calculator.new(name: 'Total') @statistics.values.each_with_object(calculator) do |conf, total| total.add(conf[:stats]) end end |
#code_test_stats_line ⇒ String
Return the final meta statistics line.
167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/countless/statistics.rb', line 167 def code_test_stats_line code = calculate_code tests = calculate_tests ratio = tests.fdiv(code) ratio = '0' if ratio.nan? res = [ "Code LOC: #{code}", "Test LOC: #{tests}", "Code to Test Ratio: 1:#{format('%.1f', ratio)}" ].join(' ' * 5) " #{res}" end |
#to_s ⇒ String
Convert the code statistics to a formatted string buffer.
rubocop:disable Metrics/MethodLength – because of the complex formatting
logic with fully dynamic columns widths
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/countless/statistics.rb', line 109 def to_s col_sizes = {} rows = to_table.map do |row| next row unless row.is_a?(Array) row = row.map(&:to_s) cols = row.map(&:length).each_with_index.map { |len, idx| [idx, [len]] } col_sizes.deep_merge!(cols.to_h) { |_, left, right| left + right } row end # Calculate the correct column sizes col_sizes = col_sizes.values.each_with_object([]) do |widths, memo| memo << (widths.max + 2) end # Enforce the correct column sizes per row splitter = ([0] + col_sizes + [0]).map { |size| '-' * size }.join('+') rows.each_with_object([]) do |row, memo| next memo << splitter if row == :splitter next memo << row if row.is_a?(String) cols = row.each_with_index.map do |col, idx| meth = idx.zero? ? :ljust : :rjust col.send(meth, col_sizes[idx] - 2) end memo << "| #{cols.join(' | ')} |" end.join("\n") end |
#to_table ⇒ Array<Array<String, Integer>, Symbol>
Convert the code statistics to a processable table structure. Each element in the resulting array is a single line, while array elements reflect columns. The special :splitter row value will be converted later by #to_s.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/countless/statistics.rb', line 146 def to_table table = [ :splitter, %w[Name Lines LOC Comments Classes Methods M/C LOC/M], :splitter ] @statistics.each_value { |conf| table << conf[:stats].to_h.values } table << :splitter if @total table << @total.to_h.values table << :splitter end table << code_test_stats_line table end |