slather 2.4.9 → 2.7.1
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/.travis.yml +4 -2
- data/CHANGELOG.md +51 -0
- data/README.md +21 -1
- data/assets/slather.css +2 -1
- data/lib/slather/command/coverage_command.rb +4 -1
- data/lib/slather/coverage_file.rb +14 -9
- data/lib/slather/coverage_service/coveralls.rb +57 -0
- data/lib/slather/coverage_service/html_output.rb +51 -2
- data/lib/slather/profdata_coverage_file.rb +42 -2
- data/lib/slather/project.rb +35 -3
- data/lib/slather/version.rb +1 -1
- data/slather.gemspec +4 -4
- data/spec/fixtures/FixtureFramework/FixtureFramework.h +19 -0
- data/spec/fixtures/FixtureFramework/FlashExperiment.swift +7 -0
- data/spec/fixtures/FixtureFramework/Info.plist +24 -0
- data/spec/fixtures/FixtureFrameworkTests/FixtureFrameworkTests.swift +34 -0
- data/spec/fixtures/FixtureFrameworkTests/FlashExperimentTests.swift +9 -0
- data/spec/fixtures/FixtureFrameworkTests/Info.plist +22 -0
- data/spec/fixtures/fixtures.xcodeproj/project.pbxproj +222 -0
- data/spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixtures.xcscheme +21 -5
- data/spec/fixtures/fixtures.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- data/spec/slather/coverage_service/coveralls_spec.rb +20 -0
- data/spec/slather/coverage_service/html_output_spec.rb +2 -2
- data/spec/slather/profdata_coverage_spec.rb +16 -0
- data/spec/slather/project_spec.rb +12 -8
- metadata +28 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82acbc5ecfb8610c49f39cdea2ff67387d30b3c41bf78c34095a59c7b572e802
|
4
|
+
data.tar.gz: a1c830dddd4d52d8641665086ad6a63c294f00a7dd3370c7cd588c8c586db06e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 239d29e6e221b6119be23af3dc92a7f28d4608dd71acf3f7ed03530953878ab42942903ed3f505a81051c3aa6903ba2a167b37867274b24ab7fc948b9006f08c
|
7
|
+
data.tar.gz: c918c164b1da93699be34bef38291b3c43d3d43eb1d258919dc3de0bd84beb855a44318a8d6638d567543ddad7a2e647ca07a1fe12d14678b9c54bbde25a749a
|
data/.travis.yml
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
language: objective-c
|
2
2
|
script: bundle exec rake
|
3
|
-
osx_image:
|
3
|
+
osx_image: xcode12.2
|
4
|
+
|
5
|
+
cache: bundler
|
4
6
|
|
5
7
|
before_install:
|
6
8
|
- curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem
|
7
|
-
- gem install bundler -v "~>
|
9
|
+
- gem install bundler -v "~> 2.0" --no-document
|
8
10
|
|
9
11
|
install:
|
10
12
|
- bundle install --without=documentation
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,56 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## v2.7.1
|
4
|
+
|
5
|
+
* Support generating coverage for framework targets
|
6
|
+
[onato](https://github.com/onato)
|
7
|
+
[#482](https://github.com/SlatherOrg/slather/pull/482)
|
8
|
+
|
9
|
+
* Show number of lines in HTML report
|
10
|
+
[SiemianHS](https://github.com/SiemianHS)
|
11
|
+
[#494](https://github.com/SlatherOrg/slather/pull/494)
|
12
|
+
|
13
|
+
* Fixed issues with HTML report generation
|
14
|
+
[fchiba](https://github.com/fchiba)
|
15
|
+
[#483](https://github.com/SlatherOrg/slather/pull/483)
|
16
|
+
[#484](https://github.com/SlatherOrg/slather/pull/484)
|
17
|
+
|
18
|
+
* Don't fail if a source file doesn't exist
|
19
|
+
[chillpop](https://github.com/chillpop)
|
20
|
+
[#492](https://github.com/SlatherOrg/slather/pull/492)
|
21
|
+
|
22
|
+
## v2.7.0
|
23
|
+
|
24
|
+
* Add Branch Coverage data for ProfData coverage files
|
25
|
+
[hborawski](https://github.com/hborawski)
|
26
|
+
[#477](https://github.com/SlatherOrg/slather/pull/477)
|
27
|
+
|
28
|
+
* Fixed 'Argument list too long' when running 'xcrun llvm-cov'
|
29
|
+
[samuelsainz](https://github.com/samuelsainz)
|
30
|
+
[#476](https://github.com/SlatherOrg/slather/pull/476)
|
31
|
+
|
32
|
+
## v2.6.1
|
33
|
+
|
34
|
+
* Update nokogiri to 1.11
|
35
|
+
[ashin-omg](https://github.com/ashin-omg)
|
36
|
+
[#473](https://github.com/SlatherOrg/slather/pull/473)
|
37
|
+
|
38
|
+
## v2.6.0
|
39
|
+
|
40
|
+
* Added GitHub actions support
|
41
|
+
[martin-key](https://github.com/martin-key), [troyfontaine](https://github.com/troyfontaine)
|
42
|
+
[#468](https://github.com/SlatherOrg/slather/pull/468)
|
43
|
+
|
44
|
+
## v2.5.0
|
45
|
+
|
46
|
+
* Fixed activesupport and cocoapods dependencies
|
47
|
+
[daneov](https://github.com/daneov)
|
48
|
+
[#456](https://github.com/SlatherOrg/slather/pull/467)
|
49
|
+
|
50
|
+
* Fixed typo in documentation
|
51
|
+
[descorp](https://github.com/descorp)
|
52
|
+
[#456](https://github.com/SlatherOrg/slather/pull/463)
|
53
|
+
|
3
54
|
## v2.4.9
|
4
55
|
|
5
56
|
* Added support for Sonarqube output
|
data/README.md
CHANGED
@@ -149,7 +149,7 @@ ignore:
|
|
149
149
|
- ProjectTestsGroup/*
|
150
150
|
```
|
151
151
|
|
152
|
-
And then in your `.travis.yml` or `circle.yml`, call `slather` after a successful build:
|
152
|
+
And then in your `.travis.yml` or `circle.yml` or `github-action.yml`, call `slather` after a successful build:
|
153
153
|
|
154
154
|
```yml
|
155
155
|
# .travis.yml
|
@@ -168,6 +168,25 @@ test:
|
|
168
168
|
|
169
169
|
```
|
170
170
|
|
171
|
+
```yml
|
172
|
+
# github-action.yml
|
173
|
+
myjob:
|
174
|
+
steps:
|
175
|
+
- run: |
|
176
|
+
bundle config path vendor/bundle
|
177
|
+
bundle install --without=documentation --jobs 4 --retry 3
|
178
|
+
- name: Extract branch name
|
179
|
+
shell: bash
|
180
|
+
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
181
|
+
id: get_branch
|
182
|
+
- run: bundle exec slather
|
183
|
+
env:
|
184
|
+
GIT_BRANCH: ${{ steps.get_branch.outputs.branch }}
|
185
|
+
CI_PULL_REQUEST: ${{ github.event.number }}
|
186
|
+
COVERAGE_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
187
|
+
|
188
|
+
```
|
189
|
+
|
171
190
|
#### Usage with Travis CI Pro
|
172
191
|
|
173
192
|
To use Coveralls with Travis CI Pro (for private repos), add following lines along with other settings to `.slather.yml`:
|
@@ -265,3 +284,4 @@ Please make sure to follow our general coding style and add test coverage for ne
|
|
265
284
|
* [@jhersh](https://github.com/jhersh), CircleCI support.
|
266
285
|
* [@tarbrain](https://github.com/tarbrain), Cobertura support and bugfixing.
|
267
286
|
* [@ikhsan](https://github.com/ikhsan), html support.
|
287
|
+
* [@martin-key](https://github.com/martin-key) and [@troyfontaine](https://github.com/troyfontaine), Github Actions support.
|
data/assets/slather.css
CHANGED
@@ -74,6 +74,7 @@ table.source_code {
|
|
74
74
|
table.source_code td {
|
75
75
|
padding-bottom: 0.3em;
|
76
76
|
}
|
77
|
+
code.missed { background-color: rgba(255, 73, 76, 0.3); }
|
77
78
|
table.source_code tr.missed td { background-color: rgba(248, 103, 105, 0.2); }
|
78
79
|
table.source_code tr.covered td { background-color: rgba(103, 207, 124, 0.2); }
|
79
80
|
table.source_code td.num {
|
@@ -124,7 +125,7 @@ footer p, footer a {
|
|
124
125
|
Syntax Highlighting using highlight.js (https://highlightjs.org)
|
125
126
|
------------------------------------------------------------- */
|
126
127
|
.hljs {
|
127
|
-
display: block;
|
128
|
+
display: inline-block;
|
128
129
|
overflow-x: auto;
|
129
130
|
-webkit-text-size-adjust: none;
|
130
131
|
}
|
@@ -8,12 +8,13 @@ class CoverageCommand < Clamp::Command
|
|
8
8
|
option ["--jenkins"], :flag, "Indicate that the builds are running on Jenkins"
|
9
9
|
option ["--buildkite"], :flag, "Indicate that the builds are running on Buildkite"
|
10
10
|
option ["--teamcity"], :flag, "Indicate that the builds are running on TeamCity"
|
11
|
+
option ["--github"], :flag, "Indicate that the builds are running on Github Actions"
|
11
12
|
|
12
13
|
option ["--coveralls", "-c"], :flag, "Post coverage results to coveralls"
|
13
14
|
option ["--simple-output", "-s"], :flag, "Output coverage results to the terminal"
|
14
15
|
option ["--gutter-json", "-g"], :flag, "Output coverage results as Gutter JSON format"
|
15
16
|
option ["--cobertura-xml", "-x"], :flag, "Output coverage results as Cobertura XML format"
|
16
|
-
option ["--sonarqube-xml", "-sq"], :flag, "Output coverage results as
|
17
|
+
option ["--sonarqube-xml", "-sq"], :flag, "Output coverage results as SonarQube XML format"
|
17
18
|
option ["--llvm-cov", "-r"], :flag, "Output coverage as llvm-cov format"
|
18
19
|
option ["--json"], :flag, "Output coverage results as simple JSON"
|
19
20
|
option ["--html"], :flag, "Output coverage results as static html pages"
|
@@ -91,6 +92,8 @@ class CoverageCommand < Clamp::Command
|
|
91
92
|
project.ci_service = :buildkite
|
92
93
|
elsif teamcity?
|
93
94
|
project.ci_service = :teamcity
|
95
|
+
elsif github?
|
96
|
+
project.ci_service = :github
|
94
97
|
end
|
95
98
|
end
|
96
99
|
|
@@ -43,18 +43,23 @@ module Slather
|
|
43
43
|
|
44
44
|
def gcov_data
|
45
45
|
@gcov_data ||= begin
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
gcov_data = ""
|
47
|
+
|
48
|
+
Dir.chdir(project.project_dir) do
|
49
|
+
gcov_output = `gcov "#{source_file_pathname}" --object-directory "#{gcno_file_pathname.parent}" --branch-probabilities --branch-counts`
|
50
|
+
# Sometimes gcov makes gcov files for Cocoa Touch classes, like NSRange. Ignore and delete later.
|
51
|
+
gcov_files_created = gcov_output.scan(/creating '(.+\..+\.gcov)'/)
|
52
|
+
|
53
|
+
gcov_file_name = "./#{source_file_pathname.basename}.gcov"
|
54
|
+
if File.exists?(gcov_file_name)
|
55
|
+
gcov_data = File.new(gcov_file_name).read
|
56
|
+
else
|
57
|
+
gcov_data = ""
|
58
|
+
end
|
49
59
|
|
50
|
-
|
51
|
-
if File.exists?(gcov_file_name)
|
52
|
-
gcov_data = File.new(gcov_file_name).read
|
53
|
-
else
|
54
|
-
gcov_data = ""
|
60
|
+
gcov_files_created.each { |file| FileUtils.rm_f(file) }
|
55
61
|
end
|
56
62
|
|
57
|
-
gcov_files_created.each { |file| FileUtils.rm_f(file) }
|
58
63
|
gcov_data
|
59
64
|
end
|
60
65
|
end
|
@@ -36,6 +36,21 @@ module Slather
|
|
36
36
|
end
|
37
37
|
private :jenkins_job_id
|
38
38
|
|
39
|
+
def github_job_id
|
40
|
+
ENV['GITHUB_RUN_ID']
|
41
|
+
end
|
42
|
+
private :github_job_id
|
43
|
+
|
44
|
+
def github_pull_request
|
45
|
+
ENV['CI_PULL_REQUEST'] || ""
|
46
|
+
end
|
47
|
+
private :github_pull_request
|
48
|
+
|
49
|
+
def github_repo_name
|
50
|
+
ENV['GITHUB_REPOSITORY'] || ""
|
51
|
+
end
|
52
|
+
private :github_repo_name
|
53
|
+
|
39
54
|
def jenkins_branch_name
|
40
55
|
branch_name = ENV['GIT_BRANCH'] || ENV['BRANCH_NAME']
|
41
56
|
if branch_name.include? 'origin/'
|
@@ -51,6 +66,11 @@ module Slather
|
|
51
66
|
end
|
52
67
|
private :teamcity_branch_name
|
53
68
|
|
69
|
+
def github_branch_name
|
70
|
+
ENV['GIT_BRANCH'] || `git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3-`.chomp
|
71
|
+
end
|
72
|
+
private :github_branch_name
|
73
|
+
|
54
74
|
def buildkite_job_id
|
55
75
|
ENV['BUILDKITE_BUILD_NUMBER']
|
56
76
|
end
|
@@ -119,6 +139,23 @@ module Slather
|
|
119
139
|
"https://buildkite.com/" + ENV['BUILDKITE_PROJECT_SLUG'] + "/builds/" + ENV['BUILDKITE_BUILD_NUMBER'] + "#"
|
120
140
|
end
|
121
141
|
|
142
|
+
def github_git_info
|
143
|
+
{
|
144
|
+
:head => {
|
145
|
+
:id => ENV['GITHUB_SHA'],
|
146
|
+
:author_name => ENV['GITHUB_ACTOR'],
|
147
|
+
:message => (`git log --format=%s -n 1 HEAD`.chomp || "")
|
148
|
+
},
|
149
|
+
:branch => github_branch_name
|
150
|
+
}
|
151
|
+
end
|
152
|
+
private :github_git_info
|
153
|
+
|
154
|
+
def github_build_url
|
155
|
+
"https://github.com/" + ENV['GITHUB_REPOSITORY'] + "/actions/runs/" + ENV['GITHUB_RUN_ID']
|
156
|
+
end
|
157
|
+
private :github_build_url
|
158
|
+
|
122
159
|
def coveralls_coverage_data
|
123
160
|
if ci_service == :travis_ci || ci_service == :travis_pro
|
124
161
|
if travis_job_id
|
@@ -206,6 +243,26 @@ module Slather
|
|
206
243
|
else
|
207
244
|
raise StandardError, "Environment variable `TC_BUILD_NUMBER` not set. Is this running on a teamcity build?"
|
208
245
|
end
|
246
|
+
elsif ci_service == :github
|
247
|
+
|
248
|
+
if coverage_access_token.to_s.strip.length == 0
|
249
|
+
raise StandardError, "Access token is not set. Uploading coverage data for private repositories requires an access token."
|
250
|
+
end
|
251
|
+
|
252
|
+
if github_job_id
|
253
|
+
{
|
254
|
+
:service_job_id => github_job_id,
|
255
|
+
:service_name => "github",
|
256
|
+
:repo_token => coverage_access_token,
|
257
|
+
:repo_name => github_repo_name,
|
258
|
+
:source_files => coverage_files.map(&:as_json),
|
259
|
+
:service_build_url => github_build_url,
|
260
|
+
:service_pull_request => github_pull_request,
|
261
|
+
:git => github_git_info
|
262
|
+
}.to_json
|
263
|
+
else
|
264
|
+
raise StandardError, "Environment variable `GITHUB_RUN_ID` not set. Is this running on github build?"
|
265
|
+
end
|
209
266
|
else
|
210
267
|
raise StandardError, "No support for ci named #{ci_service}"
|
211
268
|
end
|
@@ -70,9 +70,14 @@ module Slather
|
|
70
70
|
|
71
71
|
total_relevant_lines = 0
|
72
72
|
total_tested_lines = 0
|
73
|
+
total_relevant_branches = 0
|
74
|
+
total_branches_tested = 0
|
73
75
|
coverage_files.each { |coverage_file|
|
74
76
|
total_tested_lines += coverage_file.num_lines_tested
|
75
77
|
total_relevant_lines += coverage_file.num_lines_testable
|
78
|
+
|
79
|
+
total_relevant_branches += coverage_file.num_branches_testable
|
80
|
+
total_branches_tested += coverage_file.num_branches_tested
|
76
81
|
}
|
77
82
|
|
78
83
|
builder = Nokogiri::HTML::Builder.with(template.at('#reports')) { |cov|
|
@@ -82,6 +87,22 @@ module Slather
|
|
82
87
|
percentage = (total_tested_lines / total_relevant_lines.to_f) * 100.0
|
83
88
|
cov.span "Total Coverage : "
|
84
89
|
cov.span decimal_f(percentage) + '%', :class => class_for_coverage_percentage(percentage), :id => "total_coverage"
|
90
|
+
cov.span " ("
|
91
|
+
cov.span total_tested_lines, :id => "total_tested_lines"
|
92
|
+
cov.span " of "
|
93
|
+
cov.span total_relevant_lines, :id => "total_relevant_lines"
|
94
|
+
cov.span " lines)"
|
95
|
+
}
|
96
|
+
|
97
|
+
cov.h4 {
|
98
|
+
percentage = (total_branches_tested / total_relevant_branches.to_f) * 100.0
|
99
|
+
cov.span "Total Branch Coverage : "
|
100
|
+
cov.span decimal_f(percentage) + '%', :class => class_for_coverage_percentage(percentage), :id => "total_coverage"
|
101
|
+
cov.span " ("
|
102
|
+
cov.span total_branches_tested, :id => "total_branches_tested"
|
103
|
+
cov.span " of "
|
104
|
+
cov.span total_relevant_branches, :id => "total_relevant_branches"
|
105
|
+
cov.span " lines)"
|
85
106
|
}
|
86
107
|
|
87
108
|
cov.input(:class => "search", :placeholder => "Search")
|
@@ -133,6 +154,7 @@ module Slather
|
|
133
154
|
filepath = coverage_file.source_file_pathname_relative_to_repo_root
|
134
155
|
filename = File.basename(filepath)
|
135
156
|
percentage = coverage_file.percentage_lines_tested
|
157
|
+
branch_percentage = coverage_file.rate_branches_tested * 100
|
136
158
|
|
137
159
|
cleaned_gcov_lines = coverage_file.cleaned_gcov_data.split("\n")
|
138
160
|
is_file_empty = (cleaned_gcov_lines.count <= 0)
|
@@ -142,7 +164,10 @@ module Slather
|
|
142
164
|
builder = Nokogiri::HTML::Builder.with(template.at('#reports')) { |cov|
|
143
165
|
cov.h2(:class => "cov_title") {
|
144
166
|
cov.span("Coverage for \"#{filename}\"" + (!is_file_empty ? " : " : ""))
|
167
|
+
cov.span("Lines: ") unless is_file_empty
|
145
168
|
cov.span("#{decimal_f(percentage)}%", :class => class_for_coverage_percentage(percentage)) unless is_file_empty
|
169
|
+
cov.span(" Branches: ") unless is_file_empty
|
170
|
+
cov.span("#{decimal_f(branch_percentage)}%", :class => class_for_coverage_percentage(branch_percentage)) unless is_file_empty
|
146
171
|
}
|
147
172
|
|
148
173
|
cov.h4("(#{coverage_file.num_lines_tested} of #{coverage_file.num_lines_testable} relevant lines covered)", :class => "cov_subtitle")
|
@@ -157,8 +182,9 @@ module Slather
|
|
157
182
|
|
158
183
|
cov.table(:class => "source_code") {
|
159
184
|
cleaned_gcov_lines.each do |line|
|
160
|
-
|
161
185
|
line_number = coverage_file.line_number_in_line(line)
|
186
|
+
missed_regions = coverage_file.branch_region_data[line_number]
|
187
|
+
hits = coverage_file.coverage_for_line(line)
|
162
188
|
next unless line_number > 0
|
163
189
|
|
164
190
|
line_source = line.split(line_number_separator, 3)[2]
|
@@ -171,7 +197,30 @@ module Slather
|
|
171
197
|
cov.td(line, :class => classes[idx])
|
172
198
|
else
|
173
199
|
cov.td(:class => classes[idx]) {
|
174
|
-
cov.pre {
|
200
|
+
cov.pre {
|
201
|
+
# If the line has coverage and missed regions, split up
|
202
|
+
# the line to show regions that weren't covered
|
203
|
+
if missed_regions != nil && hits != nil && hits > 0
|
204
|
+
regions = missed_regions.map do |region|
|
205
|
+
region_start, region_length = region
|
206
|
+
if region_length != nil
|
207
|
+
line[region_start, region_length]
|
208
|
+
else
|
209
|
+
line[region_start, line.length - region_start]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
current_line = line
|
213
|
+
regions.each do |region|
|
214
|
+
covered, remainder = current_line.split(region, 2)
|
215
|
+
cov.code(covered, :class => "objc")
|
216
|
+
cov.code(region, :class => "objc missed")
|
217
|
+
current_line = remainder
|
218
|
+
end
|
219
|
+
cov.code(current_line, :class => "objc")
|
220
|
+
else
|
221
|
+
cov.code(line, :class => "objc")
|
222
|
+
end
|
223
|
+
}
|
175
224
|
}
|
176
225
|
end
|
177
226
|
}
|
@@ -8,7 +8,7 @@ module Slather
|
|
8
8
|
include CoverageInfo
|
9
9
|
include CoverallsCoverage
|
10
10
|
|
11
|
-
attr_accessor :project, :source, :line_numbers_first, :line_data
|
11
|
+
attr_accessor :project, :source, :segments, :line_numbers_first, :line_data
|
12
12
|
|
13
13
|
def initialize(project, source, line_numbers_first)
|
14
14
|
self.project = project
|
@@ -188,7 +188,47 @@ module Slather
|
|
188
188
|
|
189
189
|
def branch_coverage_data
|
190
190
|
@branch_coverage_data ||= begin
|
191
|
-
Hash.new
|
191
|
+
branch_coverage_data = Hash.new
|
192
|
+
|
193
|
+
self.segments.each do |segment|
|
194
|
+
line, col, hits, has_count, *rest = segment
|
195
|
+
next if !has_count
|
196
|
+
if branch_coverage_data.key?(line)
|
197
|
+
branch_coverage_data[line] = branch_coverage_data[line] + [hits]
|
198
|
+
else
|
199
|
+
branch_coverage_data[line] = [hits]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
branch_coverage_data
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def branch_region_data
|
208
|
+
@branch_region_data ||= begin
|
209
|
+
branch_region_data = Hash.new
|
210
|
+
region_start = nil
|
211
|
+
current_line = 0
|
212
|
+
@segments ||= []
|
213
|
+
@segments.each do |segment|
|
214
|
+
line, col, hits, has_count, *rest = segment
|
215
|
+
# Make column 0 based index
|
216
|
+
col = col - 1
|
217
|
+
if hits == 0 && has_count
|
218
|
+
current_line = line
|
219
|
+
region_start = col
|
220
|
+
elsif region_start != nil && hits > 0 && has_count
|
221
|
+
# if the region wrapped to a new line before ending, put nil to indicate it didnt end on this line
|
222
|
+
region_end = line == current_line ? col - region_start : nil
|
223
|
+
if branch_region_data.key?(current_line)
|
224
|
+
branch_region_data[current_line] << [region_start, region_end]
|
225
|
+
else
|
226
|
+
branch_region_data[current_line] = [[region_start, region_end]]
|
227
|
+
end
|
228
|
+
region_start = nil
|
229
|
+
end
|
230
|
+
end
|
231
|
+
branch_region_data
|
192
232
|
end
|
193
233
|
end
|
194
234
|
|
data/lib/slather/project.rb
CHANGED
@@ -135,7 +135,12 @@ module Slather
|
|
135
135
|
coverage_json = JSON.parse(coverage_json_string)
|
136
136
|
coverage_json["data"].reduce([]) do |result, chunk|
|
137
137
|
result.concat(chunk["files"].map do |file|
|
138
|
-
|
138
|
+
filename = file["filename"]
|
139
|
+
path = Pathname(filename)
|
140
|
+
# Don't crash if the file doesn't exist on disk.
|
141
|
+
# This may happen for autogenerated files that have been deleted.
|
142
|
+
filename = path.exist? ? path.realpath : filename
|
143
|
+
{"filename" => filename, "segments" => file["segments"]}
|
139
144
|
end)
|
140
145
|
end
|
141
146
|
end
|
@@ -162,13 +167,24 @@ module Slather
|
|
162
167
|
end
|
163
168
|
private :create_coverage_files_for_binary
|
164
169
|
|
165
|
-
def create_coverage_files(binary_path,
|
170
|
+
def create_coverage_files(binary_path, path_objects)
|
166
171
|
line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0')
|
172
|
+
# get just file names from the path objects
|
173
|
+
pathnames = path_objects.map { |path_obj| path_obj["filename"] }.compact
|
174
|
+
# Map of path name => segment array
|
175
|
+
paths_to_segments = path_objects.reduce(Hash.new) do |hash, path_obj|
|
176
|
+
hash[path_obj["filename"]] = path_obj["segments"]
|
177
|
+
hash
|
178
|
+
end
|
167
179
|
files = create_profdata(binary_path, pathnames)
|
168
180
|
files.map do |source|
|
169
181
|
coverage_file = coverage_file_class.new(self, source, line_numbers_first)
|
170
182
|
# If a single source file is used, the resulting output does not contain the file name.
|
171
183
|
coverage_file.source_file_pathname = pathnames.first if pathnames.count == 1
|
184
|
+
# if there is segment data for the given path, add it to the coverage_file
|
185
|
+
if paths_to_segments.key?(coverage_file.source_file_pathname)
|
186
|
+
coverage_file.segments = paths_to_segments[coverage_file.source_file_pathname]
|
187
|
+
end
|
172
188
|
!coverage_file.ignored? ? coverage_file : nil
|
173
189
|
end.compact
|
174
190
|
end
|
@@ -277,7 +293,10 @@ module Slather
|
|
277
293
|
if self.arch
|
278
294
|
llvm_cov_args << "--arch" << self.arch
|
279
295
|
end
|
280
|
-
|
296
|
+
|
297
|
+
# POSIX systems have an ARG_MAX for the maximum total length of the command line, so the command may fail with an error message of "Argument list too long".
|
298
|
+
# Using the xargs command we can break the list of source_files into sublists small enough to be acceptable.
|
299
|
+
`printf '%s\\0' #{source_files.shelljoin} | xargs -0 xcrun llvm-cov #{llvm_cov_args.shelljoin}`
|
281
300
|
end
|
282
301
|
private :unsafe_profdata_llvm_cov_output
|
283
302
|
|
@@ -568,6 +587,19 @@ module Slather
|
|
568
587
|
def find_buildable_names(xcscheme)
|
569
588
|
found_buildable_names = []
|
570
589
|
|
590
|
+
# enumerate code coverage targets
|
591
|
+
begin
|
592
|
+
code_coverage_targets = xcscheme.test_action.xml_element.elements['CodeCoverageTargets']
|
593
|
+
targets = code_coverage_targets.map do |node|
|
594
|
+
Xcodeproj::XCScheme::BuildableReference.new(node) if node.is_a?(REXML::Element)
|
595
|
+
end.compact
|
596
|
+
buildable_names = targets.each do |target|
|
597
|
+
found_buildable_names.push(target.buildable_name)
|
598
|
+
end
|
599
|
+
rescue
|
600
|
+
# just in case if there are no entries in the test action
|
601
|
+
end
|
602
|
+
|
571
603
|
# enumerate build action entries
|
572
604
|
begin
|
573
605
|
xcscheme.build_action.entries.each do |entry|
|