Class: Coverband::Utils::SourceFile

Inherits:
Object
  • Object
show all
Defined in:
lib/coverband/utils/source_file.rb

Defined Under Namespace

Classes: Line

Constant Summary collapse

NOT_AVAILABLE =
"not available"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename, file_data) ⇒ SourceFile

Returns a new instance of SourceFile.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/coverband/utils/source_file.rb', line 99

def initialize(filename, file_data)
  @filename = filename
  @runtime_relavant_lines = nil
  if file_data.is_a?(Hash)
    @coverage = file_data["data"]
    @coverage_posted = file_data["timedata"] || [] # NOTE: only implement timedata for HashRedisStore
    @first_updated_at = @last_updated_at = NOT_AVAILABLE
    @first_updated_at = Time.at(file_data["first_updated_at"]) if file_data["first_updated_at"]
    @last_updated_at = Time.at(file_data["last_updated_at"]) if file_data["last_updated_at"]
    @never_loaded = file_data["never_loaded"] || false
  else
    # TODO: Deprecate this code path this was backwards compatibility from 3-4
    @coverage = file_data
    @first_updated_at = NOT_AVAILABLE
    @last_updated_at = NOT_AVAILABLE
  end
end

Instance Attribute Details

#coverageObject (readonly)

The array of coverage data received from the Coverage.result



87
88
89
# File 'lib/coverband/utils/source_file.rb', line 87

def coverage
  @coverage
end

#coverage_postedObject (readonly)

The array of coverage timedata received from the Coverage.result



89
90
91
# File 'lib/coverband/utils/source_file.rb', line 89

def coverage_posted
  @coverage_posted
end

#filenameObject (readonly)

The full path to this source file (e.g. /User/colszowka/projects/simplecov/lib/simplecov/source_file.rb)



85
86
87
# File 'lib/coverband/utils/source_file.rb', line 85

def filename
  @filename
end

#first_updated_atObject (readonly)

the date this version of the file first started to record coverage



92
93
94
# File 'lib/coverband/utils/source_file.rb', line 92

def first_updated_at
  @first_updated_at
end

#last_updated_atObject (readonly)

the date this version of the file last saw any coverage activity



94
95
96
# File 'lib/coverband/utils/source_file.rb', line 94

def last_updated_at
  @last_updated_at
end

#never_loadedObject (readonly)

meta data that the file was never loaded during boot or runtime



96
97
98
# File 'lib/coverband/utils/source_file.rb', line 96

def never_loaded
  @never_loaded
end

Instance Method Details

#build_linesObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/coverband/utils/source_file.rb', line 144

def build_lines
  coverage_exceeding_source_warn if coverage.size > src.size

  lines = src.map.with_index(1) { |src, i|
    Coverband::Utils::SourceFile::Line.new(
      src,
      i,
      never_loaded ? 0 : coverage[i - 1],
      (never_loaded || !coverage_posted.is_a?(Array)) ? nil : coverage_posted[i - 1]
    )
  }

  process_skipped_lines(lines)
end

#coverage_exceeding_source_warnObject

Warning to identify condition from Issue #56



160
161
162
# File 'lib/coverband/utils/source_file.rb', line 160

def coverage_exceeding_source_warn
  warn "Warning: coverage data from Coverage [#{coverage.size}] exceeds line count in #{filename} [#{src.size}]"
end

#covered_linesObject

Returns all covered lines as SimpleCov::SourceFile::Line



204
205
206
# File 'lib/coverband/utils/source_file.rb', line 204

def covered_lines
  @covered_lines ||= lines.select(&:covered?)
end

#covered_lines_countObject



208
209
210
# File 'lib/coverband/utils/source_file.rb', line 208

def covered_lines_count
  covered_lines&.count
end

#covered_percentObject

The coverage for this file in percent. 0 if the file has no relevant lines



170
171
172
173
174
175
176
177
# File 'lib/coverband/utils/source_file.rb', line 170

def covered_percent
  return 100.0 if no_lines?

  return 0.0 if relevant_lines.zero?

  # handle edge case where runtime in dev can go over 100%
  [Float(covered_lines.size * 100.0 / relevant_lines.to_f), 100.0].min&.round(2)
end

#covered_strengthObject



183
184
185
186
187
# File 'lib/coverband/utils/source_file.rb', line 183

def covered_strength
  return 0.0 if relevant_lines.zero?

  round_float(lines_strength / relevant_lines.to_f, 1)
end

#formatted_covered_percentObject



179
180
181
# File 'lib/coverband/utils/source_file.rb', line 179

def formatted_covered_percent
  covered_percent&.round(2)
end

#line(number) ⇒ Object

Access SimpleCov::SourceFile::Line source lines by line number



165
166
167
# File 'lib/coverband/utils/source_file.rb', line 165

def line(number)
  lines[number - 1]
end

#line_coverage(index) ⇒ Object



212
213
214
# File 'lib/coverband/utils/source_file.rb', line 212

def line_coverage(index)
  lines[index]&.coverage
end

#line_coverage_posted(index) ⇒ Object



216
217
218
# File 'lib/coverband/utils/source_file.rb', line 216

def line_coverage_posted(index)
  lines[index]&.coverage_posted
end

#linesObject Also known as: source_lines

Returns all source lines for this file as instances of SimpleCov::SourceFile::Line, and thus including coverage data. Aliased as :source_lines



139
140
141
# File 'lib/coverband/utils/source_file.rb', line 139

def lines
  @lines ||= build_lines
end

#lines_of_codeObject

Returns the number of relevant lines (covered + missed)



238
239
240
# File 'lib/coverband/utils/source_file.rb', line 238

def lines_of_code
  covered_lines.size + missed_lines.size
end

#lines_strengthObject



193
194
195
196
197
# File 'lib/coverband/utils/source_file.rb', line 193

def lines_strength
  lines.sum do |line|
    line.coverage || 0
  end
end

#missed_linesObject

Returns all lines that should have been, but were not covered as instances of SimpleCov::SourceFile::Line



222
223
224
# File 'lib/coverband/utils/source_file.rb', line 222

def missed_lines
  @missed_lines ||= lines.select(&:missed?)
end

#never_linesObject

Returns all lines that are not relevant for coverage as SimpleCov::SourceFile::Line instances



228
229
230
# File 'lib/coverband/utils/source_file.rb', line 228

def never_lines
  @never_lines ||= lines.select(&:never?)
end

#no_lines?Boolean

Returns:

  • (Boolean)


189
190
191
# File 'lib/coverband/utils/source_file.rb', line 189

def no_lines?
  lines.length.zero? || (lines.length == never_lines.size)
end

#process_skipped_lines(lines) ⇒ Object

Will go through all source files and mark lines that are wrapped within # :nocov: comment blocks as skipped.



244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/coverband/utils/source_file.rb', line 244

def process_skipped_lines(lines)
  skipping = false

  lines.each do |line|
    if Coverband::Utils::LinesClassifier.no_cov_line?(line.src)
      skipping = !skipping
      line.skipped!
    elsif skipping
      line.skipped!
    end
  end
end

#project_filenameObject

The path to this source file relative to the projects directory



125
126
127
# File 'lib/coverband/utils/source_file.rb', line 125

def project_filename
  @filename.sub(/^#{Coverband.configuration.root}/, "")
end

#relative_pathObject



264
265
266
# File 'lib/coverband/utils/source_file.rb', line 264

def relative_path
  RelativeFileConverter.convert(filename)
end

#relevant_linesObject



199
200
201
# File 'lib/coverband/utils/source_file.rb', line 199

def relevant_lines
  @runtime_relavant_lines || (lines.size - never_lines.size - skipped_lines.size)
end

#runtime_relavant_calculations(runtime_relavant_lines) ⇒ Object



117
118
119
120
121
122
# File 'lib/coverband/utils/source_file.rb', line 117

def runtime_relavant_calculations(runtime_relavant_lines)
  @runtime_relavant_lines = runtime_relavant_lines
  yield self
ensure
  @runtime_relavant_lines = nil
end

#short_nameObject

a bug that existed in simplecov was not checking that root was at the start of the file name I had previously patched this in my local Rails app



260
261
262
# File 'lib/coverband/utils/source_file.rb', line 260

def short_name
  filename.delete_prefix("#{Coverband.configuration.root}/")
end

#skipped_linesObject

Returns all lines that were skipped as SimpleCov::SourceFile::Line instances



233
234
235
# File 'lib/coverband/utils/source_file.rb', line 233

def skipped_lines
  @skipped_lines ||= lines.select(&:skipped?)
end

#srcObject Also known as: source

The source code for this file. Aliased as :source



130
131
132
133
134
# File 'lib/coverband/utils/source_file.rb', line 130

def src
  # We intentionally read source code lazily to
  # suppress reading unused source code.
  @src ||= File.open(filename, "rb", &:readlines)
end