Class: SimpleCov::LinesClassifier

Inherits:
Object
  • Object
show all
Defined in:
lib/simplecov/lines_classifier.rb

Overview

Classifies whether lines are relevant for code coverage analysis. Comments, whitespace lines, and disabled blocks are considered not relevant.

Defined Under Namespace

Classes: SkipState

Constant Summary collapse

RELEVANT =
0
NOT_RELEVANT =
nil
WHITESPACE_LINE =
/^\s*$/
COMMENT_LINE =
/^\s*#/
WHITESPACE_OR_COMMENT_LINE =
Regexp.union(WHITESPACE_LINE, COMMENT_LINE)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.no_cov_lineObject

The leading ^(\s*)# anchor is load-bearing beyond matching the marker: classify_line only reaches this for lines that already passed whitespace_line?, which is sound only while every marker is also a comment. Loosening this to match a trailing x = 1 # :nocov: would stop the toggle firing. lines_classifier_spec.rb pins the implication.

The /o flag freezes the interpolated nocov token at this process's first classification; a nocov_token configured after coverage has classified a file would be silently ignored. Sound today because configuration always precedes classification.



26
27
28
# File 'lib/simplecov/lines_classifier.rb', line 26

def self.no_cov_line
  /^(\s*)#(\s*)(:#{SimpleCov.current_nocov_token}:)/o
end

.no_cov_line?(line) ⇒ Boolean

A marker is itself a comment, so the cheap whitespace-or-comment test gates the token match: a line of real code cannot be a marker, and no longer pays to be checked against one. That matters because this runs per line of every tracked-but-unloaded file, once in every process of a parallel run.

Returns:



34
35
36
37
38
# File 'lib/simplecov/lines_classifier.rb', line 34

def self.no_cov_line?(line)
  no_cov_line.match?(line)
rescue ArgumentError
  false
end

.whitespace_line?(line) ⇒ Boolean

Returns:



40
41
42
43
44
# File 'lib/simplecov/lines_classifier.rb', line 40

def self.whitespace_line?(line)
  WHITESPACE_OR_COMMENT_LINE.match?(line)
rescue ArgumentError
  false
end

Instance Method Details

#classify(lines) ⇒ Object

The skip state lives in a one-slot box owned by this call rather than in an ivar, so one classifier instance can serve concurrent classify calls without the toggles interleaving.



63
64
65
66
67
68
69
70
71
# File 'lib/simplecov/lines_classifier.rb', line 63

def classify(lines)
  lines = lines.to_a
  directive_disabled = directive_disabled_line_set(lines)
  skip_state = SkipState.new

  lines.map.with_index(1) do |line, line_number|
    classify_line(line, line_number, directive_disabled, skip_state)
  end
end