simplecov 0.6.4 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +378 -12
  3. data/CONTRIBUTING.md +51 -0
  4. data/ISSUE_TEMPLATE.md +23 -0
  5. data/LICENSE +1 -1
  6. data/README.md +456 -252
  7. data/doc/alternate-formatters.md +56 -0
  8. data/doc/commercial-services.md +20 -0
  9. data/doc/editor-integration.md +18 -0
  10. data/lib/simplecov.rb +223 -44
  11. data/lib/simplecov/command_guesser.rb +47 -35
  12. data/lib/simplecov/configuration.rb +281 -191
  13. data/lib/simplecov/defaults.rb +38 -43
  14. data/lib/simplecov/exit_codes.rb +10 -0
  15. data/lib/simplecov/file_list.rb +51 -34
  16. data/lib/simplecov/filter.rb +50 -3
  17. data/lib/simplecov/formatter.rb +4 -1
  18. data/lib/simplecov/formatter/multi_formatter.rb +34 -0
  19. data/lib/simplecov/formatter/simple_formatter.rb +18 -12
  20. data/lib/simplecov/jruby_fix.rb +44 -0
  21. data/lib/simplecov/last_run.rb +26 -0
  22. data/lib/simplecov/lines_classifier.rb +48 -0
  23. data/lib/simplecov/load_global_config.rb +8 -0
  24. data/lib/simplecov/no_defaults.rb +4 -0
  25. data/lib/simplecov/profiles.rb +33 -0
  26. data/lib/simplecov/profiles/bundler_filter.rb +5 -0
  27. data/lib/simplecov/profiles/hidden_filter.rb +5 -0
  28. data/lib/simplecov/profiles/rails.rb +18 -0
  29. data/lib/simplecov/profiles/root_filter.rb +10 -0
  30. data/lib/simplecov/profiles/test_frameworks.rb +8 -0
  31. data/lib/simplecov/railtie.rb +3 -1
  32. data/lib/simplecov/railties/tasks.rake +9 -7
  33. data/lib/simplecov/raw_coverage.rb +41 -0
  34. data/lib/simplecov/result.rb +17 -55
  35. data/lib/simplecov/result_merger.rb +100 -67
  36. data/lib/simplecov/source_file.rb +82 -67
  37. data/lib/simplecov/version.rb +4 -2
  38. metadata +153 -222
  39. data/.gitignore +0 -31
  40. data/.travis.yml +0 -15
  41. data/Appraisals +0 -8
  42. data/Gemfile +0 -5
  43. data/Rakefile +0 -19
  44. data/cucumber.yml +0 -13
  45. data/features/config_adapters.feature +0 -44
  46. data/features/config_autoload.feature +0 -46
  47. data/features/config_command_name.feature +0 -33
  48. data/features/config_coverage_dir.feature +0 -20
  49. data/features/config_deactivate_merging.feature +0 -42
  50. data/features/config_merge_timeout.feature +0 -39
  51. data/features/config_nocov_token.feature +0 -79
  52. data/features/config_project_name.feature +0 -27
  53. data/features/config_styles.feature +0 -93
  54. data/features/cucumber_basic.feature +0 -29
  55. data/features/merging_test_unit_and_rspec.feature +0 -44
  56. data/features/rspec_basic.feature +0 -31
  57. data/features/rspec_fails_on_initialization.feature +0 -14
  58. data/features/rspec_groups_and_filters_basic.feature +0 -29
  59. data/features/rspec_groups_and_filters_complex.feature +0 -35
  60. data/features/rspec_groups_using_filter_class.feature +0 -40
  61. data/features/rspec_without_simplecov.feature +0 -20
  62. data/features/skipping_code_blocks_manually.feature +0 -70
  63. data/features/step_definitions/html_steps.rb +0 -45
  64. data/features/step_definitions/simplecov_steps.rb +0 -66
  65. data/features/step_definitions/transformers.rb +0 -13
  66. data/features/step_definitions/web_steps.rb +0 -64
  67. data/features/support/env.rb +0 -26
  68. data/features/test_unit_basic.feature +0 -34
  69. data/features/test_unit_groups_and_filters_basic.feature +0 -29
  70. data/features/test_unit_groups_and_filters_complex.feature +0 -35
  71. data/features/test_unit_groups_using_filter_class.feature +0 -40
  72. data/features/test_unit_without_simplecov.feature +0 -20
  73. data/features/unicode_compatiblity.feature +0 -67
  74. data/gemfiles/multi_json-legacy.gemfile +0 -7
  75. data/gemfiles/multi_json-legacy.gemfile.lock +0 -85
  76. data/gemfiles/multi_json-new.gemfile +0 -7
  77. data/gemfiles/multi_json-new.gemfile.lock +0 -85
  78. data/lib/simplecov/adapters.rb +0 -29
  79. data/lib/simplecov/merge_helpers.rb +0 -39
  80. data/simplecov.gemspec +0 -29
  81. data/test/faked_project/Gemfile +0 -6
  82. data/test/faked_project/Rakefile +0 -8
  83. data/test/faked_project/cucumber.yml +0 -13
  84. data/test/faked_project/features/step_definitions/my_steps.rb +0 -23
  85. data/test/faked_project/features/support/env.rb +0 -12
  86. data/test/faked_project/features/test_stuff.feature +0 -6
  87. data/test/faked_project/lib/faked_project.rb +0 -11
  88. data/test/faked_project/lib/faked_project/framework_specific.rb +0 -18
  89. data/test/faked_project/lib/faked_project/meta_magic.rb +0 -24
  90. data/test/faked_project/lib/faked_project/some_class.rb +0 -29
  91. data/test/faked_project/spec/faked_spec.rb +0 -11
  92. data/test/faked_project/spec/meta_magic_spec.rb +0 -10
  93. data/test/faked_project/spec/some_class_spec.rb +0 -10
  94. data/test/faked_project/spec/spec_helper.rb +0 -15
  95. data/test/faked_project/test/faked_test.rb +0 -11
  96. data/test/faked_project/test/meta_magic_test.rb +0 -13
  97. data/test/faked_project/test/some_class_test.rb +0 -15
  98. data/test/faked_project/test/test_helper.rb +0 -16
  99. data/test/fixtures/app/controllers/sample_controller.rb +0 -10
  100. data/test/fixtures/app/models/user.rb +0 -10
  101. data/test/fixtures/deleted_source_sample.rb +0 -15
  102. data/test/fixtures/frameworks/rspec_bad.rb +0 -9
  103. data/test/fixtures/frameworks/rspec_good.rb +0 -9
  104. data/test/fixtures/frameworks/testunit_bad.rb +0 -9
  105. data/test/fixtures/frameworks/testunit_good.rb +0 -9
  106. data/test/fixtures/iso-8859.rb +0 -3
  107. data/test/fixtures/resultset1.rb +0 -4
  108. data/test/fixtures/resultset2.rb +0 -5
  109. data/test/fixtures/sample.rb +0 -16
  110. data/test/fixtures/utf-8.rb +0 -3
  111. data/test/helper.rb +0 -35
  112. data/test/shoulda_macros.rb +0 -29
  113. data/test/test_1_8_fallbacks.rb +0 -33
  114. data/test/test_command_guesser.rb +0 -21
  115. data/test/test_deleted_source.rb +0 -16
  116. data/test/test_file_list.rb +0 -24
  117. data/test/test_filters.rb +0 -80
  118. data/test/test_merge_helpers.rb +0 -107
  119. data/test/test_result.rb +0 -147
  120. data/test/test_return_codes.rb +0 -39
  121. data/test/test_source_file.rb +0 -95
  122. data/test/test_source_file_line.rb +0 -110
@@ -1,57 +1,52 @@
1
- # Load default formatter gem
2
- require 'simplecov-html'
3
-
4
- SimpleCov.adapters.define 'root_filter' do
5
- # Exclude all files outside of simplecov root
6
- add_filter do |src|
7
- !(src.filename =~ /^#{SimpleCov.root}/)
8
- end
9
- end
10
-
11
- SimpleCov.adapters.define 'test_frameworks' do
12
- add_filter '/test/'
13
- add_filter '/features/'
14
- add_filter '/spec/'
15
- add_filter '/autotest/'
16
- end
17
-
18
- SimpleCov.adapters.define 'rails' do
19
- load_adapter 'test_frameworks'
20
-
21
- add_filter '/config/'
22
- add_filter '/db/'
23
- add_filter '/vendor/bundle/'
1
+ # frozen_string_literal: true
24
2
 
25
- add_group 'Controllers', 'app/controllers'
26
- add_group 'Models', 'app/models'
27
- add_group 'Mailers', 'app/mailers'
28
- add_group 'Helpers', 'app/helpers'
29
- add_group 'Libraries', 'lib'
30
- add_group 'Plugins', 'vendor/plugins'
31
- end
3
+ # Load default formatter gem
4
+ require "simplecov-html"
5
+ require "pathname"
6
+ require "simplecov/profiles/root_filter"
7
+ require "simplecov/profiles/test_frameworks"
8
+ require "simplecov/profiles/bundler_filter"
9
+ require "simplecov/profiles/hidden_filter"
10
+ require "simplecov/profiles/rails"
32
11
 
33
12
  # Default configuration
34
13
  SimpleCov.configure do
35
14
  formatter SimpleCov::Formatter::HTMLFormatter
15
+ load_profile "bundler_filter"
16
+ load_profile "hidden_filter"
36
17
  # Exclude files outside of SimpleCov.root
37
- load_adapter 'root_filter'
18
+ load_profile "root_filter"
38
19
  end
39
20
 
40
21
  # Gotta stash this a-s-a-p, see the CommandGuesser class and i.e. #110 for further info
41
- SimpleCov::CommandGuesser.original_run_command = "#{$0} #{ARGV.join(" ")}"
22
+ SimpleCov::CommandGuesser.original_run_command = "#{$PROGRAM_NAME} #{ARGV.join(' ')}"
42
23
 
43
24
  at_exit do
44
- # Store the exit status of the test run since it goes away after calling the at_exit proc...
45
- if $! #was an exception thrown?
46
- #if it was a SystemExit, use the accompanying status
47
- #otherwise set a non-zero status representing termination by some other exception
48
- #(see github issue 41)
49
- @exit_status = $!.is_a?(SystemExit) ? $!.status : 1
50
- end
51
- SimpleCov.at_exit.call
52
- exit @exit_status if @exit_status # Force exit with stored status (see github issue #5)
25
+ # If we are in a different process than called start, don't interfere.
26
+ next if SimpleCov.pid != Process.pid
27
+
28
+ SimpleCov.set_exit_exception
29
+ SimpleCov.run_exit_tasks!
53
30
  end
54
31
 
32
+ # Autoload config from ~/.simplecov if present
33
+ require "simplecov/load_global_config"
34
+
55
35
  # Autoload config from .simplecov if present
56
- config_path = File.join(SimpleCov.root, '.simplecov')
57
- load config_path if File.exist?(config_path)
36
+ # Recurse upwards until we find .simplecov or reach the root directory
37
+
38
+ config_path = Pathname.new(SimpleCov.root)
39
+ loop do
40
+ filename = config_path.join(".simplecov")
41
+ if filename.exist?
42
+ begin
43
+ load filename
44
+ rescue LoadError, StandardError
45
+ $stderr.puts "Warning: Error occurred while trying to load #{filename}. " \
46
+ "Error message: #{$!.message}"
47
+ end
48
+ break
49
+ end
50
+ config_path, = config_path.split
51
+ break if config_path.root?
52
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ module ExitCodes
5
+ SUCCESS = 0
6
+ EXCEPTION = 1
7
+ MINIMUM_COVERAGE = 2
8
+ MAXIMUM_COVERAGE_DROP = 3
9
+ end
10
+ end
@@ -1,44 +1,61 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # An array of SimpleCov SourceFile instances with additional collection helper
2
4
  # methods for calculating coverage across them etc.
3
- class SimpleCov::FileList < Array
4
- # Returns the count of lines that have coverage
5
- def covered_lines
6
- return 0.0 if empty?
7
- map {|f| f.covered_lines.count }.inject(&:+)
8
- end
5
+ module SimpleCov
6
+ class FileList < Array
7
+ # Returns the count of lines that have coverage
8
+ def covered_lines
9
+ return 0.0 if empty?
10
+ map { |f| f.covered_lines.count }.inject(:+)
11
+ end
9
12
 
10
- # Returns the count of lines that have been missed
11
- def missed_lines
12
- return 0.0 if empty?
13
- map {|f| f.missed_lines.count }.inject(&:+)
14
- end
13
+ # Returns the count of lines that have been missed
14
+ def missed_lines
15
+ return 0.0 if empty?
16
+ map { |f| f.missed_lines.count }.inject(:+)
17
+ end
15
18
 
16
- # Returns the count of lines that are not relevant for coverage
17
- def never_lines
18
- return 0.0 if empty?
19
- map {|f| f.never_lines.count }.inject(&:+)
20
- end
19
+ # Returns the count of lines that are not relevant for coverage
20
+ def never_lines
21
+ return 0.0 if empty?
22
+ map { |f| f.never_lines.count }.inject(:+)
23
+ end
21
24
 
22
- # Returns the count of skipped lines
23
- def skipped_lines
24
- return 0.0 if empty?
25
- map {|f| f.skipped_lines.count }.inject(&:+)
26
- end
25
+ # Returns the count of skipped lines
26
+ def skipped_lines
27
+ return 0.0 if empty?
28
+ map { |f| f.skipped_lines.count }.inject(:+)
29
+ end
27
30
 
28
- # Returns the overall amount of relevant lines of code across all files in this list
29
- def lines_of_code
30
- covered_lines + missed_lines
31
- end
31
+ # Computes the coverage based upon lines covered and lines missed for each file
32
+ # Returns an array with all coverage percentages
33
+ def covered_percentages
34
+ map(&:covered_percent)
35
+ end
32
36
 
33
- # Computes the coverage based upon lines covered and lines missed
34
- def covered_percent
35
- return 100.0 if empty? or lines_of_code == 0
36
- covered_lines * 100.0 / lines_of_code
37
- end
37
+ # Finds the least covered file and returns that file's name
38
+ def least_covered_file
39
+ sort_by(&:covered_percent).first.filename
40
+ end
41
+
42
+ # Returns the overall amount of relevant lines of code across all files in this list
43
+ def lines_of_code
44
+ covered_lines + missed_lines
45
+ end
46
+
47
+ # Computes the coverage based upon lines covered and lines missed
48
+ # @return [Float]
49
+ def covered_percent
50
+ return 100.0 if empty? || lines_of_code.zero?
51
+ Float(covered_lines * 100.0 / lines_of_code)
52
+ end
38
53
 
39
- # Computes the strength (hits / line) based upon lines covered and lines missed
40
- def covered_strength
41
- return 0 if empty? or lines_of_code == 0
42
- map {|f| f.covered_strength }.inject(&:+) / size
54
+ # Computes the strength (hits / line) based upon lines covered and lines missed
55
+ # @return [Float]
56
+ def covered_strength
57
+ return 0.0 if empty? || lines_of_code.zero?
58
+ Float(map { |f| f.covered_strength * f.lines_of_code }.inject(:+) / lines_of_code)
59
+ end
43
60
  end
44
61
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SimpleCov
2
4
  #
3
5
  # Base filter class. Inherit from this to create custom filters,
@@ -16,21 +18,48 @@ module SimpleCov
16
18
  @filter_argument = filter_argument
17
19
  end
18
20
 
19
- def matches?(source_file)
21
+ def matches?(_)
20
22
  raise "The base filter class is not intended for direct use"
21
23
  end
22
24
 
23
25
  def passes?(source_file)
24
- warn "DEPRECATION: SimpleCov::Filter#passes?(x) has been renamed to #matches?. Please update your custom filters accordingly!"
26
+ warn "#{Kernel.caller.first}: [DEPRECATION] #passes? is deprecated. Use #matches? instead."
25
27
  matches?(source_file)
26
28
  end
29
+
30
+ def self.build_filter(filter_argument)
31
+ return filter_argument if filter_argument.is_a?(SimpleCov::Filter)
32
+ class_for_argument(filter_argument).new(filter_argument)
33
+ end
34
+
35
+ def self.class_for_argument(filter_argument)
36
+ if filter_argument.is_a?(String)
37
+ SimpleCov::StringFilter
38
+ elsif filter_argument.is_a?(Regexp)
39
+ SimpleCov::RegexFilter
40
+ elsif filter_argument.is_a?(Array)
41
+ SimpleCov::ArrayFilter
42
+ elsif filter_argument.is_a?(Proc)
43
+ SimpleCov::BlockFilter
44
+ else
45
+ raise ArgumentError, "You have provided an unrecognized filter type"
46
+ end
47
+ end
27
48
  end
28
49
 
29
50
  class StringFilter < SimpleCov::Filter
30
51
  # Returns true when the given source file's filename matches the
31
52
  # string configured when initializing this Filter with StringFilter.new('somestring)
32
53
  def matches?(source_file)
33
- (source_file.filename =~ /#{filter_argument}/)
54
+ source_file.project_filename.include?(filter_argument)
55
+ end
56
+ end
57
+
58
+ class RegexFilter < SimpleCov::Filter
59
+ # Returns true when the given source file's filename matches the
60
+ # regex configured when initializing this Filter with RegexFilter.new(/someregex/)
61
+ def matches?(source_file)
62
+ (source_file.project_filename =~ filter_argument)
34
63
  end
35
64
  end
36
65
 
@@ -41,4 +70,22 @@ module SimpleCov
41
70
  filter_argument.call(source_file)
42
71
  end
43
72
  end
73
+
74
+ class ArrayFilter < SimpleCov::Filter
75
+ def initialize(filter_argument)
76
+ filter_objects = filter_argument.map do |arg|
77
+ Filter.build_filter(arg)
78
+ end
79
+
80
+ super(filter_objects)
81
+ end
82
+
83
+ # Returns true if any of the filters in the array match the given source file.
84
+ # Configure this Filter like StringFilter.new(['some/path', /^some_regex/, Proc.new {|src_file| ... }])
85
+ def matches?(source_files_list)
86
+ filter_argument.any? do |arg|
87
+ arg.matches?(source_files_list)
88
+ end
89
+ end
90
+ end
44
91
  end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SimpleCov
2
4
  # TODO: Documentation on how to build your own formatters
3
5
  module Formatter
4
6
  end
5
7
  end
6
8
 
7
- require 'simplecov/formatter/simple_formatter'
9
+ require "simplecov/formatter/simple_formatter"
10
+ require "simplecov/formatter/multi_formatter"
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ module Formatter
5
+ class MultiFormatter
6
+ module InstanceMethods
7
+ def format(result)
8
+ formatters.map do |formatter|
9
+ begin
10
+ formatter.new.format(result)
11
+ rescue => e
12
+ STDERR.puts("Formatter #{formatter} failed with #{e.class}: #{e.message} (#{e.backtrace.first})")
13
+ nil
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.new(formatters = nil)
20
+ Class.new do
21
+ define_method :formatters do
22
+ @formatters ||= Array(formatters)
23
+ end
24
+ include InstanceMethods
25
+ end
26
+ end
27
+
28
+ def self.[](*args)
29
+ warn "#{Kernel.caller.first}: [DEPRECATION] ::[] is deprecated. Use ::new instead."
30
+ new(Array([*args]))
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,19 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # A ridiculously simple formatter for SimpleCov results.
3
5
  #
4
- class SimpleCov::Formatter::SimpleFormatter
5
- # Takes a SimpleCov::Result and generates a string out of it
6
- def format(result)
7
- output = ""
8
- result.groups.each do |name, files|
9
- output << "Group: #{name}\n"
10
- output << "="*40
11
- output << "\n"
12
- files.each do |file|
13
- output << "#{file.filename} (coverage: #{file.covered_percent.round(2)}%)\n"
6
+ module SimpleCov
7
+ module Formatter
8
+ class SimpleFormatter
9
+ # Takes a SimpleCov::Result and generates a string out of it
10
+ def format(result)
11
+ output = "".dup
12
+ result.groups.each do |name, files|
13
+ output << "Group: #{name}\n"
14
+ output << "=" * 40
15
+ output << "\n"
16
+ files.each do |file|
17
+ output << "#{file.filename} (coverage: #{file.covered_percent.round(2)}%)\n"
18
+ end
19
+ output << "\n"
20
+ end
21
+ output
14
22
  end
15
- output << "\n"
16
23
  end
17
- output
18
24
  end
19
25
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(JRUBY_VERSION) && JRUBY_VERSION.to_f < 1.7
4
+ require "jruby"
5
+ java_import "org.jruby.ast.NodeType"
6
+
7
+ # Coverage for JRuby < 1.7.0 does not work correctly
8
+ #
9
+ # - does not distinguish lines that cannot be executed
10
+ # - does (partial) coverage for files loaded before `Coverage.start`.
11
+ # - does not expand a path like `lib/../spec` to `spec`.
12
+ #
13
+ # This monkey patches Coverage to address those issues
14
+ module Coverage
15
+ class << self
16
+ alias __broken_result__ result
17
+
18
+ def result # rubocop:disable Metrics/MethodLength
19
+ fixed = {}
20
+ __broken_result__.each do |path, executed_lines|
21
+ next unless File.file? path
22
+
23
+ covered_lines = executed_lines.dup
24
+
25
+ process = lambda do |node|
26
+ if node.node_type == NodeType::NEWLINENODE
27
+ pos = node.position
28
+ covered_lines[pos.line] ||= 0
29
+ end
30
+ node.child_nodes.each(&process)
31
+ end
32
+
33
+ process[JRuby.parse(File.read(path), path)]
34
+
35
+ if (first = covered_lines.detect { |x| x }) && first > 0
36
+ fixed[File.expand_path(path)] = covered_lines
37
+ end
38
+ end
39
+
40
+ fixed
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module SimpleCov
6
+ module LastRun
7
+ class << self
8
+ def last_run_path
9
+ File.join(SimpleCov.coverage_path, ".last_run.json")
10
+ end
11
+
12
+ def read
13
+ return nil unless File.exist?(last_run_path)
14
+ json = File.read(last_run_path)
15
+ return nil if json.strip.empty?
16
+ JSON.parse(json)
17
+ end
18
+
19
+ def write(json)
20
+ File.open(last_run_path, "w+") do |f|
21
+ f.puts JSON.pretty_generate(json)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # Classifies whether lines are relevant for code coverage analysis.
5
+ # Comments & whitespace lines, and :nocov: token blocks, are considered not relevant.
6
+
7
+ class LinesClassifier
8
+ RELEVANT = 0
9
+ NOT_RELEVANT = nil
10
+
11
+ WHITESPACE_LINE = /^\s*$/
12
+ COMMENT_LINE = /^\s*#/
13
+ WHITESPACE_OR_COMMENT_LINE = Regexp.union(WHITESPACE_LINE, COMMENT_LINE)
14
+
15
+ def self.no_cov_line
16
+ /^(\s*)#(\s*)(\:#{SimpleCov.nocov_token}\:)/o
17
+ end
18
+
19
+ def self.no_cov_line?(line)
20
+ line =~ no_cov_line
21
+ rescue ArgumentError
22
+ # E.g., line contains an invalid byte sequence in UTF-8
23
+ false
24
+ end
25
+
26
+ def self.whitespace_line?(line)
27
+ line =~ WHITESPACE_OR_COMMENT_LINE
28
+ rescue ArgumentError
29
+ # E.g., line contains an invalid byte sequence in UTF-8
30
+ false
31
+ end
32
+
33
+ def classify(lines)
34
+ skipping = false
35
+
36
+ lines.map do |line|
37
+ if self.class.no_cov_line?(line)
38
+ skipping = !skipping
39
+ NOT_RELEVANT
40
+ elsif skipping || self.class.whitespace_line?(line)
41
+ NOT_RELEVANT
42
+ else
43
+ RELEVANT
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end