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 :nocov: token blocks, are considered not relevant.

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

Returns:

  • (Boolean)


30
31
32
33
34
35
# File 'lib/simplecov/lines_classifier.rb', line 30

def self.no_cov_line?(line)
  no_cov_line.match?(line)
rescue ArgumentError
  # E.g., line contains an invalid byte sequence in UTF-8
  false
end

.whitespace_line?(line) ⇒ Boolean

Returns:

  • (Boolean)


37
38
39
40
41
42
# File 'lib/simplecov/lines_classifier.rb', line 37

def self.whitespace_line?(line)
  WHITESPACE_OR_COMMENT_LINE.match?(line)
rescue ArgumentError
  # E.g., line contains an invalid byte sequence in UTF-8
  false
end

Instance Method Details

#classify(lines) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/simplecov/lines_classifier.rb', line 44

def classify(lines)
  lines = lines.to_a
  directive_disabled = directive_disabled_line_set(lines)
  # The `:nocov:` skip state lives in a one-slot box owned by this
  # call, not in an ivar, so one classifier instance can serve
  # concurrent `classify` calls without the toggles interleaving.
  skip_state = [false]

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