undercover 0.7.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +2 -2
- data/CHANGELOG.md +11 -1
- data/lib/undercover/changeset.rb +4 -0
- data/lib/undercover/cli.rb +11 -7
- data/lib/undercover/filter_set.rb +22 -2
- data/lib/undercover/lcov_parser.rb +6 -0
- data/lib/undercover/result.rb +1 -1
- data/lib/undercover/simplecov_formatter.rb +52 -0
- data/lib/undercover/simplecov_result_adapter.rb +4 -0
- data/lib/undercover/version.rb +1 -1
- data/lib/undercover.rb +12 -18
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c8f43820b6be7cbae834f152ed56778f8fb3540e878a012ce0bb5274be7b0e3
|
4
|
+
data.tar.gz: '0798f165b6deef05078311ff04822bc4c1dc708e3830b569b5575be2d1f8a3fe'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 922c43acac57c8e57df9c902b9739c4f084a090e6afc9b838868e80ce8c39ea5d5e087952c40e7446fceaa97313ee686aacfef1e8a62af8dd01879d665e5abda
|
7
|
+
data.tar.gz: 3d538e5526d124c9ffba53c53de75dd2e6009b0abf1de4a333ccd3e013da195b15811217d0e1a8b1b12bd7c34d47cac47c42dd6e4838cd82e3a571602c0e5966
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
# [0.8.0] - 2025-08-28
|
10
|
+
|
11
|
+
### Added
|
12
|
+
- Filter out files ignored by simplecov using `add_filter` ([#234](https://github.com/grodowski/undercover/pull/234))
|
13
|
+
- Add LF and LH parsing to LcovParser for simplecov-lcov 0.9 compatibility
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
- Fix an `Undercover::Result` edge case causing errors with ignored branches on uningnored lines
|
17
|
+
|
9
18
|
# [0.7.4] - 2025-07-13
|
10
19
|
|
11
20
|
### Fixed
|
@@ -185,7 +194,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
185
194
|
### Added
|
186
195
|
- First release of `undercover` 🎉
|
187
196
|
|
188
|
-
[Unreleased]: https://github.com/grodowski/undercover/compare/v0.
|
197
|
+
[Unreleased]: https://github.com/grodowski/undercover/compare/v0.8.0...HEAD
|
198
|
+
[0.8.0]: https://github.com/grodowski/undercover/compare/v0.7.4...v0.8.0
|
189
199
|
[0.7.4]: https://github.com/grodowski/undercover/compare/v0.7.3...v0.7.4
|
190
200
|
[0.7.3]: https://github.com/grodowski/undercover/compare/v0.7.2...v0.7.3
|
191
201
|
[0.7.2]: https://github.com/grodowski/undercover/compare/v0.7.1...v0.7.2
|
data/lib/undercover/changeset.rb
CHANGED
data/lib/undercover/cli.rb
CHANGED
@@ -5,9 +5,6 @@ require 'rainbow'
|
|
5
5
|
|
6
6
|
module Undercover
|
7
7
|
module CLI
|
8
|
-
# TODO: Report calls >parser< for each file instead of
|
9
|
-
# traversing the whole project at first!
|
10
|
-
|
11
8
|
WARNINGS_TO_S = {
|
12
9
|
stale_coverage: Rainbow('🚨 WARNING: Coverage data is older than your ' \
|
13
10
|
'latest changes and results might be incomplete. ' \
|
@@ -21,12 +18,20 @@ module Undercover
|
|
21
18
|
run_report(opts)
|
22
19
|
end
|
23
20
|
|
24
|
-
def self.run_report(opts)
|
21
|
+
def self.run_report(opts) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
25
22
|
coverage_path = opts.simplecov_resultset || opts.lcov
|
26
23
|
return handle_missing_coverage_path(opts) if coverage_path.nil?
|
27
24
|
return handle_missing_file(coverage_path) unless File.exist?(coverage_path)
|
28
25
|
|
29
|
-
|
26
|
+
simplecov_adapter = if opts.simplecov_resultset
|
27
|
+
SimplecovResultAdapter.parse(File.open(opts.simplecov_resultset), opts)
|
28
|
+
else
|
29
|
+
# TODO: lcov will be deprecated end of 2025 and we'll be able to refactor harder
|
30
|
+
LcovParser.parse(File.open(opts.lcov), opts)
|
31
|
+
end
|
32
|
+
|
33
|
+
changeset_obj = changeset(opts)
|
34
|
+
report = Undercover::Report.new(changeset_obj, opts, simplecov_adapter).build
|
30
35
|
handle_report_validation(report, coverage_path)
|
31
36
|
end
|
32
37
|
|
@@ -63,8 +68,7 @@ module Undercover
|
|
63
68
|
|
64
69
|
def self.changeset(opts)
|
65
70
|
git_dir = File.join(opts.path, opts.git_dir)
|
66
|
-
|
67
|
-
Undercover::Changeset.new(git_dir, opts.compare, filter_set)
|
71
|
+
Undercover::Changeset.new(git_dir, opts.compare)
|
68
72
|
end
|
69
73
|
end
|
70
74
|
end
|
@@ -2,16 +2,36 @@
|
|
2
2
|
|
3
3
|
module Undercover
|
4
4
|
class FilterSet
|
5
|
-
attr_reader :allow_filters, :reject_filters
|
5
|
+
attr_reader :allow_filters, :reject_filters, :simplecov_filters
|
6
6
|
|
7
|
-
def initialize(allow_filters, reject_filters)
|
7
|
+
def initialize(allow_filters, reject_filters, simplecov_filters)
|
8
8
|
@allow_filters = allow_filters || []
|
9
9
|
@reject_filters = reject_filters || []
|
10
|
+
@simplecov_filters = simplecov_filters || []
|
10
11
|
end
|
11
12
|
|
12
13
|
def include?(filepath)
|
13
14
|
fnmatch = proc { |glob| File.fnmatch(glob, filepath, File::FNM_EXTGLOB) }
|
15
|
+
|
16
|
+
# Check if file was ignored by SimpleCov filters
|
17
|
+
return false if ignored_by_simplecov?(filepath)
|
18
|
+
|
19
|
+
# Apply Undercover's own filters
|
14
20
|
allow_filters.any?(fnmatch) && reject_filters.none?(fnmatch)
|
15
21
|
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def ignored_by_simplecov?(filepath)
|
26
|
+
simplecov_filters.any? do |filter|
|
27
|
+
if filter[:string]
|
28
|
+
filepath.include?(filter[:string])
|
29
|
+
elsif filter[:regex]
|
30
|
+
filepath.match?(Regexp.new(filter[:regex]))
|
31
|
+
elsif filter[:file]
|
32
|
+
filepath == filter[:file]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
16
36
|
end
|
17
37
|
end
|
@@ -57,6 +57,11 @@ module Undercover
|
|
57
57
|
false
|
58
58
|
end
|
59
59
|
|
60
|
+
def ignored_files
|
61
|
+
# supported by SimplecovResultAdapter only
|
62
|
+
[]
|
63
|
+
end
|
64
|
+
|
60
65
|
private
|
61
66
|
|
62
67
|
# rubocop:disable Metrics/MethodLength, Style/SpecialGlobalVars, Metrics/AbcSize
|
@@ -79,6 +84,7 @@ module Undercover
|
|
79
84
|
source_files[@current_filename] << [line_no.to_i, block_no.to_i, branch_no.to_i, covered.to_i]
|
80
85
|
when /^end_of_record$/, /^$/
|
81
86
|
@current_filename = nil
|
87
|
+
when /^LF:(\d+)|LH:(\d+)/ # lines found, lines hit; no-op
|
82
88
|
else
|
83
89
|
raise LcovParseError, "could not recognise '#{line}' as valid LCOV"
|
84
90
|
end
|
data/lib/undercover/result.rb
CHANGED
@@ -43,7 +43,7 @@ module Undercover
|
|
43
43
|
|
44
44
|
# check branch coverage for line_no
|
45
45
|
coverage.each do |ln, _block, _branch, cov|
|
46
|
-
return true if ln == line_no && cov && cov.zero?
|
46
|
+
return true if ln == line_no && cov && cov != 'ignored' && cov.zero?
|
47
47
|
end
|
48
48
|
|
49
49
|
# check line coverage for line_no
|
@@ -13,12 +13,60 @@ module SimpleCovJSONFormatter
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
module SimpleCov
|
17
|
+
class << self
|
18
|
+
attr_accessor :filter_definitions
|
19
|
+
|
20
|
+
alias filtered_uncached filtered
|
21
|
+
|
22
|
+
def filtered(files)
|
23
|
+
@filter_definitions ||= extract_filter_definitions
|
24
|
+
original_files = files.dup
|
25
|
+
filtered_uncached(files).tap do |filtered_files|
|
26
|
+
filtered_file_paths = (original_files.map(&:filename) - filtered_files.map(&:filename))
|
27
|
+
filtered_file_paths.each do |file|
|
28
|
+
relative_path = file.delete_prefix("#{SimpleCov.root}/")
|
29
|
+
@filter_definitions << {file: relative_path} unless covered_by_serializable_filters?(relative_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def extract_filter_definitions
|
37
|
+
filter_array = []
|
38
|
+
|
39
|
+
filters.each do |filter|
|
40
|
+
case filter
|
41
|
+
when SimpleCov::StringFilter
|
42
|
+
filter_array << {string: filter.filter_argument}
|
43
|
+
when SimpleCov::RegexFilter
|
44
|
+
filter_array << {regex: filter.filter_argument.source}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
filter_array
|
49
|
+
end
|
50
|
+
|
51
|
+
def covered_by_serializable_filters?(relative_path)
|
52
|
+
@filter_definitions.any? do |filter_def|
|
53
|
+
if filter_def[:string]
|
54
|
+
relative_path.include?(filter_def[:string])
|
55
|
+
elsif filter_def[:regex]
|
56
|
+
relative_path.match?(Regexp.new(filter_def[:regex]))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
16
63
|
module Undercover
|
17
64
|
class ResultHashFormatterWithRoot < SimpleCovJSONFormatter::ResultHashFormatter
|
18
65
|
def format
|
19
66
|
formatted_result[:meta] = {timestamp: @result.created_at.to_i}
|
20
67
|
format_files
|
21
68
|
add_undercover_meta_fields
|
69
|
+
add_ignored_files
|
22
70
|
formatted_result
|
23
71
|
end
|
24
72
|
|
@@ -30,6 +78,10 @@ module Undercover
|
|
30
78
|
end
|
31
79
|
end
|
32
80
|
|
81
|
+
def add_ignored_files
|
82
|
+
formatted_result[:meta][:ignored_files] = SimpleCov.filter_definitions || []
|
83
|
+
end
|
84
|
+
|
33
85
|
# format_files uses relative path as keys, as opposed to the superclass method
|
34
86
|
def format_files
|
35
87
|
formatted_result[:coverage] ||= {}
|
data/lib/undercover/version.rb
CHANGED
data/lib/undercover.rb
CHANGED
@@ -21,11 +21,12 @@ require 'undercover/version'
|
|
21
21
|
module Undercover
|
22
22
|
class Report
|
23
23
|
extend Forwardable
|
24
|
+
|
24
25
|
def_delegators :changeset, :validate
|
25
26
|
|
26
27
|
attr_reader :changeset,
|
27
28
|
:lcov,
|
28
|
-
:
|
29
|
+
:coverage_adapter,
|
29
30
|
:results,
|
30
31
|
:code_dir,
|
31
32
|
:filter_set,
|
@@ -35,15 +36,16 @@ module Undercover
|
|
35
36
|
#
|
36
37
|
# @param changeset [Undercover::Changeset]
|
37
38
|
# @param opts [Undercover::Options]
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
@lcov = LcovParser.parse(File.open(opts.lcov), opts) if opts.lcov
|
39
|
+
# @param coverage_adapter [Undercover::SimplecovResultAdapter|Undercover::LcovParser] pre-parsed coverage adapter
|
40
|
+
def initialize(changeset, opts, coverage_adapter)
|
41
|
+
@coverage_adapter = coverage_adapter
|
43
42
|
|
44
43
|
@code_dir = opts.path
|
45
44
|
@changeset = changeset
|
46
|
-
|
45
|
+
|
46
|
+
ignored_files = coverage_adapter.ignored_files || []
|
47
|
+
@filter_set = FilterSet.new(opts.glob_allow_filters, opts.glob_reject_filters, ignored_files)
|
48
|
+
changeset.filter_with(filter_set)
|
47
49
|
@max_warnings_limit = opts.max_warnings_limit
|
48
50
|
@loaded_files = {}
|
49
51
|
@results = {}
|
@@ -106,29 +108,21 @@ module Undercover
|
|
106
108
|
|
107
109
|
attr_reader :loaded_files
|
108
110
|
|
109
|
-
# rubocop:disable Metrics/
|
111
|
+
# rubocop:disable Metrics/AbcSize
|
110
112
|
def load_and_parse_file(filepath)
|
111
113
|
key = filepath.gsub(/^\.\//, '')
|
112
114
|
return if loaded_files[key]
|
113
|
-
return unless include_file?(filepath)
|
114
115
|
|
115
116
|
root_ast = Imagen::Node::Root.new.build_from_file(
|
116
117
|
File.join(code_dir, filepath)
|
117
118
|
)
|
118
119
|
return if root_ast.children.empty?
|
119
120
|
|
120
|
-
# lcov will be deprecated at some point and we'll be able to refactor harder
|
121
|
-
coverage = simplecov_resultset || lcov
|
122
|
-
|
123
121
|
loaded_files[key] = []
|
124
122
|
root_ast.find_all(->(node) { !node.is_a?(Imagen::Node::Root) }).each do |imagen_node|
|
125
|
-
loaded_files[key] << Result.new(imagen_node,
|
123
|
+
loaded_files[key] << Result.new(imagen_node, coverage_adapter, filepath)
|
126
124
|
end
|
127
125
|
end
|
128
|
-
# rubocop:enable Metrics/
|
129
|
-
|
130
|
-
def include_file?(filepath)
|
131
|
-
filter_set.include?(filepath)
|
132
|
-
end
|
126
|
+
# rubocop:enable Metrics/AbcSize
|
133
127
|
end
|
134
128
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: undercover
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Grodowski
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-08-28 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: base64
|